Tuesday, March 2, 2010

Creating A Doctrine Custom Behaviour, Part 1

Doctrine is a wonderful ORM library, but the manual is..., well, let's just say I think it was written by the developers, and out of obligation :-)

Behaviours are a motivating feature for using Doctrine, so here is a two-part tutorial on how to add your own minimal behaviour. The first part will show how to add a field to a table. The second part will show how to have its contents set automatically. For a more in-depth example see here or study the source code of the core behaviours.

The first thing you need to know is to put your behaviour classes in your models directory, or a sub-directory of your choice. You don't need a directory structure that matches the "XXX_YYY_" prefixes of the class name. This is assuming you are using Doctrine's auto-loading of table classes; if not you can put them anywhere you like of course. I'm putting them in models/behaviors/ (yes, using American spelling!)

Make a file called "DarrenTestable.php" with these contents:

class DarrenTestable extends Doctrine_Template{
public function setTableDefinition(){
$this->hasColumn('darren_testing','string');
}
}


See, I told you it was minimal! To add it to an existing class, add this to your YAML schema:


ActsAs:
DarrenTestable


Recreate the class from the schema and you should see a field called "darren_testing". On MySQL the type is "text" (i.e. this is what "string" maps to if you are using MySQL).

Even that very small example is doing something useful: if this behaviour is used in 10 classes and we need to change the name or data type (or set a default, add an index, etc.) we only need to edit it one place.

While still staying within the scope of a minimal example, we can expand it in two directions. We can have our code automatically set the field value (see part 2 of this article), and we can allow users to customize it. Here is how we add some options, with defaults:


class DarrenTestable extends Doctrine_Template
{
protected $_options = array(
'name'=>'darren_testing',
'type'=>'string',
'options'=>array(),
);

public function setTableDefinition()
{
$this->hasColumn($this->_options['name'],
$this->_options['type'], null, $this->_options['options']);
//$this->addListener(new DarrenTestableListener($this->_options));
}
}


I have added the call to the listener we'll use in part 2, but commented it out for the moment. The options contains a sub-array called options which is passed on to Doctrine_Table::setColumn() and can be used to set defaults and so on.

Usage is exactly like above if we want the defaults. If we want to change the name, and require it to be set (i.e. NOT NULL) you would do:

ActsAs:
DarrenTestable:
name: being_silly
options:
notnull: true

No comments: