<?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>Stereo Interactive &#38; Design - Ann Arbor, Michigan Web Design &#187; Doctrine</title>
	<atom:link href="http://stereointeractive.com/blog/tag/doctrine/feed/" rel="self" type="application/rss+xml" />
	<link>http://stereointeractive.com/blog</link>
	<description>Development Blog</description>
	<lastBuildDate>Tue, 20 Mar 2012 08:00:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Symfony 1.4 admin generator sort on custom column</title>
		<link>http://stereointeractive.com/blog/2011/01/08/symfony-1-4-admin-generator-sort-on-custom-column/</link>
		<comments>http://stereointeractive.com/blog/2011/01/08/symfony-1-4-admin-generator-sort-on-custom-column/#comments</comments>
		<pubDate>Sat, 08 Jan 2011 20:01:05 +0000</pubDate>
		<dc:creator>Scott Meves</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://stereointeractive.com/blog/?p=569</guid>
		<description><![CDATA[If you use the symfony 1.4 admin generator with doctrine you may notice that the column headings in the list view are links that enable you to sort your results by that column. If you customize the list view to include columns that include data from a foreign table, the generator will not automatically create [...]]]></description>
			<content:encoded><![CDATA[<p>If you use the symfony 1.4 admin generator with doctrine you may notice that the column headings in the list view are links that enable you to sort your results by that column. If you customize the list view to include columns that include data from a foreign table, the generator will not automatically create these sort links. Here is how I make foreign columns sortable. <span id="more-569"></span></p>
<p>Let&#8217;s say I have a model &#8220;Payment&#8221; and it has a one-to-many relationship with &#8220;Person&#8221; (i.e. one person has many payments, or the payment table has a foreign key &#8220;person_id&#8221;). I want the list of payments sortable by &#8220;last_name&#8221;.</p>
<p>In generator.yml:</p>

<div class="wp_syntax"><div class="code"><pre class="yml"> config:
  fields:
   last_name: { is_real: true }
...
  list:
    display:  [id, date, amount, last_name]</pre></div></div>

<p>Let&#8217;s update our Payment.class.php file with methods to fetch the person&#8217;s last name.</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span class="kw2">class</span> Payment <span class="kw2">extends</span> BasePayment
<span class="br0">&#123;</span>
<span class="sy0">...</span>
  <span class="kw2">public</span> <span class="kw2">function</span> getLastName<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="kw1">return</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">Person</span><span class="sy0">-&gt;</span><span class="me1">last_name</span><span class="sy0">;</span>
  <span class="br0">&#125;</span></pre></div></div>

<p>Now, if you reload your generated list view, you&#8217;ll see the column heading for last_name has been converted to a link. Now, we&#8217;ll have to add this foreign column (last_name) to our query and also add some logic to sort by the proper column when necessary.</p>
<p>Let&#8217;s add a custom table method to our list query, adding another line to generator.yml:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml">...
config:
  list:
  ...
    table_method: doSelectJoinPerson</pre></div></div>

<p>Let&#8217;s add the new method to our PaymentTable.class.php:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span class="kw2">class</span> PaymentTable <span class="kw2">extends</span> Doctrine_Table
<span class="br0">&#123;</span>
  <span class="sy0">...</span>  
  <span class="kw2">public</span> static <span class="kw2">function</span> doSelectJoinPerson<span class="br0">&#40;</span><span class="re0">$query</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="re0">$rootAlias</span> <span class="sy0">=</span> <span class="re0">$query</span><span class="sy0">-&gt;</span><span class="me1">getRootAlias</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="kw1">return</span> <span class="re0">$query</span><span class="sy0">-&gt;</span><span class="me1">select</span><span class="br0">&#40;</span><span class="re0">$rootAlias</span> <span class="sy0">.</span> <span class="st_h">'.*, p.last_name'</span><span class="br0">&#41;</span>
      <span class="sy0">-&gt;</span><span class="me1">leftJoin</span><span class="br0">&#40;</span><span class="re0">$rootAlias</span> <span class="sy0">.</span> <span class="st_h">'.Person p'</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>The table_method parameter in our list configuration is used to define which method should be executed on our model&#8217;s table when it fetches results from the database.  Our main model will always have an alias &#8220;r&#8221; as defined in the symfony/doctrine source code (check out <code>sfFormFilterDoctrine::doBuildQuery()</code>). </p>
<p>We now need to pass the table alias for our foreign table (in this case, we used &#8216;p&#8217; for Person) into our sort query if &#8216;last_name&#8217; is given as our sort parameter. Let&#8217;s override the <code>addSortQuery($query)</code> in our actions class:</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span class="kw2">class</span> paymentActions <span class="kw2">extends</span> autoPaymentActions
<span class="br0">&#123;</span>
<span class="sy0">...</span>
  <span class="kw2">protected</span> <span class="kw2">function</span> addSortQuery<span class="br0">&#40;</span><span class="re0">$query</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span><span class="kw4">null</span><span class="sy0">,</span> <span class="kw4">null</span><span class="br0">&#41;</span> <span class="sy0">==</span> <span class="br0">&#40;</span><span class="re0">$sort</span> <span class="sy0">=</span> <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getSort</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <span class="kw1">return</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span><span class="kw3">in_array</span><span class="br0">&#40;</span><span class="kw3">strtolower</span><span class="br0">&#40;</span><span class="re0">$sort</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">,</span> <span class="kw3">array</span><span class="br0">&#40;</span><span class="st_h">'asc'</span><span class="sy0">,</span> <span class="st_h">'desc'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>
    <span class="br0">&#123;</span>
      <span class="re0">$sort</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="st_h">'asc'</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="kw1">switch</span> <span class="br0">&#40;</span><span class="re0">$sort</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
      <span class="kw1">case</span> <span class="st_h">'last_name'</span><span class="sy0">:</span>
        <span class="re0">$sort</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="st_h">'p.last_name'</span><span class="sy0">;</span>
        <span class="kw1">break</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
&nbsp;
    <span class="re0">$query</span><span class="sy0">-&gt;</span><span class="me1">addOrderBy</span><span class="br0">&#40;</span><span class="re0">$sort</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="sy0">.</span> <span class="st_h">' '</span> <span class="sy0">.</span> <span class="re0">$sort</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="sy0">...</span></pre></div></div>

<p><strong>Update:</strong>A few comments below pointed out for the default admin generator theme you&#8217;ll also need to add the following method to your controller (actions.class.php):</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span class="kw2">protected</span> <span class="kw2">function</span> isValidSortColumn<span class="br0">&#40;</span><span class="re0">$column</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
  <span class="kw1">return</span> Doctrine_Core<span class="sy0">::</span><span class="me2">getTable</span><span class="br0">&#40;</span>‘Payment’<span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">hasColumn</span><span class="br0">&#40;</span><span class="re0">$column</span><span class="br0">&#41;</span> <span class="sy0">||</span> <span class="re0">$column</span> <span class="sy0">==</span> ‘last_name’<span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>Once you get used to this process, it&#8217;s really not too hard to implement for all of your admin-generated modules. No plugins necessary. </p>
<p><strong>Update 2:</strong> Updated doSelect query to use root alias defined in the query per the comments below.</p>
]]></content:encoded>
			<wfw:commentRss>http://stereointeractive.com/blog/2011/01/08/symfony-1-4-admin-generator-sort-on-custom-column/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Symfony 1.2 doctrine file upload in form</title>
		<link>http://stereointeractive.com/blog/2010/03/30/symfony-1-2-doctrine-file-upload-in-form/</link>
		<comments>http://stereointeractive.com/blog/2010/03/30/symfony-1-2-doctrine-file-upload-in-form/#comments</comments>
		<pubDate>Wed, 31 Mar 2010 00:06:51 +0000</pubDate>
		<dc:creator>Scott Meves</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://stereointeractive.com/blog/?p=497</guid>
		<description><![CDATA[Here are the required modifications for to a form class that contains a file upload field in symfony 1.2 using doctrine (and it probably works with propel, too). class NewsletterForm extends BaseNewsletterForm &#123; public function configure&#40;&#41; &#123; $this-&#62;widgetSchema&#91;'file'&#93; = new sfWidgetFormInputFileEditable&#40;array&#40; 'file_src' =&#62; '/uploads/'.$this-&#62;getObject&#40;&#41;-&#62;getfile&#40;&#41;, 'is_image' =&#62; true, 'edit_mode' =&#62; !$this-&#62;isNew&#40;&#41;, //'template' =&#62; '&#60;div&#62;%file%&#60;br /&#62;%input%&#60;br /&#62;%delete% [...]]]></description>
			<content:encoded><![CDATA[<p>Here are the required modifications for to a form class that contains a file upload field in symfony 1.2 using doctrine (and it probably works with propel, too).<br />
<span id="more-497"></span></p>

<div class="wp_syntax"><div class="code"><pre class="php"><span class="kw2">class</span> NewsletterForm <span class="kw2">extends</span> BaseNewsletterForm
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> configure<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">widgetSchema</span><span class="br0">&#91;</span><span class="st_h">'file'</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="kw2">new</span> sfWidgetFormInputFileEditable<span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span>
      <span class="st_h">'file_src'</span> <span class="sy0">=&gt;</span> <span class="st_h">'/uploads/'</span><span class="sy0">.</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">getObject</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">-&gt;</span><span class="me1">getfile</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
      <span class="st_h">'is_image'</span>  <span class="sy0">=&gt;</span> <span class="kw4">true</span><span class="sy0">,</span>
      <span class="st_h">'edit_mode'</span> <span class="sy0">=&gt;</span> <span class="sy0">!</span><span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">isNew</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">,</span>
      <span class="co1">//'template'  =&gt; '&lt;div&gt;%file%&lt;br /&gt;%input%&lt;br /&gt;%delete% %delete_label%&lt;/div&gt;',</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">validatorSchema</span><span class="br0">&#91;</span><span class="st_h">'file'</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="kw2">new</span> sfValidatorFile<span class="br0">&#40;</span><span class="kw3">array</span><span class="br0">&#40;</span>
      <span class="st_h">'required'</span> <span class="sy0">=&gt;</span> <span class="kw4">false</span><span class="sy0">,</span>
      <span class="st_h">'path'</span> <span class="sy0">=&gt;</span> sfConfig<span class="sy0">::</span><span class="me2">get</span><span class="br0">&#40;</span><span class="st_h">'sf_upload_dir'</span><span class="br0">&#41;</span>
    <span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
    <span class="re0">$this</span><span class="sy0">-&gt;</span><span class="me1">validatorSchema</span><span class="br0">&#91;</span><span class="st_h">'file_delete'</span><span class="br0">&#93;</span> <span class="sy0">=</span> <span class="kw2">new</span> sfValidatorPass<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div>

<p>If you want to override the file name generated for your uploaded file, add a &#8216;generateXXXFileName()&#8217; method to your model&#8217;s class where XXX is the column name that contains the file name (in this example, our column is &#8220;file&#8221;, so the method name is &#8216;generateFileFilename&#8217;. It takes a single parameter, which is an instance of sfValidatedFile.</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span class="kw2">class</span> Newsletter <span class="kw2">extends</span> BaseNewsletter
<span class="br0">&#123;</span>
  <span class="kw2">public</span> <span class="kw2">function</span> generateFileFileName<span class="br0">&#40;</span><span class="re0">$file</span><span class="br0">&#41;</span>
  <span class="br0">&#123;</span>
    <span class="kw1">return</span> <span class="re0">$file</span><span class="sy0">-&gt;</span><span class="me1">getOriginalName</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span>
<span class="br0">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://stereointeractive.com/blog/2010/03/30/symfony-1-2-doctrine-file-upload-in-form/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>&#8220;Could not create database for c&#8230;o use near&#8221; error with Doctrine / Symfony</title>
		<link>http://stereointeractive.com/blog/2009/12/31/could-not-create-database-for-c-o-use-near-error-with-doctrine-symfony/</link>
		<comments>http://stereointeractive.com/blog/2009/12/31/could-not-create-database-for-c-o-use-near-error-with-doctrine-symfony/#comments</comments>
		<pubDate>Thu, 31 Dec 2009 22:44:40 +0000</pubDate>
		<dc:creator>Scott Meves</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://stereointeractive.com/blog/?p=386</guid>
		<description><![CDATA[I was trying to use the symfony command line tools to rebuild my test database and I couldn&#8217;t get past this error: &#62;&#62; doctrine Could not create database for c...o use near '-sb-test' at line 1 Turns out the issue is with the &#8220;-&#8221; in my test database name. Replacing the hyphens with underscores fixed [...]]]></description>
			<content:encoded><![CDATA[<p>I was trying to use the symfony command line tools to rebuild my test database and I couldn&#8217;t get past this error:<span id="more-386"></span></p>

<div class="wp_syntax"><div class="code"><pre class="bash"><span class="sy0">&gt;&gt;</span> doctrine Could not create database <span class="kw1">for</span> c...o use near <span class="st_h">'-sb-test'</span> at line <span class="nu0">1</span></pre></div></div>

<p>Turns out the issue is with the &#8220;-&#8221; in my test database name. Replacing the hyphens with underscores fixed the problem. </p>
]]></content:encoded>
			<wfw:commentRss>http://stereointeractive.com/blog/2009/12/31/could-not-create-database-for-c-o-use-near-error-with-doctrine-symfony/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP Doctrine: Fetching related objects with hasOne relationship or one-to-zero-or-one</title>
		<link>http://stereointeractive.com/blog/2009/07/16/php-doctrine-fetching-related-objects-with-hasone-relationship-or-one-to-zero-or-one/</link>
		<comments>http://stereointeractive.com/blog/2009/07/16/php-doctrine-fetching-related-objects-with-hasone-relationship-or-one-to-zero-or-one/#comments</comments>
		<pubDate>Thu, 16 Jul 2009 18:38:35 +0000</pubDate>
		<dc:creator>Scott Meves</dc:creator>
				<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://stereointeractive.com/blog/?p=240</guid>
		<description><![CDATA[People new to the Doctrine ORM have a hard time understanding the magic that happens behind the scenes when you want to fetch a related object through a has-one-or-zero relationship. Looking through the doctrine-user group, it&#8217;s clear there is a lot confusion on this to newcomers, especially if you are coming over from Propel or [...]]]></description>
			<content:encoded><![CDATA[<p>People new to the Doctrine ORM have a hard time understanding the magic that happens behind the scenes when you want to fetch a related object through a has-one-or-zero relationship. Looking through the doctrine-user group, it&#8217;s clear there is a lot confusion on this to newcomers, especially if you are coming over from Propel or other ORMs. It can be a pretty big conceptual change to how things are done.<br />
<span id="more-240"></span></p>
<p>To use an example off of the doctrine-user group, imagine you have a Content object and this may or may not have a related Metadata record.</p>
<p>If you are familiar with Propel, then if you had your hydrated $content object, you could do</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span class="co1">// with propel:</span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$metadata</span> <span class="sy0">=</span> <span class="re0">$content</span><span class="sy0">-&gt;</span><span class="me1">getMetadata</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
  <span class="co1">// do something with the related $metadata</span>
<span class="br0">&#125;</span></pre></div></div>

<p>and getMetadata() would return NULL if there was no related record to be found.</p>
<p><strong>Doctrine will automatically create an empty related object if you request one</strong>, so calling <code>$content->Metadata</code> or <code>$content['Metadata']</code> or $content->getMetadata() will always return a Metadata object, even if it does not exist in the database. So, you can&#8217;t rely on the same trick above to see if a related object exists. </p>
<p>So, how do you check if a related object actually exists? The first way, and my favorite, is using the <code>exists()</code> method to check if the related object is persistent (i.e. the object is saved in the DB).</p>

<div class="wp_syntax"><div class="code"><pre class="php"><span class="co1">// with doctrine </span>
<span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$content</span><span class="sy0">-&gt;</span><span class="me1">Metadata</span><span class="sy0">-&gt;</span><span class="me1">exists</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> 
  <span class="co1">// related metadata exists for this $content object</span>
<span class="br0">&#125;</span></pre></div></div>

<p>Using <code>isset()</code> will check if the related object has been hydrated/ loaded, but it will not do a query against the database to see if it exists there. So, if you fetch a Content object and do not do any joins in your query to join the related Metadata objects, then isset(), either by doing <code>isset($business->Metadata)</code> or <code>$business->isset('Metadata')</code> will *always* return false.</p>
<p>If your foreign key to the related object exists in your parent record (if content has a metadata_id field) you can always check the value of <code>$content['metadata_id']</code>. This will not work if the foreign key exists only in your metadata table (metadata has a column content_id, but content does not have a metadata_id column).</p>
<p>I think if you really wanted to do it right, if you expect to be checking for the existence of a related object (&#8220;Metadata&#8221;) on your collection of core objects (&#8220;Content&#8221;), you should do a join in your query so you don&#8217;t have to hit the database for every single Content record fetched to see if a related Metadata record exists.</p>
<p>Here are a few threads on this subject in the doctrine-user group:</p>
<ul>
<li><a href="http://groups.google.com/group/doctrine-user/browse_thread/thread/75ba51a6c59685cb">Call $record->Related without creating new object</a></li>
<li><a href="http://groups.google.com/group/doctrine-user/browse_thread/thread/cfd24581e03322eb">hasOne relationship</a></li>
<li><a href="http://groups.google.com/group/doctrine-user/browse_thread/thread/de79d55b0af80a1d">Awkward handling of One-to-Zero-or-One relationships in Doctrine</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://stereointeractive.com/blog/2009/07/16/php-doctrine-fetching-related-objects-with-hasone-relationship-or-one-to-zero-or-one/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

