WordPress Config Setup on Multiple Environments

Let’s say, you’re working on a WordPress project where you have your local machine, staging environment (environment setup which is the same as or close to production), and production environment (deployed to the world wide web).

WordPress has this config file: wp-config.php. The problem with this is you have to separately configure it between different environments. For example moving from local setup to staging setup, you can sync both folders directly and set the staging config file as read-only. But the problem with this is you have to separately update both the staging and production config files.

Looking around, I stumbled upon WordPress-Config-Bootstrap on GitHub. It uses an array map of the environment and its domain, simple but smart:

// Define Environments
$environments = array(
    'local'       => '.local',
    'development' => '.dev',
    'staging'     => 'stage.',
    'preview'     => 'preview.',
);

See the rest of the code here.

I forked it and came up with my own version where there are separate files for each environment. I think that it’s easier to maintain this way than compressing all the config variables for different environments in one file together.

The wp-config.php file will look like this:

// Define Environments here
// Update this according to your needs
$environment_map = array(
    'blog.yoursite.local' => 'local',
    'blog.yoursite.staging' => 'staging',
    'blog.yoursite.com' => 'production'
);

// Get Server name
$server_name = $_SERVER['SERVER_NAME'];

define('ENVIRONMENT', $environment_map[$server_name]);

define('ABSPATH', dirname(__FILE__) . '/');

$env_config = ABSPATH . sprintf('wp-config-%s.php', ENVIRONMENT);

// Terminate if file doesn't exist
// if(!file_exists(($env_config)))  exit("$env_config doesn't exist");

/** Sets up WP config based on environment. */
require_once($env_config);

This is the part that determines which config file to use:

$env_config = ABSPATH . sprintf('wp-config-%s.php', ENVIRONMENT);

You will need to create one config file for each environment e.g. wp-config-local.php, wp-config-production.php, etc.

See my forked version of WordPress-Config-Bootstrap.

Solution to Apache Web Server and VirtualBox NFS Mounted File Cache Problems

I have my VirtualBox installed on my Mac OS X Lion spinning a Virtual CentOS instance where my LAMP stack is running. This idea of a virtual server environment is really neat because it gives me the luxury to develop in a Linux environment close enough to my Linux setup in production. But I encountered a problem that seems simple but I couldn’t find an obvious solution – shared folder caching problem.

Every time I make changes in my JS/CSS files, it doesn’t get updated on the web page itself. I checked the file in the web server directory itself and it’s updated. But when I try to access it via its url, I couldn’t see the changes that I made. Which made me think that it has something to do with Apache and not VirtualBox.

After extensive googling and researching, I stumbled into these Apache directives:

The solution is to disable the above directives which are enabled by default. So basically we’re disabling memory mapping (EnableMMAP) which is not good when we’re working with NFS mounted files. We’re also disabling apache’s sendfile (EnableSendFile) support which basically reads static file from buffer or cache without reading the actual file itself.

Here’s how your configuration will look like:

<Directory "/path/to/document_root/">
# Some other directives here

EnableMMAP Off
EnableSendfile Off
</Directory>

I hope that it works for you and saved you from spending too much time finding out the solution.

Amazon S3′s PermanentRedirect and cURL error code 51 Problems

I’ve spent hours figuring out the cause of the errors I recently encountered in my build script. Part of my build script is to upload files to Amazon S3 using the AWS SDK for PHP 1.5.5. The tricky part was that it works on Mac OSX, remote Red Hat and CentOS servers, and in our company’s intranet CentOS. But it’s having problems in my VirtualBox CentOS setup. Here are the errors:

cURL error code
The exact error message:

PHP Fatal error:  Uncaught exception 'cURL_Exception' with message 'cURL resource: Resource id #81; cURL error: SSL: certificate subject name '*.s3.amazonaws.com' does not match target host name 'xxx.xxx.xxx.com.s3.amazonaws.com' (cURL error code 51). See http://curl.haxx.se/libcurl/c/libcurl-errors.html for an explanation of error codes.'

Possible cause:
SSL certificate is either too new or too old for this particular version of OpenSSL.

Solution:
Add this line:

$s3->path_style = true;

after the instantiation of the AmazonS3 class:

$s3 = new AmazonS3();
$s3->path_style = true;

PermanentRedirect
After I managed to solve the ‘cURL error code 51′ problem. I encountered another one, here’s part of the json response I get from AmazonS3:

  ["body"]=>
  object(CFSimpleXML)#17 (6) {
   ["Code"]=>
    string(17) "PermanentRedirect"
    ["Message"]=>
    string(137) "The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint."
    ["RequestId"]=>
    string(16) "xxxxxxxx"
    ["Bucket"]=>
    string(23) "xxx.xxx.xxx.com"
    ["HostId"]=>
    string(64) "xxxxx"
    ["Endpoint"]=>
    string(40) "xxx.xxx.xxx.com.s3.amazonaws.com"
  }
  ["status"]=>
  int(301)

Possible Cause:
Endpoint or location is not specified.

Solution:
Specify the endpoint/location based your server’s current location. In my case, my VirtualBox is in Singapore.
Singapore is in South East Asia, so I just need to add this line in between the instantiation and set_region call:

$s3->set_region(AmazonS3::REGION_APAC_SE1);

Final code will look like:

$s3 = new AmazonS3();
$s3->set_region(AmazonS3::REGION_APAC_SE1);
$s3->path_style = true;

Installing modules for a specific Python version in your Mac OSX Lion

Note: I am using Mac OSX 10.7.3 with XCode 4.3.2

I came across this problem lately where I need a certain module to run a script that is only compatible with Python 2.6. My default Python version is 2.7. So if I install using easy_instal, the system will install the module for Python 2.7 only. So in this case, when I run Python 2.6, I don’t have the module that I just installed. Then I found out how easy it is to do it.

In your mac, you have multiple versions of Python installed:

$ cd /System/Library/Frameworks/Python.framework/Versions
$ ls
$ 2.3     2.5     2.6     2.7     Current

Which means that you also have multiple version of easy_install. So if you type easy_install and ‘double tab’. You will get:

$ easy_install
$ easy_install      easy_install-2.5  easy_install-2.6  easy_install-2.7

This represents easy_install for each version.

The obvious conclusion is:
e.g. If you want to install a module for a Python 2.6:

$ sudo easy_install-2.6 <modulename>

Simple Comet Implementation Using PHP and jQuery

I have been researching about the Comet application model recently. I stumbled upon a great article from Zeitoun.net in which their AJAX implementation example is written in PHP and ProtoType (a JavaScript Framework). I decided to modify the Classic AJAX/ProtoType Implementation to use  jQuery – my JavaScript framework of choice thus far. This is only the client side of the entire architecture when you’re dealing with huge databases and web services but at least this gets you started.

We’ll be using 3 files here:

  • backend.php
  • data.txt
  • index.html

Both backend.php and data.txt stayed the same as the original example. I only modified index.html’s JavaScript block to look  like this:

var Comet = function (data_url) {
this.timestamp = 0;
this.url = data_url;
this.noerror = true;

this.connect = function() {
var self = this;

$.ajax({
type : 'get',
url : this.url,
dataType : 'json',
data : {'timestamp' : self.timestamp},
success : function(response) {
self.timestamp = response.timestamp;
self.handleResponse(response);
self.noerror = true;
},
complete : function(response) {
// send a new ajax request when this request is finished
if (!self.noerror) {
// if a connection problem occurs, try to reconnect each 5 seconds
setTimeout(function(){ comet.connect(); }, 5000);
}else {
// persistent connection
self.connect();
}

self.noerror = false;
}
});
}

this.disconnect = function() {}

this.handleResponse = function(response) {
$('#content').append('
<div>'
+ response.msg + '</div>
'
);
}

this.doRequest = function(request) {
$.ajax({
type : 'get',
url : this.url,
data : {'msg' : request}
});
}
}

var comet = new Comet('./backend.php');
comet.connect();

For more details, check out the article where I based this from. Happy hacking!

jQuery Comet on GitHub

Download:

Thoughts, moving on to mig33

Another chapter of my career is starting to unfold. After working at Yolk for 8 months, I’m moving on to mig33. My new job will commence on 17th October, 2011; which also roughly marks my 3rd year working and living in Singapore.

Father time is indeed deceiving, how he passes by so fast without noticing him. I can vividly remember my first day at my first job in Singapore when I was looking for muvee‘s office, getting lost, going to City Hall instead of Bugis. Until I finally found the office, I was then warmly welcomed by two great engineers/colleagues who inspired me (Tim and Tjerk).

Now I’m very excited to start a new job again. I’m gonna be working on exciting projects that has over 50 million users, which is something new for me. It’s about time to study and work on technologies like Hadoop, Memcached, Redis, and MongoDB. Then get my skill levels up on Python. Also, I’ll sharpen my OOP and Design Patterns knowledge.

mig33 will be my 3rd company in Singapore. I feel very blessed to be able to work again with great ex-colleagues: Tim and Ali. Good luck to me. :D

Fibonacci in Python compared to C-style Languages

I have played around with Python these past few months. Learning Python will make you realize some of the not so good things about PHP and other similar C-style Languages. But I’m not going to delve into their comparison, you can find a good article about that subject here.

What got me intrigued is how I was able to implement the classic Fibonacci function in Python without having to use an extra variable that should be present in both PHP or Javascript implementation.

First I’ll show you how it is implemented in both JavaScript and PHP:

JavaScript: (Copy and run in your browser’s JS console to see it in action now!)

<script type="text/javascript">
function fib(n)
{
    var a = 0, b = 1;
    while(b < n) {
        console.log(b);
        sum = a + b;
        a = b;
        b = sum;
    }
}

fib(60);
</script>

PHP:

<?php
function fib($n)
{
    $a = 0, $b = 1;
    while($b < $n) {
        echo $b . PHP_EOL;
        $sum = $a + $b;
        $a = $b;
        $b = $sum;
    }
}

fib(60);
?>

You’ll notice that both JavaScript and PHP use the following variables: n, a, b, and sum. Variable n will be the size or the limit of the series while a, b and sum are there to help determine what numbers to display.

Now it’s Python’s turn:

def fib(n):
    a, b = 0, 1
    while(b < n):
        print(b)
        a, b = b, a + b
       
fib(60)

For Python, it doesn’t need to use the extra variable sum. This is because you can assign variables simultaneously in Python just like in Ruby and Perl.

This is one of those little things that we might overlook when building applications. Yes, we only saved one variable in this Fibonacci function. But how much more when we build more complex applications? When we’ll need to strategically assign variables in large and scalable applications?

Implementing Inheritance for jQueryUI Dialog Boxes

First of all, nothing fancy here. Just want to show you a good way to implement Inheritance on jQueryUI Dialog Boxes. Here is one way to take advantage of Javascript’s Inheritance capability. We can use inheritance for jQuery UI dialog boxes – e.g. we have the parent ‘DialogBox’ which will have the basic properties like width, height, border colour, border thickness, close box, etc. Then all these basic properties of the parent ‘DialogBox’ will be inherited by its children classes like ‘MessageBox’, ‘LoginBox’, ‘EditBox’, and ‘UploadBox’. These children classes will have its own unique properties as well. Which will make the implementation look like this:

var dbox = new StatusMessageBox('message here..'); // this will initialize the message dialog box
dbox.render(); // this will render the message dialog box

Time to dissect the classes. Let’s start with the parent class ‘DialogBox’ – this is where all the basic and common properties will be set. Please refer to the code comments for more details:

var DialogBox = function(properties, attr) {
this.properties = properties;
this.attr = attr;
}
DialogBox.prototype.preRender = function() {
// do something before rendering the dialog box
}
DialogBox.prototype.postRender = function() {
// do something after the redering the dialog box
}
DialogBox.prototype.render = function(appendElt) {
//this.preRender(this.dialogContent);

var appendElt = (appendElt) ? appendElt : $('#container');
var self = this;

var defaultAttr = {
'class' : 'dialog_box'
};
var defaultProperties = {
'title' : 'Message',
'width' : '350',
'height' : 'auto',
'modal' : true,
'resizable' : true,
'buttons' : {
'OK' : function() {
$(this).dialog('close');
}
},
'open' : function() {
self.postRender();
},
'beforeClose' : function() {
//$(this).dialog('destroy');
}

};

// overwrite the default properties and attributes if necessary
$.extend(defaultProperties, this.properties);
$.extend(defaultAttr, this.attr);

// create the element
var dialog = $(document.createElement('div')).attr(defaultAttr);

this.dialogContent.appendTo(dialog);

// append the box to the parent element
dialog.appendTo(appendElt);

// apply the dialog box properties
dialog.dialog(defaultProperties);

 // make this accessible outside
this.dialogObj = dialog;
}

As you can see, the base class is setting up the possible common properties among dialog boxes. Let’s move on to the ‘StatusMessageBox’ class below. This type of dialog box will prompt for messages e.g. error or success messages. You can initialize its message property which will set the message to be prompted by the message box. ‘StatusMessageBox’ is also inheriting its basic properties from its parent: ‘DialogBox’.

/**
* Display simple status message
*
*/

var StatusMessageBox = function(msg) {
// create the dialog box content
var defaultMsg = (msg) ? msg : 'default message';
this.dialogContent = $(document.createElement('p')).html(defaultMsg);
}
/**
* inherit from DialogBox
*/

StatusMessageBox.prototype = new DialogBox();
StatusMessageBox.prototype.constructor = StatusMessageBox;

Concept is the same with the rest of DialogBox’s children like: ‘LoginBox’, ‘EditBox’, and ‘UploadBox’. Please take note that ‘UploadBox’ in the demo is dependent on uploadify and swfobject.

Suggestions and ideas for improvement will be greatly appreciated.

Time to play:

The class itself.
Live demo.

Fix for pinify’s createThumbbarButtons function bug

If you are using pinify‘s createThumbbarButtons function, and you got stuck finding ways to make it work. Then this article is for you. I’m dealing with jQuery pinify version 1.2 here.

First of all, they did a great job with pinify – it makes life easier for web developers who want or who are required to make use if IE9′s browser pinning feature. My task was to implement thumbnail preview controls in one of the sites I’m working on.

After diligently following the documentation and pinify’s example, I found myself stuck in getting it to work. Until I finally decided to dissect jquery.pinify.js. I looked for the createThumbbarButtons function and I found it with a try/catch statement. With catch statement left empty, I inserted console.log(‘createThumbbarButtons error: ‘ + e.description); under the catch(e) declaration. It ended up spitting a “Object doesn’t support property or method ‘addEventListener’” error.

Stupid IE as usual, it’s having problems with addEventListener. This error is caused by document.addEventListener(‘msthumbnailclick’, clickCurrent, false); which is only found within the createThumbbarButtons function. The solution is to replace the addEventListener statement with a good old jQuery bind:

$(document).bind(‘msthumbnailclick’, clickCurrent);

Update: Okay, the correct solution for this is to add the following tag within your head tag:

<meta http-equiv="X-UA-Compatible" content="IE=9" />

This will force the browser to use IE9 compatibility mode if it is available. And this will recognize addEventListener without any errors.

Finally it worked. =)

A weird PHP behavior

This post about the oddity on how PHP converts float to integer. This is not new to most of the PHP geeks out there, but I just want to point this out to those who are not aware of this yet. You may or may not tackle this in the future, but it’s worth knowing about.

See the PHP code below:

echo (int)((0.7 + 0.1) * 10);

At first look, what’ll come to your mind is that the output will be ’8′. But that’s not the actual output. If you’ll try to run it – the output is ’7′.
That’s not all, try:

echo (int)((0.6 + 0.1) * 10);  //outputs 7
echo (int)((0.8 + 0.1) * 10); //outputs 9

See the result? Okay, so that sums it up. ;)