YAML Makes Life Easier
This post isn’t going to be breaking any new ground. I’ve been working on a project on and off for about a year now. It’s using the CodeIgniter 1.7 framework and Doctrine 1.2 for its ORM. With Doctrine, there are kind of two ways to define Models. You can create them in PHP or you can create them in YAML. I was doing the former for the longest time, but recently switched over to YAML and have been just kicking myself for not doing so sooner. Here’s an example of a model in PHP:
* Description of field * * @property integer $order * @property boolean $required * @property ValueType $ValueType * @property FormField $FormField * @author Eric * @author Eric */ class Field extends Doctrine_Record { public function setTableDefinition() { $this->hasColumn('field_order', 'integer', 4); $this->hasColumn('required', 'boolean'); $this->hasColumn('value_type_id', 'integer'); $this->hasColumn('form_field_id', 'integer'); } public function setUp() { $this->hasOne('ValueType', array ( 'local' => 'value_type_id', 'foreign' => 'id' )); $this->hasMany('LeadType as LeadTypes', array( 'local' => 'field_id', 'foreign' => 'lead_type_id', 'refClass' => 'LeadTypeField' )); $this->hasOne('FormField', array ( 'local' => 'form_field_id', 'foreign' => 'id' )); } }
And here’s the Field.yml file for my project:
Field: tableName: field columns: id: type: integer(8) primary: true autoincrement: true field_order: type: int(4) required: type: boolean actAs: Timestampable: relations: FormField: ValueType: LeadType: foreignAlias: Fields
Now, when we run that through Doctrine_Core::generateModelsFromYaml, it will generate two files for you. An abstract BaseField class:
/** * BaseField * * This class has been auto-generated by the Doctrine ORM Framework * * @property integer $id * @property int $field_order * @property boolean $required * @property FormField $FormField * @property LeadType $LeadType * * @package ##PACKAGE## * @subpackage ##SUBPACKAGE## * @author ##NAME## <##EMAIL##> * @version SVN: $Id: Builder.php 7490 2010-03-29 19:53:27Z jwage $ */ abstract class BaseField extends Doctrine_Record { public function setTableDefinition() { $this->setTableName('field'); $this->hasColumn('id', 'integer', 8, array( 'type' => 'integer', 'primary' => true, 'autoincrement' => true, 'length' => '8', )); $this->hasColumn('field_order', 'int', 4, array( 'type' => 'int', 'length' => '4', )); $this->hasColumn('required', 'boolean', null, array( 'type' => 'boolean', )); } public function setUp() { parent::setUp(); $this->hasOne('FormField', array( 'local' => 'form_field_id', 'foreign' => 'id')); $this->hasOne('LeadType', array( 'local' => 'lead_type_id', 'foreign' => 'id')); $timestampable0 = new Doctrine_Template_Timestampable(); $this->actAs($timestampable0); } }
and a Field class that extends the BaseField class.
Now, a couple of things to take away from this. Writing the Doctrine models by hand in PHP is a pain, where as doing so in YAML is pretty easy. Also, Doctrine creates that nice Abstract class for you, which is overwritten every time you generate the code, but also generates a simple class which extends the generated class and which is never overwritten. YAML, which stands for YAML Ain’t Markup Language, is a data serialization format and is probably closest to JSON. Using the friendly Online YAML Parser, here’s the above Field.yml file in the popular JSON format:
{ "Field": { "actAs": { "Timestampable": null }, "tableName": "field", "columns": { "field_order": { "type": "int(4)" }, "required": { "type": "boolean" }, "id": { "autoincrement": true, "type": "integer(8)", "primary": true } }, "relations": { "ValueType": null, "LeadType": { "foreignAlias": "Fields" }, "FormField": null } } }
YAML skips the curly brackets (or braces, or squiggly brackets, or whatever you wish to call them), quotation marks, commas, and instead relies on spacing and indentation.
There’s another neat trick that Doctrine utilizes YAML for, and that is loading data into a database. What this is especially useful for is initializing default data into a database. Here’s a partial example, based on the Field.yml file above:
Field: Field_1: field_order: 1 required: false Field_2: field_order: 2 required: true Field_2: field_order: 3 required: true
I dropped the relationships for brevity, but what the above YAML would give us are three Fields in the database, with their assigned field_orders and required values. To load that data you simply call Doctrine_Core::loadData(‘FieldData.yml’) and that is it. Read more about it here.