<?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>Alexander Stelter - foo, bar, baz &#187; orm</title>
	<atom:link href="http://www.alexander-stelter.de/blog/tag/orm/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.alexander-stelter.de/blog</link>
	<description>PHP, Javascript, Doctrine, Internet, Bücher, Real-Life</description>
	<lastBuildDate>Thu, 09 Sep 2010 05:57:10 +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>Doctrine 2 Preview Release veröffentlicht</title>
		<link>http://www.alexander-stelter.de/blog/364-doctrine-2-preview-release-veroffentlicht/</link>
		<comments>http://www.alexander-stelter.de/blog/364-doctrine-2-preview-release-veroffentlicht/#comments</comments>
		<pubDate>Wed, 02 Sep 2009 05:24:41 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[doctrine 2]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[preview release]]></category>

		<guid isPermaLink="false">http://www.alexander-stelter.de/blog/?p=364</guid>
		<description><![CDATA[Heute morgen haben die Entwickler von Doctrine einen ersten Preview Release des neuen Doctrine 2 veröffentlicht. Genau ein Jahr, nachdem Doctrine 1 stable wurde, geht also Doctrine 2 seinen ersten Weg an die Öffentlichkeit. Btw. Herzlichen Glückwunsch zum Geburtstag, Doctrine 1 . Bei Doctrine 2 handelt es sich um einen kompletten Redesign des Codes und [...]]]></description>
			<content:encoded><![CDATA[<p>Heute morgen haben die Entwickler von Doctrine einen ersten Preview Release des neuen Doctrine 2 <a href="http://www.doctrine-project.org/blog/doctrine2-preview-release" >veröffentlicht</a>. Genau ein Jahr, nachdem Doctrine 1 stable wurde, geht also Doctrine 2 seinen ersten Weg an die Öffentlichkeit. Btw. <strong>Herzlichen Glückwunsch zum Geburtstag, Doctrine 1</strong> <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p>Bei Doctrine 2 handelt es sich um einen kompletten Redesign des Codes und der Infrastruktur. 90% des Codes wurden neu geschrieben und in neue Konzepte gepresst. Das neue Doctrine 2 ist in Pakete aufgeteilt, die aber höchst wahrscheinlich bei den meisten im Paket verwendet werden:
<ul>
<li>Doctrine Common (Generic components, high re usability)</li>
<li>Doctrine DBAL (The database abstraction layer, includes: Common)</li>
<li>Doctrine ORM (The ORM tools, includes: Common + DBAL)</li>
</ul>
<p>Die Pakete können separat runtergeladen werden, und werden im Moment (noch) gleichzeitig released und maintained, dies kann sich aber wohl in Zukunft ändern.</p>
<p>Einige Tools von Doctrine 1 (z.B. das CLI oder die Migrations) befinden sich noch in der Entwicklung und werden ggf. später im Extension Repository landen und nicht mehr im Core enthalten sein, das ist aber aktuell noch nicht geklärt.</p>
<p>Generell sei zu sagen, dass dieser Release <strong>nicht für die Produktion gedacht</strong> ist, sondern für die Community als ersten Test, um ein wenig mit dem neuen Core warm zu werden. Ein Quickstart Tutorial wurde hier <a href="http://www.doctrine-project.org/documentation/manual/2_0/en/introduction#sandbox-quickstart" >veröffentlicht</a>. Der Download ist <a href="http://www.doctrine-project.org/download" >hier zu finden</a>, Bugs können &#8211; wie immer &#8211; im <a href="http://trac.doctrine-project.org/" >Trac</a> gemeldet werden.</p>
<p align="left"><a target="_blank" class="tt" href="http://twitter.com/home/?status=Doctrine+2+Preview+Release+ver%C3%B6ffentlicht+http://bit.ly/9jbbWo" title="Post to Twitter"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-twitter-micro3.png" alt="Post to Twitter" /></a> <a target="_blank" class="tt" href="http://delicious.com/post?url=http://www.alexander-stelter.de/blog/364-doctrine-2-preview-release-veroffentlicht/&amp;title=Doctrine+2+Preview+Release+ver%C3%B6ffentlicht" title="Post to Delicious"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-delicious-micro3.png" alt="Post to Delicious" /></a> <a target="_blank" class="tt" href="http://digg.com/submit?url=http://www.alexander-stelter.de/blog/364-doctrine-2-preview-release-veroffentlicht/&amp;title=Doctrine+2+Preview+Release+ver%C3%B6ffentlicht" title="Post to Digg"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-digg-micro3.png" alt="Post to Digg" /></a> <a target="_blank" class="tt" href="http://www.facebook.com/share.php?u=http://www.alexander-stelter.de/blog/364-doctrine-2-preview-release-veroffentlicht/&amp;t=Doctrine+2+Preview+Release+ver%C3%B6ffentlicht" title="Post to Facebook"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-facebook-micro3.png" alt="Post to Facebook" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexander-stelter.de/blog/364-doctrine-2-preview-release-veroffentlicht/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Doctrine wächst und gedeiht</title>
		<link>http://www.alexander-stelter.de/blog/155-doctrine-wachst-und-gedeiht/</link>
		<comments>http://www.alexander-stelter.de/blog/155-doctrine-wachst-und-gedeiht/#comments</comments>
		<pubDate>Thu, 14 Feb 2008 20:29:21 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[doctrine 0.10]]></category>
		<category><![CDATA[doctrine 0.9]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[php 5.3]]></category>

		<guid isPermaLink="false">http://www.alexander-stelter.de/blog/?p=155</guid>
		<description><![CDATA[Doctrine wächst und gedeiht, so war es heute im offiziellen Entwickler-Blog zu lesen. Der nächste Release für die 0.9er Branch wird nun wohl auch der letzte sein (0.9.1). Gleichzeitig wird es auch einen neuen Release der 0.10er Branch geben, welche dann auch weiterhin unterstützt wird. Soll heißen für die 0.9.x Branch wird es keine Bugfixes [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.phpdoctrine.org/" >Doctrine</a> wächst und gedeiht, so war es heute im offiziellen Entwickler-Blog zu <a href="http://www.phpdoctrine.org/blog/doctrine-all-grown-up" >lesen</a>. Der nächste Release für die 0.9er Branch wird nun wohl auch der letzte sein (0.9.1). Gleichzeitig wird es auch einen neuen Release der 0.10er Branch geben, welche dann auch weiterhin unterstützt wird. Soll heißen für die 0.9.x Branch wird es keine Bugfixes mehr geben. Der Trunk bleibt weiterhin für den Produktiveinsatz nicht empfohlen, da hier Refactoring und die Entwicklung von neuen Features betrieben wird. Wenn man mal einen Einblick haben will, was gerade implementiert wird oder ein neues Feature ausprobieren will, kann man aber gerne damit rumspielen.</p>
<p>Weiterhin fiebert man im Hause Doctrine bereits dem Release von PHP 5.3 entgegen, da man danach die Klassen-Infrastruktur von Doctrine auf Namespaces umstellt und somit eine weitere Modularisierung erreicht.</p>
<p>Ich habe leider im Moment keine Gelegenheit eine der aktiven Branches produktiv zu verwenden, werde aber wahrscheinlich in naher Zukunft wieder Gelegenheit haben mit einer neueren Version zu arbeiten. Ich kann allerdings auch sagen, dass die älteren Versionen auch im Produktivbetrieb doch schon recht stabil sind (so man sie dann mal ans Laufen bekommen hat) <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p>Für interessierte Leser kann ich auch die diversen <a href="http://www.phpdoctrine.org/community" >Mailinglisten</a> empfehlen. Hier wird munter über die Weiterentwicklung, Refactoring und Probleme diskutiert. Ich halte weiterhin an Doctrine fest, es ist ein wirklich tolles Tool wenn man objektorientiert Programmieren will und sein Datenmodell über einen ORM-Layer abstrahieren will. Man sollte trotzdem bedenken, dass eine solche Struktur nicht gerade für schwache Live-Maschinen gedacht ist &#8211; ich gehe hier von einem High-Traffic-Projekt aus. Für das Blog um die Ecke oder die Webvisitenkarte sollte ein normales Web-Paket durchaus ausreichen <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> . Beziehen kann man Doctrine aus dem offiziellen <a href="http://trac.phpdoctrine.org/" >SVN Repository</a>.</p>
<p align="left"><a target="_blank" class="tt" href="http://twitter.com/home/?status=Doctrine+w%C3%A4chst+und+gedeiht+http://bit.ly/c3O93Z" title="Post to Twitter"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-twitter-micro3.png" alt="Post to Twitter" /></a> <a target="_blank" class="tt" href="http://delicious.com/post?url=http://www.alexander-stelter.de/blog/155-doctrine-wachst-und-gedeiht/&amp;title=Doctrine+w%C3%A4chst+und+gedeiht" title="Post to Delicious"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-delicious-micro3.png" alt="Post to Delicious" /></a> <a target="_blank" class="tt" href="http://digg.com/submit?url=http://www.alexander-stelter.de/blog/155-doctrine-wachst-und-gedeiht/&amp;title=Doctrine+w%C3%A4chst+und+gedeiht" title="Post to Digg"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-digg-micro3.png" alt="Post to Digg" /></a> <a target="_blank" class="tt" href="http://www.facebook.com/share.php?u=http://www.alexander-stelter.de/blog/155-doctrine-wachst-und-gedeiht/&amp;t=Doctrine+w%C3%A4chst+und+gedeiht" title="Post to Facebook"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-facebook-micro3.png" alt="Post to Facebook" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexander-stelter.de/blog/155-doctrine-wachst-und-gedeiht/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DBMS spezifisches SQL im Doctrine Query</title>
		<link>http://www.alexander-stelter.de/blog/147-dbms-spezifisches-sql-im-doctrine-query/</link>
		<comments>http://www.alexander-stelter.de/blog/147-dbms-spezifisches-sql-im-doctrine-query/#comments</comments>
		<pubDate>Thu, 31 Jan 2008 19:47:00 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[sql standard]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.alexander-stelter.de/blog/?p=147</guid>
		<description><![CDATA[Wer mit Doctrine arbeitet, der vermisst es ab und an, die Datenbankmanagement-System spezifischen SQL-Funktionen verwenden zu können, da diese nativ vom Doctrine-Query-Parser angemeckert werden, da sie nicht zum SQL-Standard gehören. Jetzt hatte ich wieder den Fall, dass ich einen simplen Select hatte, in dem ich entscheiden mußte, ob ich das Datum der Einstellung oder das [...]]]></description>
			<content:encoded><![CDATA[<p>Wer mit <a href="http://www.phpdoctrine.net" >Doctrine</a> arbeitet, der vermisst es ab und an, die Datenbankmanagement-System spezifischen <a href="http://de.wikipedia.org/wiki/SQL" >SQL</a>-Funktionen verwenden zu können, da diese nativ vom Doctrine-Query-Parser angemeckert werden, da sie nicht zum SQL-Standard gehören.</p>
<p>Jetzt hatte ich wieder den Fall, dass ich einen simplen Select hatte, in dem ich entscheiden mußte, ob ich das Datum der Einstellung oder das Datum der Aktualisierung des Datensatzes zum Sortieren benutze. Das verlangt einen Vergleich im Query, den man in SQL folgendermaßen abfangen kann:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> i<span style="color: #66cc66;">.*,</span> <span style="color: #993333; font-weight: bold;">IF</span><span style="color: #66cc66;">&#40;</span>i<span style="color: #66cc66;">.</span>date_created <span style="color: #66cc66;">&gt;</span> i<span style="color: #66cc66;">.</span>date_updated<span style="color: #66cc66;">,</span> i<span style="color: #66cc66;">.</span>date_created <span style="color: #66cc66;">,</span> date_updated<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> date_compare <span style="color: #993333; font-weight: bold;">FROM</span> item <span style="color: #993333; font-weight: bold;">AS</span> i <span style="color: #993333; font-weight: bold;">ORDER</span> <span style="color: #993333; font-weight: bold;">BY</span> date_compare</pre></td></tr></table></div>

<p>Das in einen Doctrine-Query gepackt sieht so aus:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Query</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Doctrine_Query<span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">select</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'i.*, IF(i.date_created &gt; i.date_updated, i.date_created , date_updated) as date_compare'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'Db_Item i'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">orderBy</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'date_compare'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">FETCH_ARRAY</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Das so ausgeführt wirft eine Exception, weil Doctrine mit dem Funktionsaufruf IF nicht zurecht kommt, da sie nicht zum Standard gehört. Jetzt habe ich bisher immer einen Workarround gefunden, doch diesmal wollte ich mich damit nicht abgeben. Nach einiger Recherche kam ich auf ein <a href="http://www.symforc.com/post/2007/10/28/Using-aggregate-functions-with-sfDoctrine " >Blog</a>, welches sich um sfDoctrine dreht (das <a href="http://www.symfony-project.org/" >Symfony</a> Plugin basierend auf Doctrine). Hier ist genau dieses Problem beschrieben und es wird eine Option beschrieben, mit der man beeinflussen kann, wie sehr der Doctrine Parser auf Kompatibilität zu anderen DBMS achtet.</p>
<p>Folgendes Beispiel funktioniert wie gewollt:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">Doctrine_Manager<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #339933;">-&gt;</span><span style="color: #004000;">setAttribute</span><span style="color: #009900;">&#40;</span>Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">ATTR_PORTABILITY</span><span style="color: #339933;">,</span> Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">PORTABILITY_ALL</span> ^ Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">PORTABILITY_EXPR</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
<span style="color: #000088;">$Query</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Doctrine_Query<span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">select</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'i.*, IF(i.date_created &gt; i.date_updated, i.date_created , date_updated) as date_compare'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'Db_Item i'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">orderBy</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'date_compare'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">FETCH_ARRAY</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Man kann also die Portability über das Entfernen des Flags PORTABILITY_EXPR beeinflussen und damit verlangen, dass der Doctrine-Query-Parser auf solche Dinge nicht mehr achtet. Da lohnt sich vielleicht sogar der Blick in den Source bzw. die Api-Doku, vielleicht finden sich ja noch mehr solche Einstellungen <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p>Ich hoffe anderen damit helfen zu können,  wie mir der Blog-Eintrag <a href="http://www.symforc.com" >Symforc</a> geholfen hat <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p align="left"><a target="_blank" class="tt" href="http://twitter.com/home/?status=DBMS+spezifisches+SQL+im+Doctrine+Query+http://bit.ly/aOmHRb" title="Post to Twitter"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-twitter-micro3.png" alt="Post to Twitter" /></a> <a target="_blank" class="tt" href="http://delicious.com/post?url=http://www.alexander-stelter.de/blog/147-dbms-spezifisches-sql-im-doctrine-query/&amp;title=DBMS+spezifisches+SQL+im+Doctrine+Query" title="Post to Delicious"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-delicious-micro3.png" alt="Post to Delicious" /></a> <a target="_blank" class="tt" href="http://digg.com/submit?url=http://www.alexander-stelter.de/blog/147-dbms-spezifisches-sql-im-doctrine-query/&amp;title=DBMS+spezifisches+SQL+im+Doctrine+Query" title="Post to Digg"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-digg-micro3.png" alt="Post to Digg" /></a> <a target="_blank" class="tt" href="http://www.facebook.com/share.php?u=http://www.alexander-stelter.de/blog/147-dbms-spezifisches-sql-im-doctrine-query/&amp;t=DBMS+spezifisches+SQL+im+Doctrine+Query" title="Post to Facebook"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-facebook-micro3.png" alt="Post to Facebook" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexander-stelter.de/blog/147-dbms-spezifisches-sql-im-doctrine-query/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Doctrine RC1 == Doctrine Beta</title>
		<link>http://www.alexander-stelter.de/blog/118-doctrine-rc1-doctrine-beta/</link>
		<comments>http://www.alexander-stelter.de/blog/118-doctrine-rc1-doctrine-beta/#comments</comments>
		<pubDate>Tue, 13 Nov 2007 20:36:11 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://www.alexander-stelter.de/blog/?p=118</guid>
		<description><![CDATA[Nachdem ich vor einer Weile berichtet hatte, dass der erste Release Candidate von Doctrine veröffentlicht wurde, habe ich heute nach einer Weile nochmal ins Blog der Entwickler gesehen und gelesen, dass sie mit dem Verkünden des RC1 wohl etwas voreilig waren. Ich nehme mal an sie meinen den 30. November. Sie haben nun kurzerhand aus [...]]]></description>
			<content:encoded><![CDATA[<p>Nachdem ich vor einer Weile <a href="http://www.alexander-stelter.de/blog/archives/79-Doctrine-RC1-veroeffentlicht.html">berichtet</a> hatte, dass der erste Release Candidate von <a href="http://www.phpdoctrine.net">Doctrine</a> veröffentlicht wurde, habe ich heute nach einer Weile nochmal ins <a href="http://doctrine.pengus.net/index.php/blog/">Blog</a> der Entwickler gesehen und gelesen, dass sie mit dem Verkünden des RC1 wohl etwas <a href="http://doctrine.pengus.net/index.php/blog/beta-2">voreilig</a> waren.  Ich nehme mal an sie meinen den 30. November. Sie haben nun kurzerhand aus dem RC1 ein Beta1 gemacht und haben sich damit selbst wieder die Möglichkeit gegeben &#8211; ohne großes Trara &#8211; Api-Änderungen zu machen, die die Rückwärtskompatibilität zerstören. Eine Beta2 ist für den 31. November <a href="http://doctrine.pengus.net/index.php/blog/beta-2">angekündigt</a> &#8211; ja, das steht da so <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p>Just heute mußte ich feststellen, dass die Rückwärtskompatibilität schon gelitten hat, denn nach einem Update auf die neuste Revision funktionierte die Anwendung nicht mehr. Ich habe es mir erstmal gespart das zu debuggen und die alte Version zurückgespielt und hebe mir diesen Spaß mal für später auf. Im Prinzip finde ich das nicht schlimm, denn man setzt diese Version ja auf eigene Gefahr ein, jedoch dann einen Rückschritt von einem lang angekündigten RC auf eine Beta zu machen finde ich doch merkwürdig, war da jemand zu voreilig? Das hält mich natürlich nicht davon ab Doctrine weiter zu verwenden ..</p>
<p>Was ich noch erwähnen will, dass ich sehr begeistert von der neuen Webseite bin, die offenkundig auf <a href="http://www.symfony-project.com/">Symfony</a> basiert. Endlich gibt es eine Api-Doku und ein neues Manual, mit dem man besser arbeiten kann, wie ich finde. Mal schauen, wie es weiter geht ..</p>
<p align="left"><a target="_blank" class="tt" href="http://twitter.com/home/?status=Doctrine+RC1+%3D%3D+Doctrine+Beta+http://bit.ly/9HRzIT" title="Post to Twitter"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-twitter-micro3.png" alt="Post to Twitter" /></a> <a target="_blank" class="tt" href="http://delicious.com/post?url=http://www.alexander-stelter.de/blog/118-doctrine-rc1-doctrine-beta/&amp;title=Doctrine+RC1+%3D%3D+Doctrine+Beta" title="Post to Delicious"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-delicious-micro3.png" alt="Post to Delicious" /></a> <a target="_blank" class="tt" href="http://digg.com/submit?url=http://www.alexander-stelter.de/blog/118-doctrine-rc1-doctrine-beta/&amp;title=Doctrine+RC1+%3D%3D+Doctrine+Beta" title="Post to Digg"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-digg-micro3.png" alt="Post to Digg" /></a> <a target="_blank" class="tt" href="http://www.facebook.com/share.php?u=http://www.alexander-stelter.de/blog/118-doctrine-rc1-doctrine-beta/&amp;t=Doctrine+RC1+%3D%3D+Doctrine+Beta" title="Post to Facebook"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-facebook-micro3.png" alt="Post to Facebook" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexander-stelter.de/blog/118-doctrine-rc1-doctrine-beta/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Enterprise: ORM in PHP mit Doctrine #5</title>
		<link>http://www.alexander-stelter.de/blog/89-enterprise-orm-in-php-mit-doctrine-5/</link>
		<comments>http://www.alexander-stelter.de/blog/89-enterprise-orm-in-php-mit-doctrine-5/#comments</comments>
		<pubDate>Mon, 24 Sep 2007 18:18:32 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[baumstruktur]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[nestedset]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://www.alexander-stelter.de/blog/?p=89</guid>
		<description><![CDATA[Achtung:Dieses Turorial bezieht sich auf eine veraltete Version von Doctrine und funktioniert vermutlich mit den neueren 1.x und späteren 2.x Releasen nicht mehr. Nachdem wir uns in den letzten Beiträgen die generelle Funktionsweise von Doctrine angesehen haben, wollen wir uns nun die weiterführenden Features ansehen. Heute beginnen wir mit dem NestedSet. Mit diesem ist es [...]]]></description>
			<content:encoded><![CDATA[<p style="border: #ff0000 1px dotted; padding: 4px; color: #ff0000; font-weight: bold;">Achtung:<br />Dieses Turorial bezieht sich auf eine veraltete Version von <a href="http://www.doctrine-project.org/">Doctrine</a> und funktioniert vermutlich mit den neueren 1.x und späteren 2.x Releasen nicht mehr.</p>
<p>Nachdem wir uns in den letzten Beiträgen die generelle Funktionsweise von <a href="http://www.phpdoctrine.net" >Doctrine</a> <a href="http://www.alexander-stelter.de/blog/archives/67-Enterprise-ORM-in-PHP-mit-Doctrine-4.html" >angesehen</a> haben, wollen wir uns nun die weiterführenden Features ansehen. Heute beginnen wir mit dem <a href="http://de.wikipedia.org/wiki/Nested_set" >NestedSet</a>. Mit diesem ist es möglich eine Baumstruktur datenbankseitig abzubilden, zu durchwandern und diese zu ändern. Doctrine bringt dieses Feature nativ mit. Hierbei sei gesagt, dass diese Komponente sich noch ständigen Änderungen unterzieht. Für mein Beispiel verwende ich die Revision <strong>2630</strong>, die ich aus dem SVN ausgecheckt habe.</p>
<p>In diesem Beispiel nehmen wir einen Kategoriebaum, in den wir die Produkte aus den vorherigen Beispielen einordnen könnten. Ich lege den Fokus aber nur auf den Baum und die Kategorien, die Verknüpfung zwischen Kategorie und Produkt stellt dann später nur noch eine 1:n-Beziehung dar, falls Verständnisprobleme auftreten, kann ich das gerne im Einzelfall per E-Mail schildern <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .<span id="more-89"></span>Legen wir also zunächst, wie bei den anderen Beispielen auch, die Datenbanktabellen mittels SQL an und danach die PHP Klassen. </p>
<p>Die SQL Querys sind eigentlich nicht spektakulär. Zur Tabelle cattree sei zu sagen, dass die Felder lft, rgt, level und root_id von Doctrine selber gesetzt werden und wir uns nicht drum kümmern müssen. lft und rgt geben die Range der jeweiligen Einträge an. Die root_id verwaltet die einzelnen Bäume. Wir können mittels Doctrine in einer Tabelle mehrere verschiedene Bäume verwalten. Der Flexibilität halber verwende ich das immer direkt. Dann kann man später immernoch einen Baum hinzufügen, wenn nötig. Hier also die SQL Querys:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`cat`</span> <span style="color: #66cc66;">&#40;</span>
<span style="color: #ff0000;">`id`</span> BIGINT <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span> <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">,</span>
<span style="color: #ff0000;">`name`</span> VARCHAR<span style="color: #66cc66;">&#40;</span> <span style="color: #cc66cc;">255</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span>
<span style="color: #66cc66;">&#41;</span> ENGINE <span style="color: #66cc66;">=</span> MYISAM ;
&nbsp;
&nbsp;
&nbsp;
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`cattree`</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">`id`</span> bigint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`lft`</span> bigint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`rgt`</span> bigint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`category_id`</span> bigint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`level`</span> bigint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`root_id`</span> bigint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span>  <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>MyISAM;</pre></td></tr></table></div>

<p>Kommen wir nun zu den Doctrine Records. Die Kategorie-Tabelle ist auch unspektakulär. Man kann natürlich den Namen auch direkt im Baum speichern, aber über eine zusätzliche Verknüpfung ist das ganze noch ein wenig flexibler <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span>
	Data_Db_Cat
<span style="color: #000000; font-weight: bold;">extends</span>
	Doctrine_Record
<span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setTableDefinition
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTableName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cat'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'primary'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'unsigned'</span> <span style="color: #339933;">&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'autoincrement'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'string'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">255</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setUp
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Kommen wir nun zum Baum selbst. Hier sehen wir kleine Differenzen zu den &#8220;normalen&#8221; Records. Wir müssen hier nur die ID, category_id und root_id selber definieren. Wenn wir nur einen Baum verwalten möchten, können wir die root_id auch weglassen. Zusätzlich sagen wir der Klasse, dass sie als NestedSet fungieren soll (actAs()) und übergeben, dass wir mehrere Bäume verwalten wollen und wie die root-Ebene heißen soll. Zu guterletzt verknüpfen wir den Baum mit der Kategorie und fertig ist das NestedSet:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span>
	Data_Db_Cattree
<span style="color: #000000; font-weight: bold;">extends</span>
	Doctrine_Record
<span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setTableDefinition
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTableName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'cattree'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'primary'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'unsigned'</span> <span style="color: #339933;">&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'autoincrement'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'category_id'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">8</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'hasManyRoots'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'rootColumnName'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'root_id'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">actAs</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'NestedSet'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setUp
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasMany</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_Cat'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'category_id'</span><span style="color: #339933;">,</span>
                                    <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Legen wir also nun einen neuen Root-Node an. Dazu müssen wir zunächst eine neue Kategorie anlegen, diese jedoch nicht speichern. Beim Übergeben eines Records an den Baum wird eine Autosave-Methode aufgerufen, die das Speichern für uns übernimmt.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Category</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_Cat<span style="color: #339933;">;</span>
<span style="color: #000088;">$Category</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Meine RootNode'</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Nachdem wir eine Kategorie angelegt haben, legen wir einen Record in der Tree-Tabelle an und weisen ihr den betreffenden Eintrag zu, auch hier müssen wir nicht speichern.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$RootNode</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_Cattree<span style="color: #339933;">;</span>
<span style="color: #000088;">$RootNode</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Data_Db_Cat</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Category</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Damit das ganze jetzt aber auch was mit unserem Baum zu tun hat, müssen wir nun die NestedSet-Struktur anlegen, dazu holen wir uns erstmal das Tabellen-Objekt mittels getTable() und führen darauf dann ein getTree() aus. Dann können wir mittels createRoot() den Knoten anlegen und speichern.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Tree</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Connection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_Cattree'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTree</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Tree</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createRoot</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$RootNode</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Jetzt wollen wir mal ein paar Einträge in den Baum schreiben und diese danach wieder auslesen. Dazu müssen wir uns zunächst den Baum abholen, bzw. den Root-Knoten. Dieser hat die Id 1, das haben wir uns gemerkt.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$RootNode</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Connection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_Cattree'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Für das Arbeiten auf dem Baum sind hier nicht die Kategorie-Ids ausschlaggebend, sondern die Node-Ids. Man kann aber über eine Querverknüpfung natürlich von den Kategorien auf die Node-Ids kommen.</p>
<p>Jetzt wollen wir 10 Ebenen mit jeweils 5 Unterebenen einziehen. Dazu verwenden wir zwei verschachtelte For-Schleifen. Das Konzept bleibt gleich: Kategorie anlegen, Node-Eintrag anlegen, einfügen. Hier verwenden wir aber zum Einfügen nicht mehr createRoot() sondern insertAsFirstChildOf. Dies wird auf den Node-Record ausgeführt. Hier wird zusätzlich noch eine Zwischenebene verwendet. Zunächst haben wir nur den Record. Mittels getNode() auf den Record sagen wir, dass wir die Baum-Funktionalitäten in Anspruch nehmen wollen und wandeln den Record in einen NestedSet Record um und fügen diesen dann ein:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">for</span>
<span style="color: #009900;">&#40;</span>
	<span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">10</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span>
<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$Category</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_Cat<span style="color: #339933;">;</span>
	<span style="color: #000088;">$Category</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Ebene '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'-1'</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000088;">$NodeRecord</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_Cattree<span style="color: #339933;">;</span>
	<span style="color: #000088;">$NodeRecord</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Data_Db_Cat</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Category</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000088;">$NodeRecord</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getNode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">insertAsFirstChildOf</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$RootNode</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">for</span>
	<span style="color: #009900;">&#40;</span>
		<span style="color: #000088;">$x</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$x</span> <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">5</span><span style="color: #339933;">;</span> <span style="color: #000088;">$x</span><span style="color: #339933;">++</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$InnerCategory</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_Cat<span style="color: #339933;">;</span>
		<span style="color: #000088;">$InnerCategory</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Ebene '</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'-2-'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$x</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #000088;">$InnerNode</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_Cattree<span style="color: #339933;">;</span>
		<span style="color: #000088;">$InnerNode</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Data_Db_Cat</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$InnerCategory</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #000088;">$InnerNode</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getNode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">insertAsFirstChildOf</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$NodeRecord</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Nun wollen wir auf dem Baum lesen. Mittels fetchBranch können wir an einem bestimmten Punkt einsteigen und ab da alle Kindelemente auslesen. Das ist für den Direkteinstieg in den Baum ziemlich praktisch und es ist keine Rekursion nötig. Das komplette Ausgeben des Baums lösen wir gleich mit einer Funktion (normalerweise ist das ja teil einer Klasse, aber in unserem simplen Beispiel ist es nur eine rekursive Funktion).</p>
<p>Mittels getLevel() auf einen Node, sind wir übrigens immer in der Lage die Tiefe des aktuellen Nodes auszugeben. Natürlich gibt es auch Funktionen, um von einem Node aufwärts zu laufen, dazu gibt es z.B. getParent(), das aber nur am Rande. Schauen wir uns nun das Auslesen eines Teilbaumes an:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Branch</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Connection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_Cattree'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTree</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fetchBranch</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">14</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">foreach</span>
<span style="color: #009900;">&#40;</span>
	<span style="color: #000088;">$Branch</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$Record</span>
<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$Node</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Record</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getNode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #b1b100;">echo</span> <span style="color: #990000;">str_repeat</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">' - '</span><span style="color: #339933;">,</span> <span style="color: #000088;">$Node</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLevel</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>  <span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">' '</span> <span style="color: #339933;">.</span><span style="color: #000088;">$Record</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Data_Db_Cat</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&lt;br /&gt;'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Das Ergebnis zeigt, dass alles korrekt funktioniert:<br />
<blockquote>- Ebene 2-1<br />
- &#8211; Ebene 2-2-4<br />
- &#8211; Ebene 2-2-3<br />
- &#8211; Ebene 2-2-2<br />
- &#8211; Ebene 2-2-1<br />
- &#8211; Ebene 2-2-0</p></blockquote>
<p>Jetzt gehen wir den Baum einmal mit einer rekursiven Funktion durch. Dafür holen wir uns zunächst auch wieder den Root-Node herraus:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$RootNode</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Connection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_Cattree'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Anschließend rufen wir unsere Funktion printTree auf und übergeben den Knoten. PHP arbeitet hier speicherschonend mit Referenzen. Der übergebene Node ist nur ein Doctrine-Record, also muss in der Funktion zunächst auch wieder ein getNode() folgen. Danach prüfen wir, ob Kindelemente vorhanden sind (hasChildren()) und geben diese aus. Dann prüfen wir, ob die jeweiligen Kindelemente noch Unterelemente haben und rufen die Funktion anschließend mit diesem Knoten neu auf, eigentlich ganz einfach <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> printTree
<span style="color: #009900;">&#40;</span>
	<span style="color: #000088;">$Record</span>
<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$Node</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Record</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getNode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">if</span>
	<span style="color: #009900;">&#40;</span>
		<span style="color: #000088;">$Node</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLevel</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">echo</span> <span style="color: #990000;">str_repeat</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">' - '</span><span style="color: #339933;">,</span> <span style="color: #000088;">$Node</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLevel</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>  <span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">' '</span> <span style="color: #339933;">.</span><span style="color: #000088;">$Record</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Data_Db_Cat</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&lt;br /&gt;'</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
	<span style="color: #b1b100;">if</span>
	<span style="color: #009900;">&#40;</span>
		<span style="color: #000088;">$Node</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasChildren</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #b1b100;">foreach</span>
		<span style="color: #009900;">&#40;</span>
			<span style="color: #000088;">$Node</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getChildren</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$Child</span>
		<span style="color: #009900;">&#41;</span>
		<span style="color: #009900;">&#123;</span>
			<span style="color: #000088;">$ChildNode</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Child</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getNode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">echo</span> <span style="color: #990000;">str_repeat</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">' - '</span><span style="color: #339933;">,</span> <span style="color: #000088;">$ChildNode</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLevel</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>  <span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">' '</span> <span style="color: #339933;">.</span><span style="color: #000088;">$Child</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Data_Db_Cat</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">name</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&lt;br /&gt;'</span><span style="color: #339933;">;</span>
			<span style="color: #b1b100;">if</span>
			<span style="color: #009900;">&#40;</span>
				<span style="color: #000088;">$ChildNode</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasChildren</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
			<span style="color: #009900;">&#41;</span>
			<span style="color: #009900;">&#123;</span>
				printTree<span style="color: #009900;">&#40;</span><span style="color: #000088;">$Child</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
			<span style="color: #009900;">&#125;</span>
		<span style="color: #009900;">&#125;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000088;">$RootNode</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Connection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_Cattree'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
printTree<span style="color: #009900;">&#40;</span><span style="color: #000088;">$RootNode</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>An der Ausgabe sehen wir, dass alles richtig gelaufen ist (gekürzt, weil zu lang <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> )<br />
<blockquote>Meine RootNode<br />
- Ebene 9-1<br />
- &#8211; Ebene 9-2-4<br />
- &#8211; Ebene 9-2-3<br />
- &#8211; Ebene 9-2-2<br />
- &#8211; Ebene 9-2-1<br />
- &#8211; Ebene 9-2-0<br />
- Ebene 8-1<br />
- &#8211; Ebene 8-2-4<br />
- &#8211; Ebene 8-2-3<br />
- &#8211; Ebene 8-2-2<br />
- &#8211; Ebene 8-2-1<br />
- &#8211; Ebene 8-2-0<br />
- Ebene 7-1<br />
- &#8211; Ebene 7-2-4<br />
- &#8211; Ebene 7-2-3<br />
- &#8211; Ebene 7-2-2<br />
- &#8211; Ebene 7-2-1<br />
- &#8211; Ebene 7-2-0</p></blockquote>
<p>Allerdings sollte man dazu sagen, dass die Sortierung bei diesem Konzept ein wenig problematisch ist, eine Lösung gibt es zwar dafür, aber die würde zu weit führen. Desweiteren kann ich einen Blick in die <a href="http://www.phpdoctrine.net/doctrine/manual/new/?one-page#hierarchical-data" >Doku</a> empfehlen, wo noch weitere tolle Funktionen des NestedSets erklärt sind. (Löschen, verschieben, einfügen an bestimmten Punkten etc.).</p>
<p>Man sollte sich allerdings nicht einbilden, dass NestedSets ultra schnell sind. Hier ist die Flexibilität auf Kosten der Performance entstanden. Durch die Verschachtelung und die Struktur sind Schreiboperationen sehr rechenintensiv, da die Grenzen neu berechnet werden müssen, jedoch ist so ein Kategoriebaum in Kombination mit <a href="http://www.danga.com/memcached/" >memcached</a> (welcher auch bereits in Doctrine implementiert ist und ein Treiber vorhanden ist) doch recht gut benutzbar, eine Empfehlung an alle, die Kategoriebäume mit beliebiger Größe verwalten müssen. Für Leseoperationen ist das Cachen natürlich praktisch, für Schreiboperationen löst es die Probleme nicht, jedoch werden die Tabellen nicht gelockt, wenn geschrieben wird, da das Lesen über den Cache erfolgt.</p>
<p>Fragen beantworte ich natürlich gerne per Mail oder in den Kommentaren <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .</p>
<p align="left"><a target="_blank" class="tt" href="http://twitter.com/home/?status=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%235+http://bit.ly/aOLMMs" title="Post to Twitter"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-twitter-micro3.png" alt="Post to Twitter" /></a> <a target="_blank" class="tt" href="http://delicious.com/post?url=http://www.alexander-stelter.de/blog/89-enterprise-orm-in-php-mit-doctrine-5/&amp;title=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%235" title="Post to Delicious"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-delicious-micro3.png" alt="Post to Delicious" /></a> <a target="_blank" class="tt" href="http://digg.com/submit?url=http://www.alexander-stelter.de/blog/89-enterprise-orm-in-php-mit-doctrine-5/&amp;title=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%235" title="Post to Digg"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-digg-micro3.png" alt="Post to Digg" /></a> <a target="_blank" class="tt" href="http://www.facebook.com/share.php?u=http://www.alexander-stelter.de/blog/89-enterprise-orm-in-php-mit-doctrine-5/&amp;t=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%235" title="Post to Facebook"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-facebook-micro3.png" alt="Post to Facebook" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexander-stelter.de/blog/89-enterprise-orm-in-php-mit-doctrine-5/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Doctrine RC1 veröffentlicht</title>
		<link>http://www.alexander-stelter.de/blog/79-doctrine-rc1-veroffentlicht/</link>
		<comments>http://www.alexander-stelter.de/blog/79-doctrine-rc1-veroffentlicht/#comments</comments>
		<pubDate>Mon, 03 Sep 2007 20:40:50 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[das-ist-drin.de]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[release candidate 1]]></category>

		<guid isPermaLink="false">http://www.alexander-stelter.de/blog/?p=79</guid>
		<description><![CDATA[Wie mein Kollege Fabian Freiburg im das-ist-drin.de Blog berichtet, haben die Entwickler von Doctrine ihr Versprechen wahr gemacht und in der Nacht vom 31. August 2007 den Release Candidate Nummer 1 des gleichnamigen Datenbank ORM Tools für PHP veröffentlicht. Wie ich finde eine sehr respektable Leistung. Ich verfolge das Doctrine Projekt bereits seit der Revision [...]]]></description>
			<content:encoded><![CDATA[<p>Wie mein Kollege Fabian Freiburg im <a href="http://das-ist-drin.de/blog/archives/127-Release-Candidate-des-PHP-ORM-Tools-Doctrine-veroeffentlicht.html" >das-ist-drin.de Blog</a> berichtet, haben die Entwickler von <a href="http://www.phpdoctrine.net" >Doctrine</a> ihr Versprechen wahr gemacht und in der Nacht vom 31. August 2007 den <a href="http://de.wikipedia.org/wiki/Release_Candidate#Release_Candidate" >Release Candidate</a> Nummer 1 des gleichnamigen Datenbank <a href="http://de.wikipedia.org/wiki/ORM" >ORM</a> Tools für <a href="http://de.php.net" >PHP</a> <a href="http://www.phpdoctrine.net/trac/wiki/packages" >veröffentlicht</a>.</p>
<p>Wie ich finde eine sehr respektable Leistung. Ich verfolge das Doctrine Projekt bereits seit der Revision 7xx und bin überrascht, welche Fortschritte ein Projekt in so kurzer Zeit machen kann. Natürlich wurde der Entwicklungsfortschritt von Doctrine sehr durch das Google Summer of Code Projekt im diesen Jahr begünstigt, jedoch muss man auch sagen, dass nicht nur Zeit und Geld notwendig ist, um eine Software stabil zu machen, sondern auch Entwicklergeist und Können und das haben die Entwickler von Doctrine auf jeden Fall schon recht früh bewiesen. Ich kann aus eigener Erfahrung sagen, dass das Entwickeln mit Doctrine zwar ab und an doch noch einiges an Nerven kostet, aber dann, wenn man durchgestiegen ist, doch recht viel Freude macht.</p>
<p>Schauen wir mal wie es weiter geht <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p align="left"><a target="_blank" class="tt" href="http://twitter.com/home/?status=Doctrine+RC1+ver%C3%B6ffentlicht+http://bit.ly/avIdBx" title="Post to Twitter"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-twitter-micro3.png" alt="Post to Twitter" /></a> <a target="_blank" class="tt" href="http://delicious.com/post?url=http://www.alexander-stelter.de/blog/79-doctrine-rc1-veroffentlicht/&amp;title=Doctrine+RC1+ver%C3%B6ffentlicht" title="Post to Delicious"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-delicious-micro3.png" alt="Post to Delicious" /></a> <a target="_blank" class="tt" href="http://digg.com/submit?url=http://www.alexander-stelter.de/blog/79-doctrine-rc1-veroffentlicht/&amp;title=Doctrine+RC1+ver%C3%B6ffentlicht" title="Post to Digg"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-digg-micro3.png" alt="Post to Digg" /></a> <a target="_blank" class="tt" href="http://www.facebook.com/share.php?u=http://www.alexander-stelter.de/blog/79-doctrine-rc1-veroffentlicht/&amp;t=Doctrine+RC1+ver%C3%B6ffentlicht" title="Post to Facebook"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-facebook-micro3.png" alt="Post to Facebook" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexander-stelter.de/blog/79-doctrine-rc1-veroffentlicht/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Enterprise: ORM in PHP mit Doctrine #4</title>
		<link>http://www.alexander-stelter.de/blog/67-enterprise-orm-in-php-mit-doctrine-4/</link>
		<comments>http://www.alexander-stelter.de/blog/67-enterprise-orm-in-php-mit-doctrine-4/#comments</comments>
		<pubDate>Tue, 14 Aug 2007 05:00:00 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[event listener]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://www.alexander-stelter.de/blog/?p=67</guid>
		<description><![CDATA[Achtung:Dieses Turorial bezieht sich auf eine veraltete Version von Doctrine und funktioniert vermutlich mit den neueren 1.x und späteren 2.x Releasen nicht mehr. Nachdem wir uns im letzten Beitrag nochmal mit dem Beziehungen der Datenbanktabellen und Klassen beschäftigt haben, wollen uns heute einem weiteren Kapitel widmen, den Event-Listenern. Sie sind ein einfaches Instrument, die auch [...]]]></description>
			<content:encoded><![CDATA[<p style="border: #ff0000 1px dotted; padding: 4px; color: #ff0000; font-weight: bold;">Achtung:<br />Dieses Turorial bezieht sich auf eine veraltete Version von <a href="http://www.doctrine-project.org/">Doctrine</a> und funktioniert vermutlich mit den neueren 1.x und späteren 2.x Releasen nicht mehr.</p>
<p>Nachdem wir uns im letzten <a href="http://www.alexander-stelter.de/blog/archives/57-Enterprise-ORM-in-PHP-mit-Doctrine-3.html" >Beitrag</a> nochmal mit dem Beziehungen der Datenbanktabellen und Klassen beschäftigt haben, wollen uns heute einem weiteren Kapitel widmen, den Event-Listenern.</p>
<p>Sie sind ein einfaches Instrument, die auch bei vielen <a href="http://de.wikipedia.org/wiki/DBMS" >DBMS</a> durch <a href="http://de.wikipedia.org/wiki/Datenbanktrigger" >Trigger</a> abgebildet sind. Ein praktisches Beispiel schauen wir uns nun einmal an. Wir haben ja eine Produkt-Tabelle und Klasse, hier wollen wir nun eine User-Id speichern, damit wir wissen, welcher User ein Produkt angelegt hat. Zusätzlich möchten wir einen aggregierten Counter für jeden User haben, damit wir nicht bei jedem Request seines Profils alle Produkte summieren müssen, um herrauszufinden, wie viele Produkte ein User angelegt hat. Dies soll natürlich nicht explizit geschehen müssen. Wir möchten, dass einem User automatisch ein Produkt &#8220;gutgeschrieben&#8221; wird, sobald er es anlegt, und es abgezogen wird, wenn er das Produkt löscht.</p>
<p>Hierzu legen wir ein Feld &#8220;product_count&#8221; an, welches beim User selbst abgelegt wird. Beginnen wir nun mit dem Anlegen der User-Klasse und Datenbank-Tabelle:<span id="more-67"></span></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span>
	Data_Db_Users
<span style="color: #000000; font-weight: bold;">extends</span>
	Doctrine_Record
<span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setTableDefinition
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTableName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'users'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'primary'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'unsigned'</span> <span style="color: #339933;">&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'autoincrement'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'username'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'string'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">255</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'firstname'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'string'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">255</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'lastname'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'string'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">255</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'password'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'string'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">255</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'product_count'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">8</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'default'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setUp
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasMany</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_Products'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span>
                                    <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'users_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Die Tabelle Verknüpfen wir direkt über die users.id über die users_id mit der Produkt-Tabelle. Bevor wir uns aber genauer der Produktkklasse widmen, müssen wir noch die Datenbanktabelle mittels SQL in der Datenbank anlegen:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`users`</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">`id`</span> bigint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`username`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> collate latin1_general_ci <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`firstname`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> collate latin1_general_ci <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`lastname`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> collate latin1_general_ci <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`password`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> collate latin1_general_ci <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`product_count`</span> bigint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span>  <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>MyISAM</pre></td></tr></table></div>

<p>Ist dies nun gemacht, legen wir eine Rückverknüpfung für die Produkt-Tabelle an. Hierzu fügen wir zunächst das Feld &#8220;users_id&#8221; in die Klasse Data_Db_Products ein. Dazu muss die folgende Zeile in die Table-Definition eingefügt werden:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'users_id'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">8</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Desweiteren wollen wir die Verknüpfung zur User-Tabelle realisieren, dies tun wir mit folgender Definition in der allerseits bekannten setUp-Methode:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasOne</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_Products'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'users_id'</span><span style="color: #339933;">,</span>
                                    <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Nun sollte noch das Feld in die Tabelle ausgeführt werden, dazu reicht ein Alter-Table-Befehl:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">ALTER TABLE `products` ADD `users_id` BIGINT NOT <span style="color: #009900; font-weight: bold;">NULL</span> AFTER `id` <span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Wenden wir uns nun den Event-Listenern zu. Doctrine unterstützt eine Reihe von Listenern. Eine vollständige Liste findet man im <a href="http://www.phpdoctrine.net/doctrine/manual/new/?one-page=1#event-listeners" >Manual</a>. Ich beschränke mich in meinem Beispiel auf zwei Record-Hooks. Es gibt noch diverse andere Möglichkeiten, die im Manual beschrieben sind. leider mußte ich feststellen, dass zwischen einigen Revisions die separaten Listener-Klassen nicht mehr funktionierten, vielleicht ist dies ja mitlerweile wieder der Fall. Wir beschränken uns auf einen postInsert und einen postDelete-Hook. Im Manual findet sich auch ein Hinweis, dass dieser Bereich gerade under heavy Construction ist, es empfielt sich also öfters mal ins Manual zu sehen.</p>
<p>Erstellen wir nun zunächst einen neuen User und speichern diesen persistent in die Datenbank. Hierbei kommen bisher keine Techniken zum Einsatz, die in vorherigen Einträgen nicht schon beschrieben worden wären. Der Vollständigkeit halber, hier aber nochmal ein vollständiges Beispiel:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Users</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_Users<span style="color: #339933;">;</span>
<span style="color: #000088;">$Users</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;username&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'User01'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Users</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;firstname&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'John'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Users</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;lastname&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Doe'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Users</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;password&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">md5</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'test12345'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Users</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Jetzt legen wir einen postInsert Listener an, der reagiert, NACHDEM ein Eintrag neu eingefügt wurde, wir erhöhen damit den Counter des Produkts und speichern es wieder. Das Gegenstück dazu heißt postDelete und wird nach dem Löschen eines Produkts ausgeführt und macht genau das Gegenstück von dem, was postInsert macht. Fügen wir nun diese beiden Methoden in die Produkt-Datenbank-Klasse ein:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> postInsert
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$Users</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$GLOBALS</span> <span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;Connection&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_Users'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;users_id&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$Users</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;product_count&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Users</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;product_count&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">+</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$Users</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> postDelete
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$Users</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$GLOBALS</span> <span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;Connection&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_Users'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;users_id&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$Users</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;product_count&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Users</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;product_count&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$Users</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
	<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p> Dies testen wir nun mit dem folgenden Code:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Products</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_Products<span style="color: #339933;">;</span>
<span style="color: #000088;">$Products</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'MyProduct01'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Products</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;users_id&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Users</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;id&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Products</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$Products</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Wir fügen nun ein Produkt ein und löschen es danach wieder. Das bedeutet, dass der Counter &#8220;product_count&#8221; weiterhin bei 0 stehen bleibt. Kommentieren wir nun das Delete aus, wird der Counter hochgezählt. Wir haben also alles richtig gemacht <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .<br />
Weitere Einsatzzwecke für die Listener sind weit gesteckt. Von History-Generierung über Datumsaktualisierung kann man einiges machen, da bleibt der eigenen Phantasie und Logik keine Grenze gesetzt, viel Spaß beim Ausprobieren.</p>
<p>Ich kann jetzt noch nicht konkret sagen, zu welchem Doctrine-Thema die Reihe fortgesetzt wird, aber sie wird fortgesetzt <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</p>
<p align="left"><a target="_blank" class="tt" href="http://twitter.com/home/?status=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%234+http://bit.ly/a7f8k7" title="Post to Twitter"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-twitter-micro3.png" alt="Post to Twitter" /></a> <a target="_blank" class="tt" href="http://delicious.com/post?url=http://www.alexander-stelter.de/blog/67-enterprise-orm-in-php-mit-doctrine-4/&amp;title=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%234" title="Post to Delicious"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-delicious-micro3.png" alt="Post to Delicious" /></a> <a target="_blank" class="tt" href="http://digg.com/submit?url=http://www.alexander-stelter.de/blog/67-enterprise-orm-in-php-mit-doctrine-4/&amp;title=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%234" title="Post to Digg"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-digg-micro3.png" alt="Post to Digg" /></a> <a target="_blank" class="tt" href="http://www.facebook.com/share.php?u=http://www.alexander-stelter.de/blog/67-enterprise-orm-in-php-mit-doctrine-4/&amp;t=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%234" title="Post to Facebook"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-facebook-micro3.png" alt="Post to Facebook" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexander-stelter.de/blog/67-enterprise-orm-in-php-mit-doctrine-4/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Löschen über Doctrine_Query</title>
		<link>http://www.alexander-stelter.de/blog/66-loschen-uber-doctrine_query/</link>
		<comments>http://www.alexander-stelter.de/blog/66-loschen-uber-doctrine_query/#comments</comments>
		<pubDate>Mon, 13 Aug 2007 19:22:03 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[delete]]></category>
		<category><![CDATA[doctrine_query]]></category>
		<category><![CDATA[löschen]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://www.alexander-stelter.de/blog/?p=66</guid>
		<description><![CDATA[Nach meinem bisherigen Wissen, konnte man nur Datensätze über Doctrine löschen, wenn man sie zuvor über eine Doctrine-Collection selektiert hat, dies konnte dann mittels finder oder Query passieren: 1 2 $Collection = $Connection-&#62;getTable&#40;'Data_Db_User'&#41;-&#62;find&#40;1&#41;; $Collection-&#62;delete&#40;&#41;; oder 1 2 3 4 5 $Query = new Doctrine_Query; $Query-&#62;from&#40;'Data_Db_User u'&#41;; $Query-&#62;where &#40;'u.id = 1'&#41;; $Result = $Query-&#62;execute&#40;&#41;; $Result-&#62;delete&#40;&#41;; Das [...]]]></description>
			<content:encoded><![CDATA[<p>Nach meinem bisherigen Wissen, konnte man nur Datensätze über Doctrine löschen, wenn man sie zuvor über eine Doctrine-Collection selektiert hat, dies konnte dann mittels finder oder Query passieren:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Collection</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Connection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_User'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Collection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>oder</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Query</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Doctrine_Query<span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_User u'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">where</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'u.id = 1'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Result</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Das war meiner Meinung nach ziemlich umständlich, doch ein Blick in die Doku der jetzigen (neueren) Revision lies mich erfahren, dass man nun auch einfach über einen Query löschen kann. Dies kommt nun der &#8220;normalen&#8221; Art und Weise der Löschung sehr nahe. Vielleicht war es bisher auch möglich, aber leider nicht dokumentiert:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Query</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Doctrine_Query<span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">delete</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_User u'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">where</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'u.id = 1'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Das ist meiner Meinung nach ein eindeutiger Fortschritt und erspart einem die Umwege über die Doctrine_Collection, welche dann wieder Performance frißt. Also ein Schritt in die richtige Richtung <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</p>
<p align="left"><a target="_blank" class="tt" href="http://twitter.com/home/?status=L%C3%B6schen+%C3%BCber+Doctrine_Query+http://bit.ly/dek21Z" title="Post to Twitter"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-twitter-micro3.png" alt="Post to Twitter" /></a> <a target="_blank" class="tt" href="http://delicious.com/post?url=http://www.alexander-stelter.de/blog/66-loschen-uber-doctrine_query/&amp;title=L%C3%B6schen+%C3%BCber+Doctrine_Query" title="Post to Delicious"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-delicious-micro3.png" alt="Post to Delicious" /></a> <a target="_blank" class="tt" href="http://digg.com/submit?url=http://www.alexander-stelter.de/blog/66-loschen-uber-doctrine_query/&amp;title=L%C3%B6schen+%C3%BCber+Doctrine_Query" title="Post to Digg"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-digg-micro3.png" alt="Post to Digg" /></a> <a target="_blank" class="tt" href="http://www.facebook.com/share.php?u=http://www.alexander-stelter.de/blog/66-loschen-uber-doctrine_query/&amp;t=L%C3%B6schen+%C3%BCber+Doctrine_Query" title="Post to Facebook"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-facebook-micro3.png" alt="Post to Facebook" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexander-stelter.de/blog/66-loschen-uber-doctrine_query/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enterprise: ORM in PHP mit Doctrine #3</title>
		<link>http://www.alexander-stelter.de/blog/57-enterprise-orm-in-php-mit-doctrine-3/</link>
		<comments>http://www.alexander-stelter.de/blog/57-enterprise-orm-in-php-mit-doctrine-3/#comments</comments>
		<pubDate>Thu, 02 Aug 2007 19:13:35 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://www.alexander-stelter.de/blog/?p=57</guid>
		<description><![CDATA[Achtung:Dieses Turorial bezieht sich auf eine veraltete Version von Doctrine und funktioniert vermutlich mit den neueren 1.x und späteren 2.x Releasen nicht mehr. Nachdem im letzten Beitrag das Thema 1:n Beziehungen beleuchtet haben, wenden wir uns nun der letzten Beziehungsart zu, die man mit einer Datenbankrelation abbilden kann, nämlich der n:m Beziehung. Als Basis dazu [...]]]></description>
			<content:encoded><![CDATA[<p style="border: #ff0000 1px dotted; padding: 4px; color: #ff0000; font-weight: bold;">Achtung:<br />Dieses Turorial bezieht sich auf eine veraltete Version von <a href="http://www.doctrine-project.org/">Doctrine</a> und funktioniert vermutlich mit den neueren 1.x und späteren 2.x Releasen nicht mehr.</p>
<p>Nachdem im letzten <a href="http://www.alexander-stelter.de/blog/archives/55-Enterprise-ORM-in-PHP-mit-Doctrine-2.html" >Beitrag</a> das Thema 1:n Beziehungen beleuchtet haben, wenden wir uns nun der letzten Beziehungsart zu, die man mit einer Datenbankrelation abbilden kann, nämlich der n:m Beziehung.<br />
Als Basis dazu nehmen wir die Klassen und Datenbanktabellen, die wir in den letzten beiden Artikeln erstellt haben und tauchen nun wieder in die Anwendung ein. Wir möchten nun festhalten, dass die verschiedenen Variationen (Light, Zero) eines Produkts (Coca Cola) in verschiedenen Handelsunternehmen (POS = Point of Sale) verkauft werden.<br />
Dies lässt sich ja auf Datenbankebene mit einer Verknüpfungstabelle darstellen, die die beiden Fremdschlüssel von den Jeweiligen Entitäten enthält und diese so mit einander verknüpft. Auf diese Weise können beliebige Kombinationen in beliebiger Anzahl dargestellt werden. Als Schutz vor Doppeleinträgen machen wir aus dem Datensatz in der Verknüpfungstabelle einen kombinierten Primärschlüssel, sodass hier Datenbankseitig bereits vor Doppeleinträgen geschützt wird. Doctrine reagiert beim Versuch einen Doppeleintrag anzulegen mit einer Exception, die von PDO geworfen wird.</p>
<p>Steigen wir aber nun in die Entwicklung der Doctrine Klassen ein.<span id="more-57"></span>Legen wir nun zunächst die Klasse für unseren Point of Sale an. Das ist eine einfache Doctrine-Klasse, wie wir sie so kennen. Eine Besonderheit dabei ist der neue Relationstyp:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">         <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasMany</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_ProductsVariations'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'pos_id'</span><span style="color: #339933;">,</span>
                                    <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'products_variations_id'</span><span style="color: #339933;">,</span>
                                    <span style="color: #0000ff;">'refClass'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Data_Db_ProductsVariations2pos'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Hier sehen wir die Besonderheit der Relation. Wir geben also nicht direkt den Schlüssel der fremden Tabelle an (in diesem Falle wäre es auch einfach nur id) sondern den Namen des Fremdschlüssels, wie er in der Verknüpfungstabelle heißt. Ebenso geben wir für die eigene Tabelle nicht die id an, sondern auch den Namen des Schlüssels, wie er in der Verknüpfungstabelle lautet. Zu guterletzt benennen wir die Verknüpfungsklasse noch über refClass. Im Ganzen sieht die Klasse dann so aus:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span>
	Data_Db_Pos
<span style="color: #000000; font-weight: bold;">extends</span>
	Doctrine_Record
<span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setTableDefinition
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTableName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'pos'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'primary'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'unsigned'</span> <span style="color: #339933;">&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'autoincrement'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'string'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">255</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'description'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'string'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">3000</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'date_created'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'timestamp'</span> <span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setUp
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasMany</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_ProductsVariations'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'pos_id'</span><span style="color: #339933;">,</span>
                                    <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'products_variations_id'</span><span style="color: #339933;">,</span>
                                    <span style="color: #0000ff;">'refClass'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Data_Db_ProductsVariations2pos'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Um die Verknüpfung nicht zu einseitig zu gestalten, fügen wir in die Data_Db_ProductsVariations noch die Gegenverknüpfung ein:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasMany</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_Pos'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'products_variations_id'</span><span style="color: #339933;">,</span>
                                    <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'pos_id'</span><span style="color: #339933;">,</span>
                                    <span style="color: #0000ff;">'refClass'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Data_Db_ProductsVariations2pos'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Nun haben wir Anwendungsseitig schonmal die halbe Miete erledigt, jetzt legen wir zunächst mal die Tabelle in der Datenbank an. Dazu verwenden wir folgenden SQL-Query:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`pos`</span> <span style="color: #66cc66;">&#40;</span>
<span style="color: #ff0000;">`id`</span> bigint<span style="color: #66cc66;">&#40;</span> <span style="color: #cc66cc;">20</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span> <span style="color: #66cc66;">,</span>
<span style="color: #ff0000;">`name`</span> varchar<span style="color: #66cc66;">&#40;</span> <span style="color: #cc66cc;">255</span> <span style="color: #66cc66;">&#41;</span> COLLATE latin1_general_ci <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">,</span>
<span style="color: #ff0000;">`description`</span> tinytext COLLATE latin1_general_ci <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">,</span>
<span style="color: #ff0000;">`date_created`</span> datetime <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">,</span>
<span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">`id`</span> <span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE <span style="color: #66cc66;">=</span> MYISAM <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET <span style="color: #66cc66;">=</span> latin1 COLLATE <span style="color: #66cc66;">=</span> latin1_general_ci;</pre></td></tr></table></div>

<p>Jetzt müssen wir als nächstes, bevor wir mit den Daten arbeiten können, die Verknüpfungstabelle realisieren. Dazu legen wir eine &#8220;normale&#8221; Doctrine-Klasse an, die komplett ohne Relationen auskommt, da die Verknüpfungen über die Entitäten selbst realisiert werden. Die Klasse und somit auch die Tabelle, besteht also auch nur aus zwei Spalten und sieht folgendermaßen aus:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span>
	Data_Db_ProductsVariations2pos
<span style="color: #000000; font-weight: bold;">extends</span>
	Doctrine_Record
<span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setTableDefinition
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTableName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'products_variations2pos'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'products_variations_id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'primary'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'unsigned'</span> <span style="color: #339933;">&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'pos_id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'primary'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'unsigned'</span> <span style="color: #339933;">&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Via Sql legen wir dann noch die Tabelle in der Datenbank an. Anschließend sind wir startklar und können Daten einfügen und auslesen:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`products_variations2pos`</span> <span style="color: #66cc66;">&#40;</span>
<span style="color: #ff0000;">`products_variations_id`</span> BIGINT <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">,</span>
<span style="color: #ff0000;">`pos_id`</span> BIGINT <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">,</span>
<span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">`products_variations_id`</span> <span style="color: #66cc66;">,</span> <span style="color: #ff0000;">`pos_id`</span> <span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE <span style="color: #66cc66;">=</span> MYISAM ;</pre></td></tr></table></div>

<p>Jetzt wollen wir erstmal ein Produkt auslesen, damit wir weiter arbeiten können, dies erledigen wir per Finder. Wir nehmen das Beispiel, dass wir Coca Cola mit der ID 1 eingefügt haben:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Product</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Connection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'Data_Db_Products'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span> <span style="color: #009900;">&#40;</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Jetzt haben wir ein Produkt im Speicher mit dem wir weiter arbeiten können. Nun wollen wir zunächst zwei POS einfügen. Dazu dient uns folgender Codeschnipsel:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Aldi</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_Pos<span style="color: #339933;">;</span>
<span style="color: #000088;">$Aldi</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Aldi Sued'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Aldi</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;description&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Aldi im Sueden und Westen Deutschlands'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Aldi</span><span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'date_created'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Y-m-d'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Aldi</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$Lidl</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_Pos<span style="color: #339933;">;</span>
<span style="color: #000088;">$Lidl</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Lidl'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Lidl</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;description&quot;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Lidl Stiftung Deutschland'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Lidl</span><span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'date_created'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Y-m-d'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Lidl</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Jetzt greifen wir über das Produkt-Objekt zunächst auf die Variationen des Produkts zu. Hier gehen wir mal davon aus, dass wir wissen, an welcher Stelle die beiden Datensätze stehen und das sie vorhanden sind. Zum Einfügen eines POS zu einer Variation gibt es wieder zwei Möglichkeiten. Die eine über die lose Array-Zuweisung, welche (wie beim letzten Mal erläutert) Performance-Einbußen mit sich bringen kann:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Light</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Data_Db_ProductsVariations</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Light</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Data_Db_Pos</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Lidl</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Light</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Data_Db_Pos</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Aldi</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Light</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Jetzt haben wir die Variante Light zu Lidl und Aldi hinzugefügt. Nehmen wir nun Variante B und fügen Zero zu Lidl hinzu:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Zero</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Data_Db_ProductsVariations</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Pv2Pos</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_ProductsVariations2pos<span style="color: #339933;">;</span>
<span style="color: #000088;">$Pv2Pos</span> <span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'products_variations_id'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Zero</span> <span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'id'</span> <span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Pv2Pos</span> <span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'pos_id'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Lidl</span> <span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'id'</span> <span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Pv2Pos</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p> Dies sieht zwar nicht ganz so cool aus, ist aber im Endeffekt performanter. Da die wenigsten Leute sich beim Benutzen der Anwendung für den coolen Source interessieren, sondern eher für die Performance, würde ich Variante B vorschlagen <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</p>
<p>Jetzt haben wir genug Daten in der Datenbank, sodass wir sie nun mit einem Query auslesen können:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Auslesen (Alle Produkte-Variationen von Lidl)</span>
<span style="color: #000088;">$Query</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Doctrine_Query<span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'Data_Db_ProductsVariations pv, pv.Data_Db_Pos p'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">where</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'p.id = '</span> <span style="color: #339933;">.</span> <span style="color: #009900;">&#40;</span>int<span style="color: #009900;">&#41;</span><span style="color: #000088;">$Lidl</span> <span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'id'</span> <span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Wie man erkennen kann ist die Verknüpfungstabelle transparent. Doctrine weiß selbst durch die Definition welche Verknüpfungen verwendet werden müssen und macht solchen Query daraus:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>
    p<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">AS</span>
    p__id<span style="color: #66cc66;">,</span> p<span style="color: #66cc66;">.</span>products_id <span style="color: #993333; font-weight: bold;">AS</span>
    p__products_id<span style="color: #66cc66;">,</span> p<span style="color: #66cc66;">.</span>name <span style="color: #993333; font-weight: bold;">AS</span>
    p__name<span style="color: #66cc66;">,</span> p<span style="color: #66cc66;">.</span>date_created <span style="color: #993333; font-weight: bold;">AS</span>
    p__date_created<span style="color: #66cc66;">,</span> p2<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">AS</span>
    p2__id<span style="color: #66cc66;">,</span> p2<span style="color: #66cc66;">.</span>name <span style="color: #993333; font-weight: bold;">AS</span>
    p2__name<span style="color: #66cc66;">,</span> p2<span style="color: #66cc66;">.</span>description <span style="color: #993333; font-weight: bold;">AS</span>
    p2__description<span style="color: #66cc66;">,</span> p2<span style="color: #66cc66;">.</span>date_created <span style="color: #993333; font-weight: bold;">AS</span>
    p2__date_created <span style="color: #993333; font-weight: bold;">FROM</span>
    products_variations p
    <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> products_variations2pos p3 <span style="color: #993333; font-weight: bold;">ON</span> p<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">=</span> p3<span style="color: #66cc66;">.</span>products_variations_id
    <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> pos p2 <span style="color: #993333; font-weight: bold;">ON</span> p2<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">=</span> p3<span style="color: #66cc66;">.</span>pos_id
    <span style="color: #993333; font-weight: bold;">WHERE</span> p2<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">2</span></pre></td></tr></table></div>

<p>Wenn wir diesen Query nun ausführen und dann durchwandern, sehen wir, dass wir Erfolg hatten. Wir bekommen die beiden hinzugefügten Varianten, die wir zum POS Lidl hinzugefügt haben. Diese sind natürlich unsortiert, aber das kann man nachholen bzw. vorher durch ein orderBy realisieren, wenn man es möchte <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> :</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #b1b100;">foreach</span>
<span style="color: #009900;">&#40;</span>
	<span style="color: #000088;">$Result</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$ProductVariation</span>
<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$ProductVariation</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Data_Db_Products</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">&quot; -&gt; &quot;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$ProductVariation</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;br /&gt;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Folgendes Ergebnis können wir betrachten:<br />
<blockquote>Coca Cola -> Light<br />
Coca Cola -> Zero</p></blockquote>
<p>Über die Objektschnittstellen von Doctrine können wir nun auch vollständig auf die Daten des eigentlichen Produkts zugreifen. Doctrine läd diese Daten dann on-Demand nach.</p>
<p>Nun haben wir 1:1, 1:n und n:m Beziehungen beleuchtet, das gibt uns die Möglichkeit vieles zu realisieren. Im nächsten Beitrag werde ich auf ein weiteres tolles Feature von Doctrine eingehen, die Eventlistener. <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .<br />
Kommentare sind gern gesehen, Fragen natürlich auch.</p>
<p align="left"><a target="_blank" class="tt" href="http://twitter.com/home/?status=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%233+http://bit.ly/coUqUH" title="Post to Twitter"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-twitter-micro3.png" alt="Post to Twitter" /></a> <a target="_blank" class="tt" href="http://delicious.com/post?url=http://www.alexander-stelter.de/blog/57-enterprise-orm-in-php-mit-doctrine-3/&amp;title=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%233" title="Post to Delicious"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-delicious-micro3.png" alt="Post to Delicious" /></a> <a target="_blank" class="tt" href="http://digg.com/submit?url=http://www.alexander-stelter.de/blog/57-enterprise-orm-in-php-mit-doctrine-3/&amp;title=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%233" title="Post to Digg"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-digg-micro3.png" alt="Post to Digg" /></a> <a target="_blank" class="tt" href="http://www.facebook.com/share.php?u=http://www.alexander-stelter.de/blog/57-enterprise-orm-in-php-mit-doctrine-3/&amp;t=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%233" title="Post to Facebook"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-facebook-micro3.png" alt="Post to Facebook" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexander-stelter.de/blog/57-enterprise-orm-in-php-mit-doctrine-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Enterprise: ORM in PHP mit Doctrine #2</title>
		<link>http://www.alexander-stelter.de/blog/55-enterprise-orm-in-php-mit-doctrine-2/</link>
		<comments>http://www.alexander-stelter.de/blog/55-enterprise-orm-in-php-mit-doctrine-2/#comments</comments>
		<pubDate>Mon, 30 Jul 2007 19:10:55 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://www.alexander-stelter.de/blog/?p=55</guid>
		<description><![CDATA[Achtung:Dieses Turorial bezieht sich auf eine veraltete Version von Doctrine und funktioniert vermutlich mit den neueren 1.x und späteren 2.x Releasen nicht mehr. Nach dem wir im letzten Beitrag die Grundlagen zu Doctrine gelernt haben, wollen wir heute ein wenig weiter in die Tiefe gehen. Wir nehmen wieder unser Beispiel und nehmen an wir haben [...]]]></description>
			<content:encoded><![CDATA[<p style="border: #ff0000 1px dotted; padding: 4px; color: #ff0000; font-weight: bold;">Achtung:<br />Dieses Turorial bezieht sich auf eine veraltete Version von <a href="http://www.doctrine-project.org/">Doctrine</a> und funktioniert vermutlich mit den neueren 1.x und späteren 2.x Releasen nicht mehr.</p>
<p>Nach dem wir im <a href="http://www.alexander-stelter.de/blog/archives/50-Enterprise-ORM-in-PHP-mit-Doctrine-1.html#extended" >letzten Beitrag</a> die Grundlagen zu <a href="http://www.phpdoctrine.net" >Doctrine</a> gelernt haben, wollen wir heute ein wenig weiter in die Tiefe gehen.<br />
Wir nehmen wieder unser Beispiel und nehmen an wir haben ein Produkt z.B. Coca Cola. Hierzu gibt es viele Varianten wie z.B. Zero, Light, Cherry. Diese wollen wir speichern und dabei das Original- bzw. Basisprodukt nur einmal speichern. Dies ist eine 1:n Beziehung, die wir in Doctrine abbilden möchten.<br />
Der Grundaufbau der Includes etc. ist genau der selbe, wie wir ihn beim letzten Mal verwendet haben, daher will ich diesen nicht mehr erläutern.<span id="more-55"></span>Beginnen wir nun direkt und erzeugen zunächst die Datenbank-Tabelle, in der wir die Variationsen speichern werden. Alles natürlich rudimentär. Hierzu dient folgender SQL-Befehl:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`products_variations`</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">`id`</span> bigint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">AUTO_INCREMENT</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`products_id`</span> bigint<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">UNSIGNED</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`name`</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span> collate latin1_general_ci <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`date_created`</span> datetime <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span>  <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">`id`</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>MyISAM  <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>latin1 COLLATE<span style="color: #66cc66;">=</span>latin1_general_ci;</pre></td></tr></table></div>

<p>Als nächstes legen wir die Datenbank-Klasse für die Tabelle an, hier kommt direkt die erste Besonderheit. Doctrine verwendet für das Einsetzen der Verbindungen zwischen den Klasse eine SetUp-Methode. Diese setzt dann die Verbindungen in folgender Weise:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasOne</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_Products'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'products_id'</span><span style="color: #339933;">,</span>
                                    <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Es wird mittels hasOne eine Beziehung gesetzt und zwar wird der lokale Schlüssel products_id mit dem fremden Schlüssel id verknüpft. Dies funktioniert nur bei 1:n Beziehungen in dieser Weise. Für n:m Beziehungen gilt eine andere Schreibweise. Dies wird Thema eines anderen Beitrages sein <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Die fertige Datenbankklasse sieht nun folgendermaßen aus:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span>
	Data_Db_ProductsVariations
<span style="color: #000000; font-weight: bold;">extends</span>
	Doctrine_Record
<span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setTableDefinition
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTableName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'products_variations'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'primary'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'unsigned'</span> <span style="color: #339933;">&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'autoincrement'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'products_id'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">8</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'string'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">3000</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'date_created'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'timestamp'</span> <span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setUp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasOne</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_Products'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'products_id'</span><span style="color: #339933;">,</span>
                                    <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Nun hilft uns eine einseitige Verknüpfung in diesem Fall nichts, also setzen wir nun den &#8220;n&#8221;-Part in der Produkt-Klasse. Diese sieht in einsatzbereitem Zustand so aus:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span>
	Data_Db_Products
<span style="color: #000000; font-weight: bold;">extends</span>
	Doctrine_Record
<span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setTableDefinition
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTableName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'products'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'integer'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'primary'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'unsigned'</span> <span style="color: #339933;">&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
                                                   <span style="color: #0000ff;">'autoincrement'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'name'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'string'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">255</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'description'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'string'</span> <span style="color: #339933;">,</span> <span style="color: #cc66cc;">3000</span> <span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notnull'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasColumn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'date_created'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'timestamp'</span> <span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> setUp
	<span style="color: #009900;">&#40;</span>
	<span style="color: #009900;">&#41;</span>
	<span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasMany</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Data_Db_ProductsVariations'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'local'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span>
                                    <span style="color: #0000ff;">'foreign'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'products_id'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Jetzt sind wir soweit, dass wir weiter arbeiten können. Wir fügen nun zunächst mal ein Basis-Produkt ein, mit dem wir dann die anderen Beispiele durchgehen. In meinem Fall ist es das Produkt &#8220;Coca Cola&#8221;:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="php" style="font-family:monospace;">try
<span style="color: #009900;">&#123;</span>
	<span style="color: #000088;">$Product</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_Products<span style="color: #339933;">;</span>
	<span style="color: #000088;">$Product</span> <span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'name'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Coca Cola'</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$Product</span> <span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'description'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Erfrischungsgetraenk'</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$Product</span> <span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'date_created'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Y-m-d'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000088;">$Product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
catch
<span style="color: #009900;">&#40;</span>
	Exception <span style="color: #000088;">$e</span>
<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #990000;">var_dump</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$e</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMessage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Ist das Produkt angelegt, machen wir uns daran die Variationsen anzulegen. Hierzu gibt es zwei verschiedene Möglichkeiten. Die Möglichkeit A verwendet die Array-Implementation von Doctrine. Sie ist jedoch nicht wirklich performant, da durch die Schreibweise mit den Array-Klammern zunächst alle bisherigen Einträge gelesen werden müssen, um den korrekten Index berechnen zu können, ich stelle sie jedoch trotzdem vor, der Vollständigkeit halber:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Product</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Connection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'Data_Db_Products'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span> <span style="color: #009900;">&#40;</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #000088;">$ProductVariations</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_ProductsVariations<span style="color: #339933;">;</span>
<span style="color: #000088;">$ProductVariations</span><span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'name'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Zero'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$ProductVariations</span><span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'date_created'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Y-m-d'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Data_Db_ProductsVariations</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$ProductVariations</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Die zweite Variations ist durchaus performanter, führt aber zum selben Ergebnis, verursacht nur weniger Datenbank-Last:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Product</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Connection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'Data_Db_Products'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span> <span style="color: #009900;">&#40;</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$ProductVariations</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Data_Db_ProductsVariations<span style="color: #339933;">;</span>
<span style="color: #000088;">$ProductVariations</span><span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'name'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'Light'</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$ProductVariations</span><span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'products_id'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Product</span> <span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'id'</span> <span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$ProductVariations</span><span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'date_created'</span> <span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">date</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Y-m-d'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$ProductVariations</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Jetzt haben wir ein Produkt mit zwei Variationsen in die Datenbank gespeichert. Diese wollen wir nun auslesen. Auch dazu gibt es zwei verschiedene Möglichkeiten, die je nach Einsatzzweck beide sinnvoll sind. Will man wirklich explizit nur ein Produkt auslesen, dann verwendet man den Finder, möchte man evtl. viele verschiedene Produkte mit ihren Variationsen auslesen, verwendet man den Query. In diesem Fall ist der Query natürlich nicht so sinnvoll, aber er sei der Vollständigkeit halber vorgestellt. Bei dieser Gelegenheit schauen wir uns dann auch mal einen Query an, den Doctrine generiert. Hierzu müssen wir nur ein echo auf das Query-Objekt machen, denn Doctrine implementiert die __toString()-Methode:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Product</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Connection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'Data_Db_Products'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span> <span style="color: #009900;">&#40;</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Doctrine_Query<span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'Data_Db_Products p , p.Data_Db_ProductsVariations'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">where</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'p.id = '</span> <span style="color: #339933;">.</span> <span style="color: #009900;">&#40;</span>int<span style="color: #009900;">&#41;</span><span style="color: #000088;">$Product</span> <span style="color: #009900;">&#91;</span> <span style="color: #0000ff;">'id'</span> <span style="color: #009900;">&#93;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Doctrine generiert dabei folgenden Query:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>
    p<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">AS</span>
    p__id<span style="color: #66cc66;">,</span> p<span style="color: #66cc66;">.</span>name <span style="color: #993333; font-weight: bold;">AS</span>
    p__name<span style="color: #66cc66;">,</span> p<span style="color: #66cc66;">.</span>description <span style="color: #993333; font-weight: bold;">AS</span>
    p__description<span style="color: #66cc66;">,</span> p<span style="color: #66cc66;">.</span>date_created <span style="color: #993333; font-weight: bold;">AS</span>
    p__date_created<span style="color: #66cc66;">,</span> p2<span style="color: #66cc66;">.</span>id <span style="color: #993333; font-weight: bold;">AS</span>
    p2__id<span style="color: #66cc66;">,</span> p2<span style="color: #66cc66;">.</span>products_id <span style="color: #993333; font-weight: bold;">AS</span>
    p2__products_id<span style="color: #66cc66;">,</span> p2<span style="color: #66cc66;">.</span>name <span style="color: #993333; font-weight: bold;">AS</span>
    p2__name<span style="color: #66cc66;">,</span> p2<span style="color: #66cc66;">.</span>date_created <span style="color: #993333; font-weight: bold;">AS</span>
    p2__date_created <span style="color: #993333; font-weight: bold;">FROM</span>
    product p
    <span style="color: #993333; font-weight: bold;">LEFT</span> <span style="color: #993333; font-weight: bold;">JOIN</span> products_variations p2 <span style="color: #993333; font-weight: bold;">ON</span> p<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">=</span> p2<span style="color: #66cc66;">.</span>products_id
    <span style="color: #993333; font-weight: bold;">WHERE</span> p<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">1</span></pre></td></tr></table></div>

<p>Wir sehen nun, dass Doctrine einen LeftJoin erstellt. Dies können wir natürlich auch beeinflussen, aber das soll dann Thema eines anderen Beitrags sein. Führen wir diesen Query nun aus</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Result</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">FETCH_ARRAY</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p> erhalten wir folgendes Ergebnis. Wobei zu sagen ist, dass ich absichtlich nur ein Array abhole, um Performance zu sparen. Man könnte natürlich auch eine Objekthirarchie abholen.<br />
<blockquote>Array<br />
(<br />
    [0] => Array<br />
        (<br />
            [id] => 1<br />
            [name] => Coca Cola<br />
            [description] => Erfrischungsgetraenk<br />
            [date_created] => 2007-07-30 00:00:00<br />
            [Data_Db_ProductsVariations] => Array<br />
                (<br />
                    [0] => Array<br />
                        (<br />
                            [id] => 1<br />
                            [products_id] => 1<br />
                            [name] => Zero<br />
                            [date_created] => 2007-07-30 00:00:00<br />
                        )</p>
<p>                    [1] => Array<br />
                        (<br />
                            [id] => 2<br />
                            [products_id] => 1<br />
                            [name] => Light<br />
                            [date_created] => 2007-07-30 00:00:00<br />
                        )</p>
<p>                )</p>
<p>        )</p>
<p>)</p></blockquote>
<p>Wir erhalten nun ein Array mit dem gesuchten Produkt und mit deinen Variationsen, mehr wollten wir ja nicht <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Schauen wir uns nun noch die zweite Variante an (per Finder). Hier haben wir (noch) nicht die Möglichkeit nur ein Array abzuholen. Wir suchen also das Produkt mit der ID 1 und können dann per Pfeiloperator auf die Variationsen zugreifen, die verknüpft sind. Doctrine wird dann im Moment des Zugriffs die betreffenden Daten nachladen (<a href="http://www.martinfowler.com/" >Martin Fowler&#8217;s</a> Lazy Loading)</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$Product</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$Connection</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTable</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'Data_Db_Products'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">find</span> <span style="color: #009900;">&#40;</span> <span style="color: #cc66cc;">1</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span>
<span style="color: #009900;">&#40;</span>
	<span style="color: #000088;">$Product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Data_Db_ProductsVariations</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$Variations</span>
<span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #000088;">$Variations</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">&quot;name&quot;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;br /&gt;&quot;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Dabei erhalten wir folgendes Ergebnis:<br />
<blockquote>Zero<br />
Light</p></blockquote>
<p>Es hat also funktioniert <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Ich hoffe dies war ein weiterer Einstieg in die Arbeit mit Doctrine <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Bei der Arbeit mit Doctrine kann man viele spannende Dinge der Objektorientierung lernen und es findt sich bei fast jedem Überlegen ein neuer &#8220;cooler&#8221; Weg die Daten zu verarbeiten. Beim nächsten Beitrag werden wir uns mit dem Verknüpfen von n:m Beziehungen beschäftigen. Genauer mit der Verknüpfung von Packungseinheiten zu ProduktVariationsen.</p>
<p>Kommentare sind natürlich willkommen <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p align="left"><a target="_blank" class="tt" href="http://twitter.com/home/?status=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%232+http://bit.ly/9R5c06" title="Post to Twitter"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-twitter-micro3.png" alt="Post to Twitter" /></a> <a target="_blank" class="tt" href="http://delicious.com/post?url=http://www.alexander-stelter.de/blog/55-enterprise-orm-in-php-mit-doctrine-2/&amp;title=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%232" title="Post to Delicious"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-delicious-micro3.png" alt="Post to Delicious" /></a> <a target="_blank" class="tt" href="http://digg.com/submit?url=http://www.alexander-stelter.de/blog/55-enterprise-orm-in-php-mit-doctrine-2/&amp;title=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%232" title="Post to Digg"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-digg-micro3.png" alt="Post to Digg" /></a> <a target="_blank" class="tt" href="http://www.facebook.com/share.php?u=http://www.alexander-stelter.de/blog/55-enterprise-orm-in-php-mit-doctrine-2/&amp;t=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%232" title="Post to Facebook"><img class="nothumb" src="http://www.alexander-stelter.de/blog/wp-content/plugins/tweet-this/icons/tt-facebook-micro3.png" alt="Post to Facebook" /></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.alexander-stelter.de/blog/55-enterprise-orm-in-php-mit-doctrine-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
