Installing PHP on OS X for web development

There are a number of ways to install PHP as a part of apache on OS X. For a while I used MAMP and a couple of scripts to start and stop the processes and point htdocs to the current directory. Then I ran into a problem with MAMP’s PHP not supporting connections to MS SQL database. After attempting to reconfigure and rebuild PHP in MAMP and ended up coming across Liip’s package for installing PHP on Mac OS X. It’s simple to install and works.

I’m posting about Liip’s resource because I lost track of it and couldn’t find it to install on a new machine and realized that maybe it might be useful to some other PHP web developers out there. If nothing else, my link might increase their Google ranking, making it easier to find it next time I’m looking for it.

WordPress network on Dreamhost

WordPress, as of version 3.0, allows you to set up more than one site within the same installation. Each site uses the same core software and users can use the same credentials in all the sites they have access to across the network. Essentially, it allows you to set up a mini WordPress.com. Since I have a growing number of WordPress sites hosted at Dreamhost, I decided to set up a network of my own to reduce time upgrading and maintaining them and to simplify user management.

Also, I needed to move to secure (SSL encrypted) logins and admin areas. This is relatively easy to setup on a site-by-site basis, however, that would have meant a dedicated IP and SSL certificate for each site. With a WordPress network and domain mapping I can host websites at their own domain, but use one-centralized WP install, set of usernames and only one dedicated IP address and SSL certificate, securing all of the sites at the cost of one. Win-Win right?

I was a little wary of running the gauntlet and getting it all set up. Don’t be. It’s very easy, really. And you’ve got lots to gain by doing it. Here’s my instructions for getting a WP network set up on Dreamhost. The instructions would probably work on any other shared hosting with a couple changes. Let’s begin!

Things you’ll need

  1. A static, dedicated IP Address. (March 2011, costs $43.17 / year)
    This is required so that the mapped domains can default to your primary domain if the domain is not recognized. As a freebie it allows you to do secure logins and administration (highly recommended).
  2. Optionally, a yearly certificate. (March 2011, costs $15 / year)
    If you want to do secure login and administration and people other than you are accessing the system, having a legit certificate means that they don’t have to accept an ‘insecure’ certificate. The certificate from Dreamhost is cheap ($15) and means less fuss when people are using the admin area.

Step 1. Install WordPress

I’m assuming you’re familiar installing WordPress. If not, you can download the latest version and read installation instructions at WordPress.org.

Step 2. Setup the network

Follow the instructions on how to Create a Network. If, like me, you do not have a Dreamhost PS (Private Server), be sure to choose sub-directory type of network. This means that your primary site will be at example.com and the next sites would be at example.com/site2, example.com/site3 and so on. Without a Dreamhost PS you won’t be able to set up the sub-domain type network since it requires that Dreamhost manually add a wildcard apache directive, which they’re not wont to do for anyone, especially those without a PS account. A sub-directory network will actually work fine, you’ll just want to be installing a new site as your primary site, not converting a site that’s been round for more than a month as there could be collisions with the permalinks (there is a note about the reason for this in the link above). Since we’re planning on doing domain mapping anyway, sub-domains are not really necessary.

Step 3. Install the Domain Mapping Plugin

Installing WordPress MU Domain Mapping is relatively straightforward and there are lots of details about A and CNAME records on their site. You can go either way with A or CNAME records. I’m using A name records to get the mapping setup.

Step 4. Add the Static IP and (optionally) SSL Certificate

You need a dedicated IP address in order to get the network set up correctly. Without it, you can’t be guaranteed that your IP won’t change and you would also have issues with other domains on the same shared IP. The general idea is that WordPress will return the appropriate site if it recognizes the incoming domain name, if it doesn’t recognize it, then WP returns your primary site.

To add the static IP, login to the Dreamhost panel and go to your list of domains and click “Add IP” underneath the domain name. They’ll ask for some information and ask you to agree to the yearly or monthly charge. By default you’ll get a self-signed certificate which will make your site secure, but visitors will get an alert saying that the site is not trusted. To get a signed SSL certificate, you can purchase one from wherever you want, or from Dreamhost. Dreamhost’s is pretty cheap and no work at all to set up. As of March 2011, the signed certificate costs $15 / year.

After setting up the IP, you’ll want to make sure your primary domain’s DNS A record points to this new IP address. If you have the DNS for your primary domain hosted at Dreamhost you don’t have to worry about that.

Step 5. Mapping domain names

After you created a new (non-primary) site in your network, you’ll want to map that domain to the new WordPress site. In each site’s admin area under Tools you’ll find an option called Domain Mapping. That’s where you can enter the domain name so that WordPress knows about it.

You also have to edit the DNS for domain that you want to map and add an A record that points to your new static IP. Once the DNS propagates, WordPress should start responding for your new domain.

Update Otto has a good walkthrough setting up the Domain Mapping Plugin.

Step 6. Secure Login and Aministration

There are instructions on WordPress.org for setting up Administration over SSL. The conclusion is that you need to add the following lines to your wp-config.php file. Note that if the DNS change on your primary domain from a shared IP to a static IP hasn’t propagated, then this will lock up the admin area, so proceed accordingly.

[code]
define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);
[/code]

Speaking at WordCamp MSP, 2010

I’m going to be speaking at WordCamp Minneapolis 2010 on November 13.

My presentation is titled WordPress Off Road. I’m going to talk about integrating WordPress with a multi-faceted (non-WordPress) website. I will be introducing a PHP class called wp_posts for exporting WordPress posts, scripts I’ve developed for maintaining multi-site WordPresses and experiences setting up LDAP authentication.

Register now – I look forward to seeing you there!

Accessing IPInfoDB with a PHP class

I am working on an analytics tool and needed to pull info from the public IPInfoDb. You can get data for 1 – 25 IP’s at a time, and the data is returned as XML or JSON. I wrote a quick Library for PHP that accesses their data using the JSON format. It selects the correct query URL based on how many IP’s you give it.

Installation and Usage

First install the script at some PHP-accessible place, for example, /path/to/class/IPInfo.php. I would also set up autoloading classes to make things simpler. Here’s an example of pulling some information on either an individual IP or several. The class returns an associative array with IP’s for the keys and information arrays (containing city, region, country, latitude, longitude) as the value.

PHP
1
2
3
4
5
6
7
8
9
10
11
// include the class or use autoload instead.
require('/path/to/class/IPInfo.php');
// instantiate the class
$ipinfo = new IPInfo();
// option1
$oneIP = $ipinfo->getInfo('123.234.345.123');
// option2
$multipleIPs = $ipinfo->getInfo( array('123.234.345.123', '1.4.3.123') );

Download

Download the IPInfo class or copy / paste from below.

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?
/* class that grabs IP info based on a couple of IP's
using the IPInfo DB http://ipinfodb.com/
*/
class IPInfo {
function getInfo($ips) {
// expects either 1 IP or an array of ips.
if (!$ips) {
return false;
}
if (!is_array($ips)) {
$ips = array($ips);
}
//IP Info db allows multiple IP request in series of up to 25. so if there are more than one, hit the
if (count($ips)>1) {
$ips = array_map(array(&$this, "cleanIP"), $ips);
$ips = array_unique($ips);
$ip_chunks = array_chunk($ips,25);
$ipinfo = array();
foreach($ip_chunks as $ipch) {
$url = "http://ipinfodb.com/ip_query2.php?timezone=false&output=json&ip=".implode(',',$ipch);
$val = $this->makeRequest($url);
foreach($val['page']['Locations'] as $i) {
$ipinfo[$i['Ip']] = $i;
}
}
return $ipinfo;
}
else {
$url = "http://ipinfodb.com/ip_query.php?timezone=false&output=json&ip=".$this->cleanIP($ips[0]);
$val = $this->makeRequest($url);
$ipinfo = array("{$ips[0]}" => $val['page']);
return array("{$ips[0]}" => $val['page']);
}
}
function cleanIP($ip) {
return preg_replace('/[^0-9.]/','',$ip);
}
private function makeRequest($url) {
$referer = "http://".$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 3);
curl_setopt($ch, CURLOPT_REFERER, $referer);
$tries=0;
$page=false;
while( $page===false && $tries<= 5) {
$page = curl_exec($ch);
$tries++;
}
$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return array('page'=>json_decode($page,true), 'tries'=>$tries, 'httpcode' => $httpcode);
}
}
?>