<?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; enterprise</title>
	<atom:link href="http://www.alexander-stelter.de/blog/tag/enterprise/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>Sun, 25 Jul 2010 11:27:40 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Eclipse PDT Review</title>
		<link>http://www.alexander-stelter.de/blog/205-eclipse-pdt-review/</link>
		<comments>http://www.alexander-stelter.de/blog/205-eclipse-pdt-review/#comments</comments>
		<pubDate>Thu, 22 May 2008 22:15:00 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[pdt]]></category>
		<category><![CDATA[review]]></category>

		<guid isPermaLink="false">http://www.alexander-stelter.de/blog/?p=205</guid>
		<description><![CDATA[Wie in einem zurückliegenden Posting angedeutet, habe ich die Eclipse PHP Developer Tools zwischenzeitlich getestet und setze sie derzeit auch tatsächlich im täglichen Arbeitsleben ein.
Im Vergleich zu vorherigen Distributionen wie YOXOS und Easy Eclipse kann die PDT Distribution an vielen Stellen Punkte sammeln. Vor allem das verbesserte Outline für Klassen und vererbte Klassen und das [...]]]></description>
			<content:encoded><![CDATA[<p>Wie in einem zurückliegenden <a href="http://www.alexander-stelter.de/blog/archives/85-Eclipse-PHP-Development-Tools-v.-1.0.html" >Posting</a> angedeutet, habe ich die <a href="http://www.eclipse.org/pdt/" >Eclipse PHP Developer Tools</a> zwischenzeitlich getestet und setze sie derzeit auch tatsächlich im täglichen Arbeitsleben ein.</p>
<p>Im Vergleich zu vorherigen Distributionen wie <a href="http://www.yoxos.com/ondemand/" >YOXOS</a> und <a href="http://www.easyeclipse.org/site/home/" >Easy Eclipse</a> kann die PDT Distribution an vielen Stellen Punkte sammeln. Vor allem das verbesserte Outline für Klassen und vererbte Klassen und das bessere Autocomplete von Klassen, Variablen und sogar Klassen-Konstanten können sich sehen lassen. Ich arbeite mitlerweile vorzugsweise mit PDT, weil mir diese Eigenschaften zusätzlich Zeit einsparen und die Effizienz beim Arbeiten erhöht.</p>
<p>Ein kleiner Schönheitsfehler ist aber dennoch enthalten. Das <a href="http://subclipse.tigris.org/" >Subclipse</a> Plugin wollte bei mir nicht so wirklich installiert werden. Zunächst fehlten einige Core-Plugins, die Voraussetzung für das Subclupse Plugin sind und als diese installiert waren, fehlten noch einige andere Dinge. Ich hab&#8217;s nachher dann erstmal aufgegeben, weil ich nicht mehr allzu viel Zeit dazu hatte. Es gibt ja glücklicherweise Stand-Alone Anwendungen wie <a href="http://rapidsvn.tigris.org/" >RapidSVN</a> mit denen man dann dennoch ein SVN Repoisitory bedienen kann. Es ist zwar nicht ganz so aus einem Guss, aber für die tägliche Arbeit auch nicht hinderlich.</p>
<p>Wenn ich&#8217;s doch schaffe, das Subclipse Plugin installiert zu bekommen, werde ich das natürlich mitteilen und auch beschreiben, wie&#8217;s funktioniert. Falls jemand anders das schonmal gelöst haben sollte, bitte kurz eine Nachricht hinterlassen &#8211; das interessiert mich brennend <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=Eclipse+PDT+Review+http://bit.ly/dmv2ii" 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/205-eclipse-pdt-review/&amp;title=Eclipse+PDT+Review" 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/205-eclipse-pdt-review/&amp;title=Eclipse+PDT+Review" 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/205-eclipse-pdt-review/&amp;t=Eclipse+PDT+Review" 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/205-eclipse-pdt-review/feed/</wfw:commentRss>
		<slash:comments>3</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>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 [...]]]></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[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 möglich eine Baumstruktur datenbankseitig abzubilden, zu durchwandern und diese zu ändern. Doctrine bringt dieses Feature nativ mit. Hierbei sei gesagt, dass diese Komponente [...]]]></description>
			<content:encoded><![CDATA[<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>Eclipse PHP Development Tools v. 1.0</title>
		<link>http://www.alexander-stelter.de/blog/85-eclipse-php-development-tools-v-1-0/</link>
		<comments>http://www.alexander-stelter.de/blog/85-eclipse-php-development-tools-v-1-0/#comments</comments>
		<pubDate>Wed, 19 Sep 2007 20:47:41 +0000</pubDate>
		<dc:creator>Alexander</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[eclipse]]></category>
		<category><![CDATA[enterprise]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[pdt]]></category>

		<guid isPermaLink="false">http://www.alexander-stelter.de/blog/?p=85</guid>
		<description><![CDATA[Heute wurden die offiziellen PHP Development Tools für Eclipse veröffentlicht. Nachdem es auf der offiziellen Projektseite von Eclipse schon für sehr viele Programmier- und Scriptsprachen Development Umgebungen gibt, wird jetzt nun auch eine Umgebung zur Entwicklung von PHP angeboten. Es gibt und gab auch schon vorher Eclipse Umgebungen für die Entwicklung von PHP unter Eclipse, [...]]]></description>
			<content:encoded><![CDATA[<p>Heute wurden die offiziellen <a href="http://www.eclipse.org/pdt/" >PHP Development Tools</a> für <a href="http://www.eclipse.org" >Eclipse</a> <a href="http://www.golem.de/0709/54863.html" >veröffentlicht</a>. Nachdem es auf der offiziellen Projektseite von Eclipse schon für sehr viele Programmier- und Scriptsprachen Development Umgebungen gibt, wird jetzt nun auch eine Umgebung zur Entwicklung von PHP angeboten. Es gibt und gab auch schon vorher Eclipse Umgebungen für die Entwicklung von PHP unter Eclipse, jedoch keine offizielle, dies wurde nun nachgeholt.</p>
<p>Wie ich finde ein guter Schritt in die richtige Richtung. Meiner Meinung nach macht PHP mehr und mehr Schritte um sich endlich auch im Enterprise-Bereich festzusetzen und da kommt eine Unterstützung in dieser Form schon ganz recht <img src='http://www.alexander-stelter.de/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . Ich werde mir das Teil auf jeden Fall mal ansehen und ggf. von <a href="http://www.easyeclipse.org/site/home/" >Easy-Eclipse</a> auf diese neue Entwicklungsumgebung umsteigen.</p>
<p align="left"><a target="_blank" class="tt" href="http://twitter.com/home/?status=Eclipse+PHP+Development+Tools+v.+1.0+http://bit.ly/aud0kj" 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/85-eclipse-php-development-tools-v-1-0/&amp;title=Eclipse+PHP+Development+Tools+v.+1.0" 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/85-eclipse-php-development-tools-v-1-0/&amp;title=Eclipse+PHP+Development+Tools+v.+1.0" 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/85-eclipse-php-development-tools-v-1-0/&amp;t=Eclipse+PHP+Development+Tools+v.+1.0" 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/85-eclipse-php-development-tools-v-1-0/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 7xx [...]]]></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[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 bei vielen DBMS durch Trigger abgebildet sind. Ein praktisches Beispiel schauen wir uns nun einmal an. Wir haben ja eine Produkt-Tabelle und Klasse, hier [...]]]></description>
			<content:encoded><![CDATA[<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>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[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 nehmen wir die Klassen und Datenbanktabellen, die wir in den letzten beiden Artikeln erstellt haben und tauchen nun wieder in die Anwendung ein. Wir [...]]]></description>
			<content:encoded><![CDATA[<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[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 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. [...]]]></description>
			<content:encoded><![CDATA[<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>
		<item>
		<title>Enterprise: ORM in PHP mit Doctrine #1</title>
		<link>http://www.alexander-stelter.de/blog/50-enterprise-orm-in-php-mit-doctrine-1/</link>
		<comments>http://www.alexander-stelter.de/blog/50-enterprise-orm-in-php-mit-doctrine-1/#comments</comments>
		<pubDate>Tue, 24 Jul 2007 19:44:59 +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=50</guid>
		<description><![CDATA[Heute starte ich meine Serie zum Thema ORM in PHP mit Doctrine.
Durch ORM ermöglicht man dem Programmierer den vollständigen objektorientierten Zugriff auf die Daten in der Datenbank und macht ihn somit unabhängig von der Speichern und verhindert somit auch die Verwendung von SQL. Das hat den Vorteil, dass man bei einem Wechsel des DBMS keine [...]]]></description>
			<content:encoded><![CDATA[<p>Heute starte ich meine Serie zum Thema <a href="http://de.wikipedia.org/wiki/Object-Relational-Mapping" >ORM</a> in <a href="http://de.php.net" >PHP</a> mit <a href="http://www.phpdoctrine.net" >Doctrine</a>.<br />
Durch ORM ermöglicht man dem Programmierer den vollständigen objektorientierten Zugriff auf die Daten in der Datenbank und macht ihn somit unabhängig von der Speichern und verhindert somit auch die Verwendung von SQL. Das hat den Vorteil, dass man bei einem Wechsel des DBMS keine Querys anpassen muss (so denn das DBMS von dem ORM-Layer untersützt wird.</p>
<p>Doctrine ist eine in PHP5 programmierte Anwendung und ca. seit einem Jahr in Entwicklung. Da Doctrine dieses Jahr als Projekt bei <a href="http://code.google.com/soc/2007/" >Google Summer of Code</a> antreten durfte, tut sich im Moment recht viel. Ich habe Doctrine seit der Revision 7xx verwendet und muss sagen, dass sich bis zur heutigen 2066 recht viel getan hat. Der erste Release-Candidate ist für Ende August <a href="http://www.phpdoctrine.net/trac/wiki/DoctrineGSoC" >angekündigt</a> worden. Der Layer funktioniert großteils reibungslos, jedoch muss man bei Problemen auch hin und wieder mal in den Source schauen um zu verstehen, wieso etwas (noch) nicht funktioniert. Die <a href="http://www.phpdoctrine.net/doctrine/manual/new/?one-page=1" >Dokumentation</a> ist zwar ausführlich, jedoch nicht so perfekt, als dass sie helfen könnte.</p>
<p>Heute machen wir einen kleinen Schnelleinstieg. Wir beginnen mit dem Aufbau der Db-Verbindung, Anlegen einer Doctrine-Db-Klasse, Einfügen von Datensätzen, Auslesen per Finder, Updaten, Auslesen per Query und Löschen. Die aktuellen Beispiele basieren auf der Revision <strong>2066</strong>. Diese kann aus dem <a href="http://de.wikipedia.org/wiki/Svn" >SVN-Repository</a> von <a href="http://doctrine.pengus.net/svn/trunk" >Doctrine</a> ausgecheckt werden. Als Client verwende ich <a href="http://tortoisesvn.tigris.org/" >Tortoise SVN</a>.<br />
<span id="more-50"></span>Steigen wir nun in unser Beispiel ein. Wir wollen in einer Datenbanktabelle Produkte speichern. In unserem Falle noch recht simpel in einer Tabelle. Als Verzeichnisstruktur legen wir folgendes an:</p>
<blockquote><p>lib/external/Doctrine [Checkout-Verzeichnis für Doctrine]<br />
lib/Data/Db                        [Ordner für die Db-Klassen]</p></blockquote>
<p>Beginnen wir nun in unserer /index.php und binden dort zunächst Doctrine per Require ein. Danach muss der Autoloader von Doctrine registriert werden, damit die benötigten Unterklassen von Doctrine automatisch nachgeladen werden können. Danach können wir direkt eine Verbindnug zur Datenbank öffnen.</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: #b1b100;">require_once</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'./lib/Doctrine/lib/Doctrine.php'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">spl_autoload_register</span> <span style="color: #009900;">&#40;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'Doctrine'</span> <span style="color: #339933;">,</span> <span style="color: #0000ff;">'autoload'</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$Connection</span> <span style="color: #339933;">=</span> Doctrine_Manager<span style="color: #339933;">::</span><span style="color: #004000;">connection</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'mysql://root:@localhost/doctrine'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Lassen wir uns diese nun per <em>echo</em> ausgeben, erhalten wir die Bestätigung, dass die Datenbankverbindung geöffnet wurde:<br />
<blockquote>Doctrine_Connection object<br />
State               : open<br />
Open Transactions   : 0<br />
Table in memory     :<br />
Driver name         : mysql</p></blockquote>
<p>Doctrine ist übrigens auch im Fehlerhandling komplett objektorientiert. Also werden keine Fehlermeldungen geworfen, sondern Exceptions. Diese müssen mittels try-catch-Block aufgefangen werden.</p>
<p>Jetzt haben wir Doctrine startklar gemacht, jedoch haben wir noch keine Datenbanktabelle, die wir verwenden können. Also legen wir uns mittels SQL folgende Tabelle an:</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="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`</span> <span style="color: #66cc66;">&#40;</span>
<span style="color: #ff0000;">`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: #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;">,</span>
<span style="color: #ff0000;">`description`</span> TINYTEXT <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;">&#41;</span> ENGINE <span style="color: #66cc66;">=</span> MYISAM ;</pre></td></tr></table></div>

<p>Als nächstes legen wir die Doctrine-Db-Klasse an, mit der wir Doctrine sagen, wie die Tabelle aussehen soll, auf die wir zugreifen wollen. Eine Datenbankrelation entspricht also einer Doctrine-Klasse. Mittels <em>hasColumn</em> definieren wir die Spalten. Hier werden Name, Typ, Länge und Attribute angegeben. Die Klasse muss von der Doctrine-Klasse Doctrine_Record abgeleitet werden und sieht in unserem Falle so aus: (lib/Db/Product.php)</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
</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: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Jetzt haben wir alle Werte gesetzt, um auf die Datenbank zugreifen zu können. Nun wollen wir mal ein Produkt anlegen und es direkt mittels der save()-Methode in die Datenbank speichern:</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;">'My First Product'</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;">'Product Product Product'</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 H:i:s'</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>Geht bei dieser Operation etwas schief, so werden wir die Meldung von Doctrine im Catch-Block ausgegeben bekommen. Wir sehen, wir können ein Objekt vom Typ Data_Db_Products behandeln wie ein Array, da für diese Klassen SPL::ArrayAccess implementiert ist. Wir können natürlich anstatt der Array-Klammern auch die Objektpfeile benutzen <em>$Product->name</em>.<br />
Nun können wir im PHPMyAdmin bereits sehen, dass ein Datensatz in der Datenbank angelegt worden ist. Fügen wir nun hinter dem Save folgendes ein:</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: #b1b100;">echo</span> <span style="color: #000088;">$Product</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></pre></td></tr></table></div>

<p> wird uns die Id des gerade eingegebenen Produktes angezeigt. Dies können wir nun natürlich auch direkt auslesen. Für die Suche nach Primärschlüsselwerten bietet Doctrine eine Finder-Methode, auf die wie folgt zugegriffen werden kann:</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;">$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;">echo</span> <span style="color: #000088;">$Product</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></pre></td></tr></table></div>

<p>Das Ergebnis spricht für sich, es hat funktioniert:<br />
<blockquote>My First Product</p></blockquote>
<p>Jetzt wollen wir den gerade ermittelten Datensatz aktualisieren. Dazu reicht es, wenn wir die Werte, die wir ändern möchten via Array-Zugriff ändern und dann speichern. Das Mappen des Datensatzes übernimmt Doctrine. Jedoch dürfen wir nicht schreibend auf die Id zugreifen, das schützt uns vor ungewollten Aktionen:</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;">$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;">'My Second Product'</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></pre></td></tr></table></div>

<p>Lesen wir dieses Produkt dann nochmal per finder neu ein, können wir sehen, dass die Änderung nicht nur in der Variable, sondern auch nach dem erneuten auslesen persistent gespeichert wurde:<br />
<blockquote>My Second Product</p></blockquote>
<p>Nun verschaffen wir uns mit folgendem Script mal ein paar Testdaten:</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
</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;">100</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>
	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;">'Product '</span> <span style="color: #339933;">.</span> <span style="color: #990000;">sprintf</span> <span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">&quot;<span style="color: #009933; font-weight: bold;">%03d</span>&quot;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$i</span> <span style="color: #009900;">&#41;</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;">'Product Product Product'</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 H:i:s'</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>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Jetzt möchten wir alle Produkte auslesen, welche eine Id zwischen 10 und 20 haben. Dazu verwenden wir einen Doctrine-Query, welcher dann eine Doctrine-Collection zurück gibt. Diese könnten wir dann mit einer Foreach-Schleife durchlaufen. Wir wollen aber zunächst nur auslesen und die Anzahl der Datensätze ausgeben:</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_Products 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 &lt; 20 AND p.id &gt; 9'</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: #b1b100;">echo</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$Result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Das Ergebnis zeigt, dass wir Erfolg hatten:<br />
<blockquote>10</p></blockquote>
<p>Möchten wir anstatt einer Doctrine-Collection direkt ein Array zurück bekommen, um den Overhead, den die Objekte mit sich bringen, ein wenig einzuschränken tauschen wir den <em>execute()</em> Aufruf aus und erhalten folglich nur noch ein Array:</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>Wir bleiben allerdings jetzt bei unserer Collection. Wir haben diese Objekte selektiert um sie zu löschen. Dies ist einfacher als man denkt, wie folgendes Beispiel zeigt:</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="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_Products 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 &lt; 20 AND p.id &gt; 9'</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>
&nbsp;
<span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;br /&gt;PRE-DELETE: &quot;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$Result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<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>
&nbsp;
<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: #b1b100;">echo</span> <span style="color: #0000ff;">&quot;&lt;br /&gt;POST-DELETE: &quot;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">echo</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$Result</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>Wir führen den Such-Query nach dem Löschen nochmal aus und sehen, dass wir nun 0 Datensätze haben die in unser Suchmuster passen. Das Löschen war also erfolgreich:<br />
<blockquote>PRE-DELETE: 10<br />
POST-DELETE: 0</p></blockquote>
<p>Das soll es für heute auch gewesen sein. Ich werde die Reihe in unregelmäßigen Abständen fortsetzen. Es gibt noch viele spannende Themen wie 1:n- n:m-Beziehungen, Events &#8230; Ich freue mich über Kommentare und Meinungen und hoffe, dass ich mit diesen Beiträgen noch mehr Leute zur objektorientierten Programmierung und Doctrine bringen kann.</p>
<p align="left"><a target="_blank" class="tt" href="http://twitter.com/home/?status=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%231+http://bit.ly/ae54h1" 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/50-enterprise-orm-in-php-mit-doctrine-1/&amp;title=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%231" 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/50-enterprise-orm-in-php-mit-doctrine-1/&amp;title=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%231" 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/50-enterprise-orm-in-php-mit-doctrine-1/&amp;t=Enterprise%3A+ORM+in+PHP+mit+Doctrine+%231" 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/50-enterprise-orm-in-php-mit-doctrine-1/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
