<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
><channel><title>A.J. Brown&#039;s Blog &#187; Doctrine ORM</title> <atom:link href="http://ajbrown.org/blog/tags/doctrine-orm/feed" rel="self" type="application/rss+xml" /><link>http://ajbrown.org/blog</link> <description>Coding adventures and technology musing for the masses</description> <lastBuildDate>Fri, 26 Mar 2010 17:57:50 +0000</lastBuildDate> <language>en</language> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.0.1</generator> <item><title>Quick Doctrine ORM Tip: Hydration Using Doctrine_Table</title><link>http://ajbrown.org/blog/2008/12/31/hydration-using-doctrine-table.html</link> <comments>http://ajbrown.org/blog/2008/12/31/hydration-using-doctrine-table.html#comments</comments> <pubDate>Wed, 31 Dec 2008 12:00:53 +0000</pubDate> <dc:creator>A.J. Brown</dc:creator> <category><![CDATA[PHP]]></category> <category><![CDATA[Doctrine ORM]]></category> <category><![CDATA[Doctrine_Record]]></category> <category><![CDATA[Doctrine_Table]]></category><guid isPermaLink="false">http://ajbrown.org/blog/?p=120</guid> <description><![CDATA[Did you know you can have what Propel calls "Peers" in Doctrine PHP?  A peer is basically an object which is responsible for hydrating (populating) a model.  From the documentation, you might think this can only be done using DQL, but you can actually use Doctrine_Table to do the work for you.]]></description> <content:encoded><![CDATA[<p>Did you know you can have what Propel calls "Peers" in <a href="">Doctrine ORM</a>?  A peer is basically an object which is responsible for hydrating (populating) a model.  From the documentation, you might think this can only be done using DQL, but you can actually use Doctrine_Table to do the work for you.</p><p>The first thing you must do is define the model you want to be hydratable.  I'll use "Article" as my model.   This step is important because it gives Doctrine an object to hydrate when we perform operations against our Doctrine_Table object.  It also, of course, allows Doctrine to do alias translation and automatically detect relationships (I.E., so you don't have to manually perform joins.</p><pre lang="PHP" line="1">
class Article extends Doctrine_Record
{

	public function setTableDefinition()
	{

		$this->hasColumn( 'title', 'string', 255,
			array( 'notblank' => true )
		);

		$this->hasColumn( 'author', 'string', 255,
			array( 'notblank' => true )
		);

		$this->hasColumn( 'body', 'clob' );

		$this->hasColumn( 'published', 'boolean', null,
			array( 'default' => false )
		);
	}

	public function setUp()
	{
		$this->hasMany( 'Comment', array(
			'local' => 'id',
            		'foreign' => 'article_id',
		);
	}
}
</pre><p><sup>*It's good practice to make all of your models<cite>Timestampable</cite>, but I left that out of this example for simplicity</sup></p><p>Now that our models have been defined, lets move on to our Peer, the<cite>Doctrine_Table</cite>.  In it's simplest form, our Peer only needs to extend Doctrine_Table.  In order to harness the power of Doctrine out of the box, we need to <strong>make sure the 3rd parameter of the Doctrine_Table constructor is set to "<em>true</em>"</strong>.  This allows Doctrine to bind our model (defined above) to the Table that this Doctrine_Table instance is representing.   Without it, we would have to manually bind the model.</p><p><strong>TIP:</strong> Instead of doing this for every Peer, create a base class which does it for you.  I haven't run into a case yet where I didn't want to let Doctrine do it's work for me.  As long as the models exist, it should work fine.</p><pre lang="PHP" line="1">
class ArticlePeer extends Doctrine_Table
{

	public function __construct( Doctrine_Connection $oDbCon )
	{
		parent::__construct(  'Article', $oDbCon, true );
	}
}
</pre><p>Now that our peer is defined, we can save ourselves the trouble of writing any DQL.  Doctrine_Table makes available some magic functions, allowing you to do simple queries against any field defined in the model you're peering.  For example, we can easily retrieve a collection of Articles by "A.J. Brown":</p><pre lang="PHP" line="1">
$peer = new ArticlePeer( $connection );
$articles = $peer->findByAuthor( 'A.J. Brown' );
</pre><p>or all published articles:</p><pre lang="PHP" line="1">
$peer = new ArticlePeer( $connection );
$articles = $peer->findByPublished( true );
</pre><p>The advantage of this approach might not be obvious at first.  After all, you could just as easily instanciate a new Doctrine_Table, passing the correct parameters, right?</p><p>Most applications won't use the simple findBy<field> methods made availble through the Doctrine_Table API.   We'll typically need to do lookups that will require custom DQL to return the objects we need.  It's a good practice to make these queries reusable, and place them at a lower level in your code.  In fact, If you follow the "Fat Model, Skinny Controller" philosophy,  you would never be writing DQL at any level of your application outside of the model / data access layer. </field></p><p>With that said, any query that hydrates Article models (or agregate data of Article models, such as counts and averages) should be performed within a method of our ArticlePeer:</p><pre lang="PHP" line="1">
< ?php
class ArticlePeer extends Doctrine_Table
{

	public function __construct( Doctrine_Connection $oDbCon )
	{
		parent::__construct(  'Article', $oDbCon, true );
	}

	public function findArticlesForReview()
	{
		return $this->createQuery()
			->where( 'Article.pendingReview = true' )
			->addWhere( "Article.status != 'draft' ")
			->orderBy( "Article.title" )
			->execute()
			;
	}

}
</pre><p>Now our user code doesn't have to know the query needed for the data, it only needs to know what the method returns.  If your definition of an article pending review changes later, you won't need to grep through all of your code for the related queries.</p><p><strong>TIP:</strong> An added benefit of placing your DQL queries inside Doctrine_Table objects is caching.  The ArticlePeer above makes a great place to implement <a href="http://ajbrown.org/blog/tags/memcached">Memcached caching</a>, since it would be completely transparent to the user.</p><p>Happy Doctrine...ing?</p><p>For more basic information on using Doctrine, check the <a href="http://www.doctrine-project.org/documentation/manual/1_1/en/one-page#working-with-objects:fetching-data">Doctrine ORM Online Manual</a>.</p> ]]></content:encoded> <wfw:commentRss>http://ajbrown.org/blog/2008/12/31/hydration-using-doctrine-table.html/feed</wfw:commentRss> <slash:comments>0</slash:comments> </item> <item><title>New Doctrine Patch: BETWEEN relation alias parsing</title><link>http://ajbrown.org/blog/2008/12/30/new-doctrine-patch-between-relation-alias-parsing.html</link> <comments>http://ajbrown.org/blog/2008/12/30/new-doctrine-patch-between-relation-alias-parsing.html#comments</comments> <pubDate>Tue, 30 Dec 2008 21:44:30 +0000</pubDate> <dc:creator>A.J. Brown</dc:creator> <category><![CDATA[PHP]]></category> <category><![CDATA[Doctrine ORM]]></category> <category><![CDATA[Doctrine_Query]]></category> <category><![CDATA[Doctrine_Query_Where]]></category><guid isPermaLink="false">http://ajbrown.org/blog/?p=151</guid> <description><![CDATA[Issue BETWEEN clauses with relational alias operands do not parse, resulting in an exception "could not find short alias". Example The following code will throw an exception. User hasOne Subscription. $q1 = Doctrine_Query::create() ->select('u.id') ->from('User u') ->where("CURRENT_DATE() BETWEEN u.Subscription.begin AND u.Subscription.end") ->addWhere( 'u.id != 5' ); Since the between operands are relational aliases, and not [...]]]></description> <content:encoded><![CDATA[<h4 id="toc-issue">Issue</h4><p>BETWEEN clauses with relational alias operands do not parse, resulting in an exception "could not find short alias".</p><h4 id="toc-example">Example</h4><p>The following code will throw an exception.  User hasOne Subscription.</p><pre lang="PHP" line="1">
$q1 = Doctrine_Query::create()
    ->select('u.id') ->from('User u') ->where("CURRENT_DATE() BETWEEN u.Subscription.begin AND u.Subscription.end")
    ->addWhere( 'u.id != 5' );
</pre><p>Since the between operands are relational aliases, and not literals or short aliases, Doctrine does not attempt to parse correctly.  I modified the behavior to do extra parsing on the expressions when BETWEEN is encountered as the operation.</p><h4 id="toc-the-goods">The Goods</h4><ul><li><a href="http://trac.doctrine-project.org/attachment/ticket/1792/fix-parse-between.diff">The Patch</a></li><li><a href="http://trac.doctrine-project.org/ticket/1792">The Ticket</a></li></ul><p>Guilherme from the team messaged me last night to let me know he's going to commit the patch.  I just checked and it's not there yet, so if you need this fix immediately, you can apply the patch above.</p> ]]></content:encoded> <wfw:commentRss>http://ajbrown.org/blog/2008/12/30/new-doctrine-patch-between-relation-alias-parsing.html/feed</wfw:commentRss> <slash:comments>1</slash:comments> </item> </channel> </rss>