on May 23rd, 2008New anti-spam commenting solution

From now on your comments should appear right away when you post them, but you will be required to have javascript enabled to post. If you can’t post a comment for some reason (other then not having javascript enabled), please email me.

on May 23rd, 2008Exceptions, you’re doing it wrong

Edit: After a couple of comments and some personal pondering I decided to remove a small part of the article, if you read it before and think something is missing, then you know why.

Once again a post aimed at the PHP community, not so much of a rant but more of something I’ve seen done horribly wrong in a lot of PHP code recently, first let me take a few examples from a couple of well known PHP frameworks and libraries:

symfony, file: lib/database/sfMySQLDatabase.class.php

$error = 'Failed to create a MySQLDatabase connection';
throw new sfDatabaseException($error);

propel, file: runtime/classes/propel/util/BasePeer.php

throw new PropelException("Expecting to delete 1 record, but criteria match multiple.");

doctrine, file: lib/Doctrine/Connection.php

throw new Doctrine_Connection_Exception('First argument should be an instance of
PDO or implement Doctrine_Adapter_Interface');

I could go on and on and list a couple of hundred of these from each of most poplar PHP libraries, and they all make the same assumption: An exception is a fatal error. And by making this assumption and using one monolithic “DatabaseException”-class, it becomes impossible to handle the exceptions in any other manner then as a fatal errors.

For example the first snippet, coming from the symfony framework is thrown when you can’t connect to a database. Since every other error that can happen to any database connection done in symfony also throws a “sfDatabaseException” how is the user of the library supposed try a backup database or supply a custom “database is down”-error page ? By regex:ing the message of the thrown exception?

Exceptions are not, and I repeat not, a fatal error mechanism (they can be, sure - but it’s not their only or primary use). Taken the above symfony code again, it should look something like this:

throw new DatabaseConnectionFailedException('MySQL');

Or something along those lines, making it possible to somehow distinguish between different type of exceptions allows us to do something like this (again assuming the symfony code):

try {
         // Try to connect to a database

} catch (DatabaseConnectionFailedException $e)  {
         // Try backup database

} catch (DatabaseException $e) {
         // Generic database error
}

So, to sum it up:

Exceptions, you’re doing it wrong!

on May 19th, 2008pySX: Simple XML processing in Python

pySX is my latest hobby project. It’s a very simple XML library that aims to simplify the process of handling XML as much as possible. The code can be found here: http://svn.loveandtheft.org/fredrik/pysx. Here are a couple of quick usage examples:

“Manual”

When accessing an element, two things can happen:

  • You get a list back, which means that there are more then one element with that name
  • You get an object of type pysx.node.Element back, which means there’s only one element with that name

Examples

Loading an xml hierarchy

import pysx
tree = pysx.handler.parse('users.xml')

Iterating over a collection of elements

for user in tree.root.users:
     print user.name
     print user.age
     print user.get_child('pysx:age') # Also under it's namespace

Accessing the n:th element

print tree.root.user[0].name

Accessing attributes

print tree.root.user['id']
print tree.root.user['pysx:id'] # namespaced

Replacing an element with another one

# replaces the first <user> with a <admin>
print tree.root.user[0].replace_self(pysx.node.Element(qname = 'admin'))
print tree.root.admin.name

Removing an element

tree.root.admin.remove_self()

on May 17th, 2008Secure your mysql_* in two minutes

If you’re still using the mysql_* functions in php instead of PDO or some other more advanced db library (propel, doctrine) there’s one big favour you can do yourself, stop using mysql_query() and use this function instead:

<?php
function mysql_squery ($sql) {
	$args = array_slice(func_get_args(), 1);
	$args = array_map('mysql_sescape', $args);
	return mysql_query(sprintf($sql, $args));
}

function mysql_sescape ($value) {
	if (is_string($value)) {
		$value = mysql_real_escape_string($value);
	}
	return $value;
}

Usage is very simple, here are a couple of demo statements:

// Inserting a row
$name = "Fredrik";
$age = 23;
mysql_squery("insert into users (name, age) values('%s', '%s')", $name, $age);

// Updating a row
$name = "Fredrik Holmström";
$id = 1;
mysql_squery("update users set name = '%s' where id = %s", $name, $id);

// Selecting 10 users
$query = mysql_squery('select * from users limit %s, %s', 0, 10);
while($row = mysql_fetch_assoc($query)) {
    echo $row['name'];
}

// Deleting a row
$id = 2;
mysql_squery('delete from users where id = %s', $id);

This will make your SQL-queries a lot more secure vs. something called SQL injections.

on May 14th, 2008Conventions and Consistency

When you’re developing a software, there are two golden rules that you always should follow: Use standard conventions and always be consistent. This applies for everything from naming to directory structure and documentation.

There is nothing more horrible then having to go back and maintain code that don’t follow any conventions nor is consistent.

on Apr 11th, 2008DO/DM Part2: LazyLoading, EmbeddedValue and some more…

Welcome traveler, to the second part in my Domain Object / Data Mapper guide & how-to & tutorial, this time we’re going to look at a more sophisticated implementation of the Data Mapper pattern that automates a lot more functionality - but we have to pay a price in complexity for that automation. We’re also going to look at a few new concepts: Lazy Loading, Embedded Value, A smarter insert/save() and possibly some Inheritance Mapping. As with the previous part the first thing you should do is to download this .zip-file containing all the classes and examples used in this article..

The first thing we should look up is the data_mapper_part2/lib/DataMapper.php file. Now if you remember the last DataMapper class used in my previous post, it was quite short; just one line - this DataMapper is a whole other beast; it weights in at about 230 lines of code including comments. Now, why have I done this? The previous class was so simple. Well, this is done mostly to give you more of a “real world” example of a proper Data Mapper that actually could be used in a real application (well almost), it also automates some things we had to do by hand, the mappers are not static anymore to allow for proper inheritance and we got a couple of convenience methods for working with our PDO-connection. So, assuming you’ve opened the DataMapper.php file by now, let’s start dissecting it - first up are our precious properties:

  • static $mappers - An array of all our instantiated mappers
  • static $dbconn - Our database connection
  • static $modelpath - The path where we can find our data mappers and domain objects
  • $domclass - DomainObject class for this mapper, DataMapper::__construct() tries to auto-resolve this from it’s own class name if we don’t overload it turning “PostMapper” into “Post”, etc.
  • $pkey - The primary key table field for this mapper
  • $table - The table name for this mapper, DataMapper::__construct() tries to auto-resolve this from it’s $domclass field if we don’t overload it in sub-classes, turning “Post” into “posts”
  • $map - Holds our IdentityMap object (also new for this part) that takes care of all object identities
  • $findstmt - A prepared PDOStatement that is created in DataMapper::__construct() and used by DataMapper::find() to achieve an automatic find()-method that works for subclasses
  • $deletestmt - A prepared PDOStatment that we created in DataMapper::__construct() to allow for an automatic delete()-method that works for all subclasses

After the properties, comes the methods - let’s skip the talk and get right to business:

  • static setConnection($dbconn) - Sets the database connection all the mappers use
  • static setModelPath($path) - Sets the path where we can find all our Data Mappers and Domain Objects
  • static getMapper($name) - Retrieves a mapper of $name type
  • static protected loadMapper($name) - Called by getMapper()-internally to load a mapper if it doesn’t exist
  • find($id) - Retrieves an object by primary key value (id) and returns it, using the $findstmt-prepared statement
  • save($obj) - Saves an object, calling either update() or insert() depending on if it’s an old or new object
  • delete($id) - Takes either and $id or an Domain object instance and deletes the row representing it in the database, using the $deletestmt-prepared satement
  • protected __construct - Constructor, tries to autoresolve the table name and domain object class name if they’re not overloaded in the subclass, also creates the IdentityMap object and puts it in the $map-field, last it sets up the two prepared statements $findstmt and $deletestmt used by find() and delete()
  • protected lastAutoincrementId() - Convenience method that returns the last auto-increment id
  • protected prepareExec($sql, $params) - Convenience method that takes an $sql string and $parameters creates a statement out of them and executes it, returning the statement
  • protected fetchAll($sql, $params) - Convenience method that returns all rows matching $sql with $parameters
  • protected fetchFirst($sql, $params) - Convenience method that returns the first row matchin $sql with $parameters
  • protected createObject($row) - Called internally to create an object from a $row, checks if the $row already has an $object in $map and returns that if so, if not it calls buildObject() with the $row and a fresh instance of our domain object ($domclass) class for this mapper
  • abstract protected update($obj) - Updates an object row in the database, overload in subclass
  • abstract protected insert($obj) - Inserts an object row into the database, overoad in subclass
  • abstract protected populateObject($row, $obj) - Populates $obj with fields from $row, overload in subclass

Phew *wipes forehead*, that’s all of them - this is starting to look more like an API documentation project then something about Data Mappers, so let’s get onto business. As you can see from the wall of text above explaining the properties and methods, we not have our find() and delete() methods *auto-magically* for every subclass of Data Mapper, so let’s wipe the PostMapper and UserMapper from the last part clean and just implement populateObject(), update() and insert() for them. That gives us complete CRUD (Create, Retrieve, Update and Delete) functionality from our mappers with just three methods. Open up models/UserMapper.php and let’s have a look at our three new methods. First out is UserMapper::populateObject() which is… simple, to say the least:

function populateObject (array $row, DomainObject $user) {
	$user->setName($row['name']);
}

Our 230-lines long DataMapper-class takes care of everything else, even setting the $id-property of the User, so the only thing we need to do is to set it’s name since this can’t be figured out automatically from mapper (or well, it can - but our mapper is to simple to do it at the moment), there’s not even any need to return the $user object.

The update() and insert() methods look pretty much alike, so we’ll look at them side by side:

protected function update (DomainObject $user) {
	$sql	= sprintf('update `%s` set `name` = ? where `%s` = ?', $this->table, $this->pkey);
	$stmt	= self::$dbconn->prepare($sql);
	$params	= array($user->getName(), $user->getId());

	$stmt->execute($params);
}

protected function insert (DomainObject $user) {
	$sql	= sprintf('insert into `%s` (`name`) values(?)', $this->table);
	$stmt	= self::$dbconn->prepare($sql);
	$params	= array($user->getName());

	$stmt->execute($params);
}

The first three rows in both update and insert are almost identical, we create a sql statement using the $table and $pkey properties, then prepare it using our $dbconn object and then setup the parameters, the update() method requires two parameters - first the name fields new value and then the object id, while insert only requires the name. That’s all there is to update() and insert() thanks to our clever base class DataMapper, let’s look at the DataMapper::save() method closer, here it is (without comments):

function save (DomainObject $obj) {
	if ($this->map->hasObject($obj)) {
		$this->update($obj);
	} else {
		$this->insert($obj);
		$obj->setId($this->lastAutoincrementId());
		$this->map->add($obj);
	}
}

As you can see save() first checks to see if the $map already has the object in it, if it does update it and be done. If the map doesn’t have the object, insert it and then set it’s Id to the lastAutoincrementId, and then add it to the map. Lets try this out in practice, I present to you listing1.php:

<?php
require	'bootstrap.php';
$userMapper = DataMapper::getMapper('User');

$yoda = new User;
$yoda->setName('Yoda');
var_dump($yoda->getId()); // NULL

$userMapper->save($yoda);
var_dump($yoda->getId()); // int(1)

$userMapper->save($yoda);
var_dump($yoda->getId()); // int(1)

First we just require boostrap.php that setups and requires all classes we need, next we retrieve the $userMapper with the static DataMapper::getMapper()-call. Secondly we create a new User, name it Yoda and save it with save() on $userMapper, now since this is a new object it won’t have an Id or be in the IdentityMap contained in $userMapper so it will call insert() this time creating the row and then assign the newly created auto-increment id to $yoda, var_dump():ing $yoda->getId() proves that the id has been set and the object is in the database, calling save() on $yoda will cause update() to trigger instead updating the row in the database.

Lazy Loading

So far everything we’ve been doing has just been a more abstract and enhanced version of what we did in part one, so let’s step it up a notch and do some Lazy Loading. If you remember in the first part where the PostMapper::findAll() method caused the User for each post to be loaded also, sometimes this isn’t optimal - so we’re going to introduce something called lazy loading that only loads the user object when we access it. Let’s have a look at the PostMapper::populateObject() method that we use to create a Post object:

function populateObject (array $row, DomainObject $post) {
	$post->setText($row['text']);
	$post->___lazyLoadSet___('user', $row['user_id']);
}

The first row looks familiar from part one, the second row is a bit weird tho, we call a method called ___lazyLoadSet__(), this is in fact just a “back door” method defined in DomainObject that lets us set an object property without going through the accessor-methods. If you remember the setUser() method required a User object, and since we’re giving it an integer here (the user_id) it would fail, there are other ways around this “issue” but this is the one that is most easily explained - and for the record, the DomainObject::___lazyLoadSet___ method looks like this:

function ___lazyLoadSet___ ($field, $value) {
	$this->$field = $value;
}

For this to work we have to modify the Post::getUser() method a bit, so it will check if the Post::$user property is an object or not, and if it’s not try to load the object that should be there in it’s place - here’s how it looks:

function getUser () {
	if (is_numeric($this->user)) {
		$this->user = DataMapper::getMapper('User')->find($this->user);
	}
	return $this->user;
}

A very simple modification of the old getUser() allows it to check if $this->user is a numeric value (not a User object) and if it is it replaces the numeric value with the real User object that should be there - but the key here is that it only happens when you access the getUser() method of the Post object, if you don’t access it the user will never be created

Before we put this all into motion I want to show two last methods, namely PostMapper::update() - since the Post is not guaranteed to always have the User object that is associated with it (for example if we load a Post, just change it texts and then save() it back again, the user will never be created) the update() method needs to be able to handle this (PostMapper::insert() looks exactly like the old PostMapper::insert() from part one except that it uses our new IdentityMap object, insert() always needs a proper User object so it can call getUser() without caring) without loading the User object from the database by calling getUser() immediately, for this we have another “magic” method called DomainObject::___lazyLoadGet___ that is the counterpart of ___lazyloadSet___ that allows us to retrieve a value without going through the get()-accessor method for it, it looks like this:

function ___lazyLoadGet___ ($field) {
	return $this->$field;
}

So, with this method ready at hand let’s go and take a look at PostMapper::update() (without comments):

protected function update (DomainObject $post) {
	if ($post->___lazyLoadGet___('user') instanceof User) {
		$user = $post->getUser();

		$userMapper = DataMapper::getMapper('User');
		if(!$userMapper->map->hasObject($user)) {
			$userMapper->save($user);
		}

		$userid = $user->getId();
	} else {
		$userid = $post->___lazyLoadGet___('user');
	}

	$sql	= sprintf('update `%s` set `text` = ?, `user_id` = ? where `%s` = ?', $this->table, $this->pkey);
	$stmt	= self::$dbconn->prepare($sql);
	$params	= array($post->getText(), $userid, $post->getId());

	$stmt->execute($params);
}

Ok, don’t be afraid - it won’t bite, let’s go through it line by line. At the top we call our ___lazyLoadGet___ method that retrieves the user property of the Post object, without triggering the autoload of getUser(), and we check if it’s an instance of the User class, if it is we retrieve it normally with getUser() and then get a hold of the $userMapper also. After that we check if the $userMapper’s identity map has the $user object in question, if it doesn’t we save() it. Next, get the id from the $user object. The else clause next is for if the ___lazyLoadGet___ call returns an value that isn’t a User object, so we just fetch it again and be on our way since it’s the user id we need. The rest of the method should be self explanatory by now so I’ll leave that for you to figure out.

So, let’s put this into motion - first let’s start with creating a few posts on our users, this is exactly the same thing we did in listing4.php in the first part: Getting an old user, creating a new and assigning one post each to them and then saving all of it to the database, so it should need no further explaination, listing2.php:

<?php
require	'bootstrap.php';
$userMapper = DataMapper::getMapper('User');
$postMapper = DataMapper::getMapper('Post');

$yoda = $userMapper->find(1);
$yodasPost = new Post;
$yodasPost->setUser($yoda);
$yodasPost->setText('Fear is the path to the dark side. Fear leads to anger.
Anger leads to hate. Hate leads to suffering.');

$hansolo = new User;
$hansolo->setName('Han-Solo');
$hansPost = new Post;
$hansPost->setUser($hansolo);
$hansPost->setText("Had a slight weapons malfunction, but everything's perfectly
alright now. We're fine, we're all fine, here, now, thank you. How are you?");

$postMapper->save($yodasPost);
$postMapper->save($hansPost);

So, as I said - almost identical to listing4.php in part one - no further explanation needed. Let’s have a look at listing3.php instead, here we retrieve all our posts with the findAll() method on PostMapper, then var_dump:ing them to show that the users are not loaded until we actually call getUser() on the Post object, listing3.php:

<?php
require	'bootstrap.php';
$postMapper = DataMapper::getMapper('Post');

$allPosts = $postMapper->findAll();
var_dump($allPosts[0], $allPosts[1]);

echo $allPosts[0]->getUser()->getName();
echo $allPosts[1]->getUser()->getName();

The var_dump() will print something like: object(Post)#6 (3) { ["text:protected"]=> string(101) "Fear is the path to the dark side. Fear leads to anger. Anger leads to hate. Hate leads to suffering." ["user:protected"]=> string(1) "1" ["id:protected"]=> int(1) } object(Post)#7 (3) { ["text:protected"]=> string(136) "Had a slight weapons malfunction, but everything's perfectly alright now. We're fine, we're all fine, here, now, thank you. How are you?" ["user:protected"]=> string(1) "2" ["id:protected"]=> int(2) }

But when we call getUser() on post #0 and #1 it will fetch the correct user object “behind the scenes” and return it instead, so we can chain getName() on there and get the expected result: YodaHan-Solo. One thing bugs me here, shouldn’t we be able to fetch all posts that are related to a User from that User object itself? Yeah we should! This requires two new methods, first: findByUser() on PostMapper and then getPosts() on User, you can look up PostMapper::findByUser() by yourself since it should (by now) be self explanatory and we’ll only look on User::getPosts() here.

function getPosts () {
	if (is_null($this->posts)) {
		$this->posts = DataMapper::getMapper('Post')->findByUser($this);
	}

	return $this->posts;
}

Looks quite a lot like Post::getUser(), basically all we do is to check if $this->posts is null, if it is replace it with the posts that have this User as their author. And that’s all there is to it, except the PostMapper::findByUser()-method. Let’s try it out, I present listing4.php:

<?php
require	'bootstrap.php';
$userMapper = DataMapper::getMapper('User');

$yoda = $userMapper->find(1);

foreach($yoda->getPosts() as $post) {
	echo '<p>', $post->getText(), '</p>';
}

A very simple piece of code, we retrieve $yoda which we know have Id 1 since earlier, then we just call $yoda->getPosts() and that will return all posts he has made and we loop through them, and it does indeed print something looking like this: <p>Fear is the path to the dark side. Fear leads to anger. Anger leads to hate. Hate leads to suffering.</p>, of course if you’ve inserted more posts for $yoda by refreshing listing2 all posts will print. That’s all I have to say about Lazy Loading for today - now it’s time for another subject that is at least as interesting but a bit easier on the brain.

Embedded Value

For this part of the article you will need a new .zip-file archive containing the updated files, it’s basically a clone of the previous archive without it’s examples and with the modified files required for these examples, you can find it here.

So, what are embedded values? Well, embedded values are objects that are represented by a field in a table - for example Date, Money, Temperature, etc. These fields often need to be objects but they don’t require their own table. Embedded Value is a design pattern that wraps this type of logic into an object that then is wrapped around a table field. Let’s create an EmbeddedDate (Can’t use Date as a class name since it already exists in PHP) class that wraps a unix timestamp:

<?php
class EmbeddedDate {

	protected $value = 0;

	function __construct ($value = 0) {
		$this->set($value);
	}

	function get () {
		return $this->value;
	}

	function getFormated ($format = 'Y-m-d H:i:s') {
		return date($format, (int)$this->value);
	}

	function set ($value) {
		if (is_numeric($value) or is_int($value)) {
			$this->value = (int)$value;

		} elseif(is_string($value)) {
			$this->value = strtotime($value);
		}
	}

	function __toString () {
		return $this->getFormated();
	}

}

An equally simple class, getFormat() formats the date we have while set() allows you to either input a string date, such as “2008-03-24 18:00″ or a numeric/integer date as a timestamp and get() returns the timestamp, __toString prints the default formated date. Let’s go ahead and add a new field to the User domain object called lastlogin that tells us when a user last logged in, this requires two new methods: User::getLastLogin(), and User::setLastLogin(), we also need to Modify our UserMapper::buildObject(), UserMapper::update() and UserMapper::insert() methods to accommodate for the changes in the User-object, as well as updating the users table in the database. The User-object methods look like this:

function getLastLogin () {
	return $this->lastlogin;
}

function setLastLogin (EmbeddedDate $lastlogin) {
	$this->lastlogin = $lastlogin;
}

The UserMapper::populateObject() method is changed so that we add one more line, looking like this: $user->setLastLogin(new EmbeddedDate($row['lastlogin'])); do accommodate the changes med to the User-class and users table, the insert() and update() methods just change their SQL and $params array to allow for one more field - should be self explanatory - let’s try this out in an example, I give you listing5.php:

<?php
require	'bootstrap.php';
$userMapper = DataMapper::getMapper('User');

$bobbafett = new User;
$bobbafett->setName('Bobba Fett');
$bobbafett->setLastLogin(new EmbeddedDate(time()));

$userMapper->save($bobbafett);

A rather straightforward example, we create a new user called Bobba Fett and assign a new LastLogin date to it which points to the current time() and then save it, so let’s retrieve it and see to that everything works:

<?php
require	'bootstrap.php';
$userMapper	= DataMapper::getMapper('User');

$bobbafett = $userMapper->find(3);
printf('%s last logged in: %s', $bobbafett->getName(), $bobbafett->getLastLogin());

An even shorter example, we retrieve the user with id 3 (Bobba Fett, Yoda is 1 and Han-Solo 2) and then print out his name and when he was last logged in (feeding the EmbeddedDate-object that is returned by getLastLogin() directly to printf() works because of the __toString()-method that we have defined in EmbeddedDate) the output should be something resembling this: Bobba Fett last logged in: 2008-04-11 17:21:41. If you get a warning about the systems timezone settings it’s because you’re running E_STRICT in php5+.

That will be all for today folks, getting tired here - how to map inheritance and many-to-many relationships is left for the third and maybe fourth part of this series, enjoy!

on Apr 7th, 2008DomainObject and DataMappers

Update: Part2 Now Available

(The first thing you should do is to download this file: data_mapper.zip, it contains all the files for this article and I will sometimes refer to files within the archive since some examples are to long to put in the article. This article also assumes that you’re fluent in SQL, know how to work with PDO (php.net/PDO) and have decent understanding of object oriented concepts)

Today we’re going to dive into the beautiful world of data mappers, what are they? How do they work? Why should you use them? Let’s start at the beginning, you know relational databases – those nifty tools you use to save information in a (hopefully) structured way so it’s easy to search, index and do various other things with. Now, databases are very good at what they do there’s no arguing that, and querying them from PHP is as easy as it’s ever been with at least two different APIs to choose from for each database driver that’s supported.

However, problems arise when we want to apply different business rules to our data that is store in a relational database – one solution is to use stored procedures, but you can only fit so much logic into those before it gets to cumbersome. After stored procedures we have functions, yes – simple php functions that usually look something like this:

<?php
function update_user_name($id, $name) {
    // Do something to the users row in the database
}

However these functions have several drawbacks, first you need to either use a global variable to hold the database connection or pass the connection to every function every time, which quickly gets annoying. Second these functions don’t fit very well with our object oriented applications, where we prefer to think of our domain as objects instead of sets and functions. So, after functions there’s the monolithic class that usually isn’t much more then a wrapper for the previously mentioned functions.

Enter Active Record, the pattern that Ruby on Rails made infamous – Active Record is half the solution to our problem, however it couples our domain model very hard with the database logic – which is something we really want to avoid (why it’s preferable to avoid this is out of the scope of this article, as it would make for a smaller essay). After Active Record we have what this article is all about, Domain Objects and Data Mappers.

Alright now, stop.

Let’s go back to the beginning, but a different beginning then the relational databases – let’s look at our object oriented application. Here in object utopia everything and everyone is an object, we have a User, Post, Comment and all these other objects all fighting for our attention. As long as we stay inside our application all our objects are happy and life is good, but when our request is over and our application is shutting down the objects have to be stored somewhere – that’s right, in the database. Now a problem arises for our objects, they don’t know how to store themselves in a database, in fact they’re pretty ignorant and only care about their own realm. Let’s take a look at one of these objects, namely the User:

<?php
class User extends DomainObject {

    protected $name;

    function setName ($name) {
        $name = (string)$name;

        if (strlen($name) < 2)
            throw new Exception('User::$name must be atleast two characters long');

        $this->name = $name;
    }

    function getName () {
        return $this->name;
    }

}

Some of you might have noticed that the User” class extends the “DomainObject” class, we’ll get to that soon. Our User object is rather simple, it has one field the protected $name and we can change and retrieve that name with it’s two accessor methods setName() and getName() respectively. As you can see here the User has no idea of what a database is and especially not how to store itself in one, now enter the UserMapper – the class responsible for knowing how to store User objects in the database and later retrieve their rows and restore them to objects (Open the data_mapper/model/UserMapper.php file for reference, as the file is to big to put in the article).

This mapper isn’t complete in any way (lacking methods for deleting and updating User objects for example), but it will suffice for this article to explain the principle behind Data Mappers. As you can see the UserMapper class extends the DataMapper class, the DataMapper class is empty except for one static variable named $dbConn that we set to a PDO connection (in boostrap.php). Let’s take a look at the internals of the UserMapper class, first up is the insert()-method.

It’s one and only argument is a User object, and the first thing it does is to check so that the method getId() (which the User object has inherited from the DomainObject class, open up the file data_mapper/lib/DomainObject.php, it should be self-explaining) returns null, which means that this User doesn’t have an Id, which in turn means that it doesn’t have a row representing it in the database – so we’re free to insert it and create the row. Secondly, we create a prepared statement and feed the user’s name to it for the only parameter and execute it. The user now has a row representing it in the database, after that we retrieve the value of the last inserted id and give it to the user object. Last we add the object to the $map class field with it’s id as key, more on this later.

And the runner up is… find()!

The next method up is find(), find takes one parameter which is an $id integer and tries to find a row in the database that matches the $id and create a User object from it, let’s dissect it line by line. The first three lines should be self explanatory, we execute a prepared statement and retrieve the only row that it returned, after that we check so that $row isn’t false (if it’s just return false since there is no row with that id), last we call the method getObjectForRow() and pass it the row we got from the database, so guess which method is next for dissection?

You guessed it - it’s getObjectForRow(), this method is our most complex so far. On the first line we get the user_id column value and save into $user_id – this is just for convenience and readability further down. Second we check if an object already exists in $map under the key with the value of $user_id, if it does there’s no reason to create a new object and we can just return it. However, if it doesn’t exist we create a new User, assign the name and id to it and put it in the map under it’s id, then return it.

So what do we have this $map array to? This “pattern” is called Identity Map (http://martinfowler.com/eaaCatalog/identityMap.html) and is what we use so we don’t get two objects representing the same database row, to quote Fowler:

“An Identity Map keeps a record of all objects that have been read from the database in a single business transaction. Whenever you want an object, you check the Identity Map first to see if you already have it.“

So, now we’ve gone through the User and UserMapper class, let’s try them out (the tables used in these examples can be found in data_mapper/examples/sql/tables_ddl.sql) in a real example:

<?php
require 'bootstrap.php';

$anakin = new User;
$anakin->setName("Anakin Skywalker");

var_dump($anakin->getId());     // NULL, Object does not have a row in the database
UserMapper::insert($anakin);    // Saves Anakin Skywalker to the database
var_dump($anakin->getId());     // int(1), Object has a row in the database and a id

On the first line we just include bootstrap.php which is located in the same folder that connects to the database (remember to edit the database connection details in bootstrap.php so they fit your database) and includes all files we need for our examples.

Next up is the creation of a Sith Lord, Anakin Skywalker. We create a new User object and set it’s name to “Anakin Skywalker”, after that we var_dump() it’s return value from getId() which returns NULL, meaning that we haven’t saved the object to the database yet, so let’s do that with UserMapper::insert($anakin); After that we check the getId() return value again, and sure enough it returns int(1).

Let’s try something a bit more advanced, have a look at this example, where we create and then retrieve a User from the database:

<?php
require 'bootstrap.php';

$obiwan = new User;
$obiwan->setName("Obi-Wan Kenobi");

UserMapper::insert($obiwan);        // Saves Obi-Wan Kenobi to the database
var_dump($obiwan->getId());         // int(2)

$sameObiwan = UserMapper::find($obiwan->getId());
var_dump($sameObiwan->getId());     // int(2)

if($obiwan === $sameObiwan) {
    echo '$obiwan and $sameObiwan points to the same object';
}

The first eight or so lines are almost identical to the previous example, so I’ll skip those here. The first interesting line is number ten, where we call UserMapper::find() with the id-value of the object we just created and inserted – now why would we do that? In real life we probably wouldn’t, but this is an example so bare with me. The find() method returns an object to us, now what is this? We already have an object representing that row, preposterous! An impostor! Hold your horses, in the next line you can see that $sameObiwan’s getId() method also returns int(2), so have two objects pointing at the same now? No, not exactly – if you check the next if()-statement you will see that $obiwan and $sameObiwan (as it’s name suggest) points to the very same object, why you may ask. Because in our UserMapper::getObjectForRow()-method we check to see if we already have an object that represents the row with that very id we’re trying to create, and returns that if we have. And since we inserted the $obiwan object and the insert()-method saved the object into the $map (UserMapper.php, line 33) we get the same object back, nifty eh?

- Let’s hug it out bitch!

Who, what? Oh, Post is here for his fifteen minutes of fame, sure – let’s take it up a notch. First of all check out the data_mapper/model/Post.php file, it should be pretty similar to the User.php file in the same directory that we looked at earlier. Post extends DomainObject, has two fields ($text, $user) and two accessor methods each for these fields. Next, bring up data_mapper/model/PostMapper.php and let’s have a look at it. As the UserMapper class PostMapper extends DataMapper, however the findAll() method is new, also the insert() method works a bit different.

PostMapper::findAll()’s three first rows should be self explanatory we select all posts, left join in the user for each post and retrieve them all with fetchAll(). Next we start looping through the rows we got, first we call Posts’s getObjectForRow()-method (which is identical to the UserMapper’s method with the same name except we create a Post-object instead of a User-object) to create our Post-object. Secondly, since we left-joined the users to the posts and each returned row both contain the Post and User rows, we call UserMapper::getObjectForRow() on the same row to create our user. We assign the User to the Post by calling setUser() and then put our creation in the $posts array. This process is done for each Post/User-pair and then we return all of it at the last line.

PostMapper::insert() is also a bit different from it’s UserMapper cousin, so let’s have a look shall we. The first thing we do is to retrieve the Post’s user and make sure it’s actually an instance of the User object (we can’t save a post that doesn’t have a user, it’s not a magical post that can post itself now is it?), then we have to make sure the user actually has an id, if doesn’t (the getId() method returns null) we insert it first into the database so it get it’s id that we later insert into the posts-table. The next rows in PostMapper::insert() is close to identical to UserMapper::insert(), so they should need no further explanation.

Let’s try this out in practice, shall we? Let’s have a look at this nugget of gold:

<?php
require 'bootstrap.php';

$anakin = UserMapper::find(1);
$leia   = new User;
$leia->setName('Leia Organa');

$leias_post = new Post;
$leias_post->setText('You came in that thing? You\'re braver than I thought.');
$leias_post->setUser($leia);

$anakins_post = new Post;
$anakins_post->setText('I find your lack of faith disturbing.');
$anakins_post->setUser($anakin);

PostMapper::insert($leias_post);
PostMapper::insert($anakins_post);

var_dump($leia->getId(), $leias_post->getId(), $anakins_post->getId()); // int(3), int(1), int(2)

At the first row we retrieve or Anakin Skywalker object (which we know should have id 1 from our previous examples), secondly we create a new user under the name of Leia Organa, this is to demonstrate that the PostMapper::insert()-method works both with a saved and unsaved User object as a Post’s User. Next we create Two posts and assign the first to Leia and the second to Anakin. Last we call PostMapper::insert() on the two posts, what happens now is that with the first post ($leias_post) the PostMapper will see that Leia isn’t saved in the database and will call UserMapper::insert() on Leia, so she gets put in the database – and then save her post afterwards. Anakin however is already in the database and his post is inserted without having to do anything with him.

Last we call var_dump() on leia and the two posts to show that they were put in the database, we should get back something like this int(3) int(1) int(2).

We’re closing on on the end, but let’s do one more example before we call it for the evening. It’s time to retrieve the posts we inserted previously, that’s easily done with the PostMapper::findAll() method, let’s have a look at this listing:

<?php
require 'bootstrap.php';

$posts = PostMapper::findAll();

foreach ($posts as $post) {
    printf('%s said: %s', $post->getUser()->getName(), $post->getText());
}

We’ve already gone through most of the logic in this example, as most of the heavy lifting is done in the findAll() method which we dissected earlier, and as you can see everything works as expected – we get an array of our posts back and loop through it, calling getUser() on the post returns our user object so we can chain getName() on that and get the user’s name, calling getText() returns the text of the post – exactly as expected.

So, why on Hoth would we ever want to do this? As I said in the paragraph about active record: It’s all about decoupling our database from our object oriented application (domain model), this allows us to develop our application and our database independently of each other. A change in the database schema doesn’t require more then a fix to the insert/find-methods in our mappers. A lot more can (and has) been said on this subject, so I advice you to go and read up on it, it’s a very interesting problem.

There’s one last thing I’d want to touch a bit on before I close for today, namely writing your mappers and domain objects by hand (as in this article) or use a tool such as Propel or phpDoctrine, personally I stand on the writing-by-hand side of things, but both approaches have their respective advantages and disadvantages so I urge you to go and check out these two projects (even though phpDoctrine is more aching towards Active Record then Data Mapper).

Over and out, Fredrik.

on Apr 6th, 2008jQuery form autoretrieval

This is a simple snippet of javascript (jQuery) and a php provider file that allows you to type a number in the top most box and it then does a json-ajax-query through jQuery to fetch any data that matches that number. The data provider file is very simple, due to this being an example and it should probably be connected to an SQL database or something similar instead, anyway here’s the zipped file: jquery.zip.

on Mar 30th, 2008Mixin’s re-visited

Here’s a new example of how to get both class wide mixins and object method injection (copying), to lazy to write anything more now, so here’s the code: My syntax highlight plugin for wordpress decided to stop working, so here’s a link instead.

on Mar 25th, 2008Json Lexer/Parser - Part2

(The reason the calls that step back one position are typed “$this->pos = $this->pos-1″ instead of with a double minus-sign is that for some reason wordpress converts two “-” signs, into just one - making the code behave erroneously when you copy it to your editor)

Here’s the second part of my JSON Lexer/Parser tutorial, this will be a rather short post with a lot of self explaining code inside it, here it is:

<?php
class lexer_stream {

	var $pos;
	var $line;
	var $length;
	var $string;

	function __construct ($string) {
		$this->pos = -1;
		$this->line = 1;
		$this->string = $string;
		$this->length = strlen($string);
	}

	function next () {
		if (++$this->pos < $this->length) {

			if ($this->curr() == “\n”) {
				$this->line++;
			}

			return $this->curr();
		} else {
			$this->pos = $this->pos-1;
			return false;
		}
	}

	function prev () {
		if ($this->pos-1 >= 0) {

			if ($this->curr() == “\n”) {
				$this->line = $this->line-1;
			}

			$this->pos = $this->pos-1;
			return $this->curr();
		} else {
			$this->pos = 0;
			return false;
		}
	}

	function curr () {
		if ($this->pos >= 0 and $this->pos < $this->length) {
			return $this->string[$this->pos];
		} else {
			return false;
		}
	}
}

This class is a simple abstraction of a string, allowing us to call next(), prev() and curr() to step forward one character, step back one character and print the current character respectively. Why did I wrap a string like this? Why not use it in it’s raw form? Well, it’s not always a string we’re going to be reading our data to parse from, it could be from a socket, http-request or a file for example - and all we need to do is implement a wrapper class like the one above for our data format and we can then pass it to the lexer (that we’re going to build).

The code should be pretty self explanatory, the reason I’ve incorporated a $line-field is so that we can give nice error messages like: “JSON Error: Invalid format <bla bla bla>, on line: 5″. Anyway, that’s all for today folks - gotta hit the sack now, immensely tired after the trip back home to Stockholm from Gothenburg, over and out!