Late Static Binding with PHP 5.3

October 6th, 2008

With the Alpha3 Release of PHP 5.3 out and about it’s looking like the much anticipated late static binding functionality is starting to solidify. Once I finally got PHP 5.3 running (see my previous post) I worked through creating an  ActiveRecord-like class to see if I could make a PHP object do act in a similar way  similar to Ruby’s Active Record.

Lets see where I ended up…

class ActiveRecord {
  public static function find($id){
    $called_class = get_called_class(); //a new function as of a2
    return new $called_class();
  }
  //A derived example to show the late static binding in action
  public static function testLSB(){
    return static::$table;
  }
}
class BasicModel extends ActiveRecord {
  public static $table = 'basicModel';
}
//Output examples
echo get_class(BasicModel::Find(1)); //Output - BasicModel
echo BasicModel::testLSB();          //Output - basicModel
echo BasicModel::$table;             //Output - basicModel
First place I saw the get_called_class() method was on the PHP Late Static Binding Manual Page

The above example is celarly a bit derived, but I’m quite excited at where this is heading. I still have a bit of work to do if I want to end up accessing all my models in the Rails/Active Record fashion.

$user = new User(1); //by passing a user id directly to the constructor
$user = User::Find(1); //by static::find();
$users = Users::FindAll(); //by static::findAL() returning an array of User objects.

I don’t see these requirements too difficult to achieve but it will require some trickery. The problem will lie if I decide to put all the database logic into static::Find(). If static::Find() returns a new instance of the class, and the constructor of each class blindly returns the results of a static::Find() call, it won’t work. The code below  doesn’t work because a constructor can’t return a new object instance and $this can’t be reassigned (like you can in some languages).

public function __construct($id){
 if (is_array($id)){
    $this->data = $id;
  }else{
    $this = static::find($id); //fatal error, can't reassign $this
    return static::find($id); //also won't do anything useful
  }
}

From fist impressions I think the idea of using is_array() to check if the $id parameter is a good way for static::Find() to pass an array to the constructor without ending up in a loop. This suggests that there needs to be a similar check inside static::Find() to return only an array in some cases instead of a new object.

So I’ve come up with this idea to solve the above issue.

public function __construct($id){
 if (is_array($id))
    $this->data = $id;
 else
    $this->data = static::find($id,true); //static::find() returns an array;
}
public static function Find($id,$returnArray = false){
  $foundResults = insert_SQL_function_here();
  if ($returnArray === true)
    return $foundResults; //return basic array
  else{
    $called_class = get_called_class();
    return new $called_class($foundResults);
  }
}

I’m not 100% convinced this is the best way to solve this. Ideally I’d like a solution that didn’t require the checks in __construct() and static::find(), but this is a start, and it’s a a reasonable exercise in using LSB.

Share this article:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • LinkedIn
  • DZone
  • Furl
  • Ma.gnolia
  • NewsVine
  • Reddit
  • Slashdot
  • StumbleUpon
  • Technorati

Installing PHP 5.3 on Mac OS X Leopard

October 6th, 2008

After many frustrating hours and three separate attempts I am finally running PHP 5.3.0alpha3 on my MacBook Pro using the default Leopard Apache installation (the one you can turn on/off with web sharing). This post is as much a summary for my own records as it is how-to to people in the same boat. I’d like to point out that I’m not very experienced with compiling software from source, and for some reason I was determined to utilise the default Leopard installation of Apache.

The problem with the whole process was the Apple compiled version of Apache runs at 64Bit, and at present it’s not possible to compile the  PHP 5.3 Apache module to be compatible. The solution is to cut the Apache binary back to run at 32Bit. That can be done quite simply and is explained by Tony Bibbs back in June with PHP 5.3 on Mac OS X 10.5.

Once you’ve cut Apache back to 32Bit, you just need to install MySQL. Before I read Tony’s post I went to all the effort of compiling MySQL 5.1RC in 64Bit, then found out that PHP wasn’t compatible with the 64bit. Installing a released version of MySQL is simple, and in my opinion not worth going through the effort of compiling from source (unless you need some special functionality). I just took the latest release from the MySQL download site and installed it (after removing numerious other versions first, see below).

After MySQL was running, I downloaded the latest snapshot of PHP 5.3 from snaps.php.net , extracted, then ran the following configure command.

./configure --prefix=/usr/local/php53 \
--with-apxs2=/usr/sbin/apxs --with-config-file-scan-dir=/usr/local/php53/php.d \
--with-iconv --with-openssl=/usr --enable-ftp --enable-sockets \
--enable-mbstring --enable-calendar --enable-bcmath \
--with-curl=shared,/usr/local/php53 --with-zlib-dir=/usr  \
--with-mysqli=/usr/local/mysql/bin/mysql_config

Note my use of –prefix=/usr/local/php53 – this was my choice, as I didn’t want it to potentially overwrite my php 5.2 installation that was there.

The important elements here are –prefix and –with-mysqli

Also – I’m not 100% on what –with-config-file-scan-dir does, but it caused no problems.

After configure succeeds I ran

sudo make

Then after a cofee/beer I ran

sudo make install

From what I could gather, the install procedure created the libphp5.so file inside the /libexec/apache2/ directory (overwriting the one that was previously there), and also added the ‘loadModule’ line within the apache config file @ /private/etc/apache2/httpd.conf. If I did this again, I would backup previous php libraries.

Finally, a sudo apachectl restart restarts the apache server and I was on my way.

Footnotes:

Here’s some locations I found useful

Apache’s Httpd.conf is @ /private/etc/apache2/httpd.conf

The APXS libraries are @ /usr/sbin/apxs

PHP & MySQL (by default) install to /usr/local/

MySQL

Throughout this whole trial and error process, I think I installed MySQL about three different times. Before finally just downloading the latest 5.0 release I took some steps to remove the previous installations. If you’ve installed MySQL many times (like I did) and you’re a bit conscious about having junk all over the place then best place to start looking for information on what’s installed where is the Readme.txt file that comes with the OS X package installer, and also the Mysql Installation notes for OS X

An article I found that also helped me search for some lost MySQL installs, and shed some light on what to do was this post titled Removing MySql – by Lee Hambly.

Share this article:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • LinkedIn
  • DZone
  • Furl
  • Ma.gnolia
  • NewsVine
  • Reddit
  • Slashdot
  • StumbleUpon
  • Technorati

Yaey new blog

September 25th, 2008

So its time to create a skin for this now, get some style!

Well at least you can all now read out political diatribe and random musings on web design and development!

Okay its not that exciting right now, but wait for it!

Going forward is fun eh.

Share this article:
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • LinkedIn
  • DZone
  • Furl
  • Ma.gnolia
  • NewsVine
  • Reddit
  • Slashdot
  • StumbleUpon
  • Technorati