<?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>Der Anti-Hype &#187; Symfony</title>
	<atom:link href="http://www.anti-hype.de/tag/symfony/feed" rel="self" type="application/rss+xml" />
	<link>http://www.anti-hype.de</link>
	<description>Zwischen Hype und Wahnsinn! (BETA)</description>
	<lastBuildDate>Sat, 24 Apr 2010 20:25:42 +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>Geschenke von der Symfony-Community</title>
		<link>http://www.anti-hype.de/2008/12/04/355</link>
		<comments>http://www.anti-hype.de/2008/12/04/355#comments</comments>
		<pubDate>Thu, 04 Dec 2008 19:50:51 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Askeet]]></category>
		<category><![CDATA[Framework]]></category>
		<category><![CDATA[Jobeet]]></category>

		<guid isPermaLink="false">http://www.anti-hype.de/?p=355</guid>
		<description><![CDATA[Für alle Symfony-Entwickler gibt es mal wieder ganz viele vorweihnachtliche Geschenke. Zum einen wurde vor kurzem Symfony 1.2 veröffentlicht und zum anderen kam für Freunde von Doctrine das Symfony + Doctrine Buch raus und kann, wie gewohnt, online durchgelesen werden.
Und als wären das nicht schon genug Geschenke: Nach dem Beispiel des inzwischen schon in die [...]]]></description>
			<content:encoded><![CDATA[<p><img align="left" title="symfony" src="http://www.anti-hype.de/wp-content/uploads/2008/09/symfony.png" alt="" hspace="10" width="200" height="54" vpsace="5" />Für alle Symfony-Entwickler gibt es mal wieder ganz viele vorweihnachtliche Geschenke. Zum einen wurde vor kurzem <a href="http://www.symfony-project.org/blog/2008/12/01/symfony-1-2-is-already-available">Symfony 1.2 veröffentlicht</a> und zum anderen kam für Freunde von Doctrine das <a href="http://www.symfony-project.org/blog/2008/12/02/introducing-the-symfony-doctrine-book">Symfony + Doctrine Buch</a> raus und kann, wie gewohnt, online durchgelesen werden.</p>
<p>Und als wären das nicht schon genug Geschenke: Nach dem Beispiel des inzwischen schon in die Jahre gekommenen Adventskalender &#8220;Askeet&#8221;, einem Tutorial über 24 Tage, gibt es dieses Jahr einen neuen Adventskalender! Jobeet heißt das Projekt und die ersten vier Tage sind schon online und lohnen sich zu lesen:</p>
<ul>
<li><a href="http://www.symfony-project.org/jobeet/1_2/en/01">Jobeet &#8211; Tag 1 &#8211; Starting up the Project</a></li>
<li><a href="http://www.symfony-project.org/jobeet/1_2/en/02">Jobeet &#8211; Tag 2 &#8211; The Project</a></li>
<li><a href="http://www.symfony-project.org/jobeet/1_2/en/03">Jobeet &#8211; Tag 3 &#8211; The Data Model</a></li>
<li><a href="http://www.symfony-project.org/jobeet/1_2/en/04">Jobeet &#8211; Tag 4 &#8211; The Controller and the View</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/12/04/355/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Propel vs. Doctrine #1</title>
		<link>http://www.anti-hype.de/2008/10/15/propel-vs-doctrine-1</link>
		<comments>http://www.anti-hype.de/2008/10/15/propel-vs-doctrine-1#comments</comments>
		<pubDate>Wed, 15 Oct 2008 16:56:53 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Propel]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.anti-hype.de/?p=322</guid>
		<description><![CDATA[Speziell, wenn man ein neues Symfony-Projekt anfängt, kommt schnell die Frage auf: Nehme ich Propel oder Doctrine für das Object-Relational Mapping (ORM)? Seit Symfony 1.1 ist Propel nicht mehr Pflicht und auch Doctrine kann problemlos genutzt werden. Da aber beide inkompatibel zueinander sind und das wohl auch immer so bleiben wird, muss man eine Entscheidung [...]]]></description>
			<content:encoded><![CDATA[<p>Speziell, wenn man ein neues Symfony-Projekt anfängt, kommt schnell die Frage auf: Nehme ich <a href="http://propel.phpdb.org/trac/">Propel</a> oder <a href="http://www.doctrine-project.org/">Doctrine</a> für das <a href="http://de.wikipedia.org/wiki/Object-Relational_Mapping">Object-Relational Mapping</a> (ORM)? Seit Symfony 1.1 ist Propel nicht mehr Pflicht und auch Doctrine kann problemlos genutzt werden. Da aber beide inkompatibel zueinander sind und das wohl auch immer so bleiben wird, muss man eine Entscheidung treffen.</p>
<p>Ich habe mich noch nicht intensiv mit Doctrine auseinander gesetzt, aber ein paar der Features sind verdammt interessant, so dass ich in nächster Zeit mal einen genaueren Blick darauf werfen werde:</p>
<ul>
<li><strong>Geschwindigkeit</strong>: Seit Propel 1.3 auch auf <a href="http://www.php.net/PDO">PDO</a> aufsetzt, ist dies kein Kriterium mehr und Propel 1.3 scheint sogar die Nase knapp vorn zu haben, wenn es um Geschwindigkeit geht.</li>
<li><strong>Behaviors</strong>: Ein geiles Feature. Von Propel kennt man es im Zusammenspiel mit Symfony schon, dass z.B. created_at Zeilen automatisch gepflegt werden. Mit Behaviors hat Doctrine etwas ähnliches an Board, allerdings noch weitaus mächtiger. Definiere ich eine Spalte als Sluggable, wird mir automatisch dafür ein Slug(*) erzeugt. Damit entfällt viel Code, den ich sonst selber schreiben müsste. Das Versionable-Behavior ermöglich es von einer Zeile bzw. einem Objekt mehrere Versionen in der Datenbank zu verwalten. Damit lässt sich ganz einfach und unkompliziert eine Versionsverwaltung aufbauen. Noch ein paar weitere Behaviors runden das Ganze ab.</li>
<li><strong>Memcache-Driver</strong>: Geplant ist ein ähnliches Feature auch für Propel 2.0. Aber Doctrine bringt es schon mit &#8211; die Möglichkeit Objekte nicht nur in eine Datenbank zu pressen, sondern auch in einen Cache (bzw. Memcache). Für verteilte Anwendungen mit mehreren Servern bzw. einem Projekt mit Datenbankreplikationen ein Traum!</li>
<li><strong>Magic Finders</strong>: Wie oft ist die erste Handlung, nach dem generieren der Propel-Objekte, angepasste Methoden für die <em>xxx</em>Peer-Klasse zu schreiben, für Fälle bei denen Objekte nicht nur per Primary Key aus der Datenbank geholt werden sollen. Doctrine bietet mit den Magic Finders eine ganze Reihe von Möglichkeiten, das schnell zu bewerkstelligen.</li>
<li><strong>Inheritance</strong>: Das Feature gefällt mir verdammt gut. Vererbung! Möchte man zum Beispiel auf seiner Seite ein Gästebuch und an anderer Stelle Kommentare haben, so haben beide im Grunde die gleiche Basis: Eine Tabelle in die beispielsweise Name, E-Mail, Homepage und Text des Autors gespeichert werden. Aber jeweils beide, Gästebuch-Eintrag und Kommentar, haben eventuell noch zusätzliche, unterschiedliche Felder. Mit Doctrine ist es möglich eine gemeinsame Basis-Tabelle zu definieren und darauf aufbauend weitere Tabellen, die die Eigenschaft der Basis-Tabelle dann in einem Objekt vereinen. Das wird eins der ersten Features sein, die ich unbedingt mal ausprobieren möchte.</li>
<li><strong>DQL</strong>: Doctrine kommt mit einer mächtigen Sprache für Queries daher: DQL. Gerade bei etwas umfangreicheren, verschachtelten Abfragen wird das bauen eines Criteria/Criterion-Objekts mit Propel etwas umständlich. Mit DQL soll dies weitaus leichter sein.</li>
</ul>
<p>Soviel zunächst zu den, für mich wichtigen, Vorteilen von Doctrine. Es sind auf jedenfall wie gesagt genug, so dass ich mich mal intensiver mit Doctrine beschäftigen möchte. Mir sind auch ein paar Nachteile aufgefallen, bei denen ich noch genauer nachsehen muss, ob es denn welche sind. Aber diese werde ich in einem weiteren Artikel verbloggen. <img src='http://www.anti-hype.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Auch Propel plant einige geniale Features für die Version 2.0 &#8211; so z.B. die angesprochene Möglichkeit Objekte zu cachen &#8211; nur ist es halt noch in Entwicklung. <img src='http://www.anti-hype.de/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>* <em>Slug: Ein Slug ist z.B. für eine URL angepasster Titel eines Artikels, damit dieser lesbar bleibt und in der URL verwendet werden kann. Außerdem muss ein Slug immer eindeutig sein, im Gegensatz allerdings zum Titel eines Artikels, der häufiger vorkommen kann.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/10/15/propel-vs-doctrine-1/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Umstieg auf Symfony 1.2</title>
		<link>http://www.anti-hype.de/2008/10/06/umstieg-auf-symfony-12</link>
		<comments>http://www.anti-hype.de/2008/10/06/umstieg-auf-symfony-12#comments</comments>
		<pubDate>Mon, 06 Oct 2008 19:30:57 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[Propel]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://www.anti-hype.de/?p=297</guid>
		<description><![CDATA[Nachdem ich mich im letzten Posting gefragt habe, ob ich nun Symfony 1.1 oder Symfony 1.2 für ein neues Projekt benutzen sollte, habe ich mich gestern für Symfony 1.2 entschieden.
Der Hauptgrund war eigentlich, dass 1.2 schon in drei Wochen, genauer am 26.10.2008, erscheinen soll, laut Roadmap. Daraus schließe ich, dass die aktuelle Version aus dem [...]]]></description>
			<content:encoded><![CDATA[<p>Nachdem ich mich <a href="http://www.anti-hype.de/2008/10/05/symfony-11-oder-12">im letzten Posting gefragt habe</a>, ob ich nun Symfony 1.1 oder Symfony 1.2 für ein neues Projekt benutzen sollte, habe ich mich gestern für Symfony 1.2 entschieden.</p>
<p>Der Hauptgrund war eigentlich, dass 1.2 schon in drei Wochen, genauer am 26.10.2008, erscheinen soll, laut <a href="http://trac.symfony-project.org/roadmap">Roadmap</a>. Daraus schließe ich, dass die aktuelle Version aus dem Trunk doch schon relativ stabil sein sollte. Die Features von Propel 1.3 sind einfach zu gut um nicht genutzt zu werden. <img src='http://www.anti-hype.de/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Für alle, die Propel 1.3 mit Symfony 1.1 benutzen wollen, gibt es eine gute <a href="http://www.symfony-project.org/cookbook/1_1/en/propel_13">Anleitung im Symfony Cookbook</a>. Dennoch wollte ich, wenn schon, auch die neuen Features von Symfony 1.2 direkt haben.</p>
<p>Aber auch das <a href="http://framework.zend.com/docs/overview">Zend Framework</a> ist damit nicht ganz aus dem Rennen. Symfony bietet mit der <a href="http://www.symfony-project.org/book/1_0/17-Extending-Symfony#Bridges%20to%20Other%20Framework%27s%20Components">sfZendFrameworkBridge</a> eine Möglichkeit das Zend Framework innerhalb von Symfony zu benutzen. Da das Zend Framework viele brauchbare Features auch abseits des alltäglichen MVC-Prinzips bietet, ist das eine gute Möglichkeit nicht für alles das Rad neu erfinden zu müssen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/10/06/umstieg-auf-symfony-12/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony 1.1 oder 1.2?</title>
		<link>http://www.anti-hype.de/2008/10/05/symfony-11-oder-12</link>
		<comments>http://www.anti-hype.de/2008/10/05/symfony-11-oder-12#comments</comments>
		<pubDate>Sun, 05 Oct 2008 14:49:18 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[Propel]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://www.anti-hype.de/?p=293</guid>
		<description><![CDATA[Ich habe gerade ein neues Projekt auf Basis von Symfony 1.1 angefangen. Leider stellt sich nun, schon beim erstellen des Schemas, die Frage ob ich auf Symfony 1.2 warten sollte.
Der Grund: Propel 1.3 kommt mit Symfony 1.2. Und ich würde gerne ein neues Feature von Propel 1.3 nutzen: 1:1-Relationen. Leider funktioniert das in Symfony 1.1 [...]]]></description>
			<content:encoded><![CDATA[<p>Ich habe gerade ein neues Projekt auf Basis von Symfony 1.1 angefangen. Leider stellt sich nun, schon beim erstellen des Schemas, die Frage ob ich auf Symfony 1.2 warten sollte.</p>
<p>Der Grund: Propel 1.3 kommt mit Symfony 1.2. Und ich würde gerne ein neues Feature von Propel 1.3 nutzen: <a href="http://propel.phpdb.org/trac/wiki/Users/Documentation/1.3/Relationships#One-to-OneRelationships">1:1-Relationen</a>. Leider funktioniert das in Symfony 1.1 noch nicht so ganz. Das Prinzip ist eigentlich ganz einfach und logisch: Eine Tabelle hat einen PrimaryKey und die andere Tabelle hat darauf einen ForeignKey <strong>und</strong> einen PrimaryKey. Somit ist logisch festgelegt, dass nur eine 1:1-Beziehung bestehen kann. Propel erkennt dies und im Modell hat man nun get-Methoden, die nur <strong>ein</strong> Objekt zurückgeben, statt einem Array.</p>
<p>Mit der aktuellen Version von Symfony aus dem Trunk (1.1.5-DEV) scheint das leider noch nicht zu funktionieren. Die Tabelle mit dem Primary-Key gibt einen Array zurück und die Tabelle mit dem Foreign-Key, wie es richtig ist, nur ein Objekt.</p>
<p>Jetzt für mich die große Frage: Warten auf Symfony 1.2? Oder Symfony 1.1 benutzen und vorerst die Methoden selber schreiben und später auf Symfony 1.2 wechseln, wenn das überhaupt problemlos klappt? Oder gar nicht Symfony benutzen und auf Zend Framework + Propel aufbauen? Die Lösung überlege ich mir jetzt wohl erstmal bei einem Kaffee&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/10/05/symfony-11-oder-12/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Refaktorisierung mit Symfony (Teil 2/5)</title>
		<link>http://www.anti-hype.de/2008/09/24/refaktorisierung-mit-symfony-teil-25</link>
		<comments>http://www.anti-hype.de/2008/09/24/refaktorisierung-mit-symfony-teil-25#comments</comments>
		<pubDate>Wed, 24 Sep 2008 19:14:59 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Refactoring]]></category>
		<category><![CDATA[Refaktorisierung]]></category>
		<category><![CDATA[test]]></category>
		<category><![CDATA[unit test]]></category>

		<guid isPermaLink="false">http://www.anti-hype.de/?p=273</guid>
		<description><![CDATA[Dies ist der zweite Teil von &#8220;Refaktorisierung mit Symfony&#8221;, eine freie, deutsche Übersetzung und leicht abgewandelte Version des Originalartikels “Call the expert: A refactoring story (Part 2/5)” veröffentlicht im offziellen Symfony-Blog. Teil 1 der Serie befindet sich hier: Refaktorisierung mit Symfony (Teil 1/5).
Anmerkung: Texte und Kommentare wurden, soweit möglich, ins Deutsche übersetzt, damit sie dem [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.anti-hype.de/wp-content/uploads/2008/09/symfony.png" alt="" title="symfony" width="200" height="54" align="left" vspace="3" hspace="10" />Dies ist der zweite Teil von &#8220;Refaktorisierung mit Symfony&#8221;, eine freie, deutsche Übersetzung und leicht abgewandelte Version des Originalartikels “<a href="http://www.symfony-project.org/blog/2008/09/19/call-the-expert-a-refactoring-story-part-2-5">Call the expert: A refactoring story (Part 2/5)</a>” veröffentlicht im offziellen <a href="http://www.symfony-project.org/blog/">Symfony-Blog</a>. Teil 1 der Serie befindet sich hier: <a href="http://www.anti-hype.de/2008/09/20/refaktorisierung-mit-symfony-teil-15">Refaktorisierung mit Symfony (Teil 1/5)</a>.</p>
<p><strong>Anmerkung</strong>: Texte und Kommentare wurden, soweit möglich, ins Deutsche übersetzt, damit sie dem Verständnis helfen. Den Sourcecode selbst habe ich Englisch gelassen, da Symfony-Funktionen und -Methoden, sowie PHP selbst, in Englisch sind und daher eine Übersetzung keinen Sinn machen würde. Im Allgemeinen empfiehlt es sich Sourcecode immer auf englisch zu schreiben. Bei den Kommentaren und der Dokumentation kommt es auf den Einzelfall an.</p>
<h2>Die Geschichte</h2>
<p>Refaktorisierung bedeutet eine Menge an Code zu verändern. Deshalb braucht man eine Möglichkeit zu Überprüfen, dass man dabei nichts kaputt macht. Also fragte Fabien, vor dem Beginn der Refaktorisierung, Vince nach seinen Unit- und Funktionstests.</p>
<p>Aber Vince hatte leider keine Unit- oder Funktionstests. Also entschieden sie sich, vor Beginn der Refaktorisierung, zunächst ein paar dieser Tests zu schreiben.</p>
<p><span id="more-273"></span></p>
<h2>Der Symfony-Browser</h2>
<p>In Symfony kann man, dank der <i>sfTestBrowser</i>-Klasse, seine Anwendung testen in dem man das Verhalten eines Browsers simuliert. Die Klasse verhält sich wie ein echter Browser aber sie nutzt nicht das HTTP-Protokoll um Symfony-Module aufzurufen. Das hat zwei Vorteile: Es ist einfach schneller und man hat zusätzlich die Möglichkeit Symfony-Objekte nach jedem Request direkt zu überprüfen.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// test/functional/frontend/productActionsTest.php</span>
<span style="color: #b1b100;">include</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/../../bootstrap/functional.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$browser</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfTestBrowser<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<h2>Die Testdaten (Fixtures)</h2>
<p>Da der Test reproduzierbar sein soll, müssen wir sicherstellen, dass die Daten in der Datenbank auch immer die Selben sind, wenn wir den Test starten. Also ging Vince hin und erstellte ein paar Testdaten:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// data/fixtures/product.yml</span>
<span style="color: #666666; font-style: italic;">// Angepasste, eingedeutschte Daten</span>
Category<span style="color: #339933;">:</span>
  toy_story<span style="color: #339933;">:</span>
    name<span style="color: #339933;">:</span> Toy Story
&nbsp;
  Wall<span style="color: #339933;">-</span>E<span style="color: #339933;">:</span>
    name<span style="color: #339933;">:</span> Wall<span style="color: #339933;">-</span>E
&nbsp;
Product<span style="color: #339933;">:</span>
  U<span style="color: #339933;">-</span>Command<span style="color: #339933;">:</span>
    title<span style="color: #339933;">:</span> Ferngesteuerter Wall<span style="color: #339933;">-</span>E
    image<span style="color: #339933;">:</span> walle<span style="color: #339933;">.</span>jpg
    description<span style="color: #339933;">:</span> <span style="color: #339933;">|</span>
      Ein ferngesteuerter Wall<span style="color: #339933;">-</span>E mit ganz vielen Funktionen<span style="color: #339933;">.</span>
      Unverzichtbar für jeden <span style="color: #0000ff;">&quot;Wall-E&quot;</span><span style="color: #339933;">-</span>Fan<span style="color: #339933;">!</span>
    price<span style="color: #339933;">:</span>  <span style="color:#800080;">59.99</span>
    is_new<span style="color: #339933;">:</span> <span style="color: #009900; font-weight: bold;">true</span>
    is_in_stock<span style="color: #339933;">:</span> <span style="color: #009900; font-weight: bold;">true</span>
    category_id<span style="color: #339933;">:</span> Wall<span style="color: #339933;">-</span>E
&nbsp;
  Interaction<span style="color: #339933;">-</span>Eve<span style="color: #339933;">:</span>
    title<span style="color: #339933;">:</span> Interaktive Eve
    image<span style="color: #339933;">:</span> eve<span style="color: #339933;">.</span>jpg
    description<span style="color: #339933;">:</span> <span style="color: #339933;">|</span>
      Eine sehr interaktive Eve<span style="color: #339933;">.</span>
      Sollte jeder zu Hause haben<span style="color: #339933;">!</span>
    price<span style="color: #339933;">:</span> <span style="color:#800080;">65.99</span>
    is_new<span style="color: #339933;">:</span> <span style="color: #009900; font-weight: bold;">true</span>
    is_in_stock<span style="color: #339933;">:</span> <span style="color: #009900; font-weight: bold;">true</span>
    category_id<span style="color: #339933;">:</span> Wall<span style="color: #339933;">-</span>E
&nbsp;
  vending<span style="color: #339933;">:</span>
    title<span style="color: #339933;">:</span> Wall<span style="color: #339933;">-</span>E Figurenset
    image<span style="color: #339933;">:</span> set<span style="color: #339933;">.</span>jpg
    description<span style="color: #339933;">:</span> <span style="color: #339933;">|</span>
      Komplettes Set mit <span style="color: #cc66cc;">8</span> Figuren<span style="color: #339933;">.</span>
      Wer das nicht hat <span style="color: #339933;">...</span> der hat<span style="color: #0000ff;">'s nicht!
    price: 6.99
    is_new: true
    is_in_stock: false
    category_id: Wall-E
&nbsp;
  woody:
    title: Toy Story Woody
    image: woody.jpg
    description: |
      Woody aus dem bekannten Film Toy Story.
    price: 24.99
    is_new: false
    is_in_stock: true
    category_id: toy_story</span></pre></div></div>

<p>In dieser Fixure-Datei haben wir zwei Kategorien und vier Produkte definiert. Bis auf das &#8220;Wall-E Figurenset&#8221; sind alle Produkte im Bestand.</p>
<p>Um die Daten aus der Fixure-Datei zu laden, benutzen wir die <i>sfPropelData</i>-Klasse. Standardmäßig löscht sfPropelData alle Daten aus den Datenbanktabellen, in die wir importieren, so dass jedes mal eine saubere Datenbank für unsere Tests zur Verfügung steht.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// initialize the database with fixtures</span>
<span style="color: #000088;">$databaseManager</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfDatabaseManager<span style="color: #009900;">&#40;</span><span style="color: #000088;">$configuration</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$loader</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfPropelData<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$loader</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">loadData</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_data_dir'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/fixtures'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Symfony benutzt die Datenbank-Konfiguration der Testumgebung, wenn es für einen Funktionstest (functional test) genutzt wird. Wenn man sich also nicht die Standarddatenbank, die man zum Entwickeln benutzt, zerstören will, sollte man sich durch einen &#8220;test&#8221;-Eintrag in der <i>database.yml</i>-Konfigurationsdatei, eine spezielle Konfiguration für die Tests anlegen.</p>
<p>Jetzt wird bei jedem Start des Skripts die Datenbank aufgeräumt und die Fixture-Daten geladen. Selbst wenn unser Test die Daten verändert, wird dies keine Auswirkung auf den nächsten Testdurchlauf haben.</p>
<h2>CSS3-Selektoren</h2>
<p>Auf der Startseite müssen wir sicherstellen, dass wir eine Liste von Produkten vorfinden und das alle Produkte, die angezeigt werden, im Bestand sind. Wir testen jetzt ob das Produkt &#8220;Toy Story Woody&#8221; angezeigt wird, aber nicht das &#8220;Wall-E Figurenset&#8221;.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$browser</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isStatusCode</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'module'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'product'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'action'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'index'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">checkResponseElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'body'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/Toy Story Woody/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">checkResponseElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'body'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'!/Wall-E Figurenset/'</span><span style="color: #009900;">&#41;</span>
<span style="color: #339933;">;</span></pre></div></div>

<p>Das Skript ist selbsterklärend:</p>
<ul>
<li>Ruf die Startseite ab (/).</li>
<li>Überprüfe, dass der Body (&lt;body&gt;) den Produkttitel enthält.</li>
<li>Überprüfe, dass die Seite nicht das Produkt enthält, dass nicht im Bestand ist.</li>
</ul>
<p>Wenn ein Produkt neu ist (is_new Spalte in der Datenbank), wird der Text &#8220;NEU!&#8221; an den Titel angehängt. Bevor wir den Test schreiben, der überprüft ob das korrekt funktioniert, schauen wir uns das Template der Startseite an:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;h1&gt;Unsere Produkte&lt;/h1&gt;
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$products</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$product</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  &lt;div&gt;
    &lt;h2&gt;
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTitle</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getIsNew</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: #000000; font-weight: bold;">?&gt;</span>&lt;span style=&quot;margin-left: 10px; color: #e55&quot;&gt;NEU!&lt;/span&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;/h2&gt;
    &lt;div style=&quot;margin-bottom: 10px&quot;&gt;
      &lt;em&gt;Kategorie&lt;/em&gt;: <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCategory</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span> -
      &lt;em&gt;Preis&lt;/em&gt;: Only $<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPrice</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span> - 
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sf_user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'favorites'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        &lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> url_for<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'product/removeFromFavorites?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;&lt;img src=&quot;/images/favorite.png&quot; /&gt;&lt;/a&gt;
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">else</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        &lt;small&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> link_to<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Zu meinen Favoriten hinzufügen'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'product/addToFavorites?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/small&gt;
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;/div&gt;
    &lt;div&gt;
      &lt;div style=&quot;float: left&quot;&gt;
        &lt;img width=&quot;100px&quot; src=&quot;/images/products/<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getImage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; /&gt;
      &lt;/div&gt;
      &lt;p&gt;
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDescription</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$sf_user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAuthenticated</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: #000000; font-weight: bold;">?&gt;</span>
          &lt;p style=&quot;text-align: right&quot;&gt;&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> url_for<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'product/edit?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;Produkt editieren&lt;/a&gt;&lt;/p&gt;
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
      &lt;/p&gt;
      &lt;br style=&quot;clear: both&quot; /&gt;
    &lt;/div&gt;
    &lt;div style=&quot;text-align: right&quot;&gt;
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> link_to<span style="color: #009900;">&#40;</span>image_tag<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/images/add_to_cart.png'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'product/buy?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;/div&gt;
    &lt;hr /&gt;
  &lt;/div&gt;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<p>Um zu Überprüfen ob der Text &#8220;NEU&#8221; hinter den Produkttitel gesetzt wird, können wir nicht einfach überprüfen ob &#8220;NEU&#8221; im Body-Tag steht. Das wäre etwas ungenau und für einen brauchbareren Test müssen wir den Test präziser schreiben. In Symfony ist dies ziemlich einfach, da die <i>checkResponseElement()</i>-Methode CSS3-Selektoren als erstes Argument annimmt:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$browser</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">checkResponseElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'h2:contains(&quot;NEU&quot;)'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span>
<span style="color: #339933;">;</span></pre></div></div>

<p>Hier überprüfen wir, dass es <strong>genau zwei</strong> H2-Tags haben, die das Wort &#8220;NEU&#8221; enthalten.</p>
<p>Jetzt müssen wir noch das Editieren von Produkten testen. Das Szenario dafür ist das folgende:</p>
<ul>
<li>Einloggen als Administrator</li>
<li>Auf den &#8220;Produkt editieren&#8221;-Link klicken</li>
<li>Das Formular mit neuen Daten ausfüllen und eine neue Datei hochladen</li>
<li>Das Formular abschicken</li>
<li>Überprüfen, dass die abgeschickten Daten auf der Homepage angezeigt werden</li>
<li>Ausloggen</li>
</ul>
<p>Um uns als Administrator einzuloggen, müssen wir auf den &#8220;Einloggen&#8221;-Link klicken:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$browser</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">click</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Einloggen'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRedirected</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'module'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'user'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
&nbsp;
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'action'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'signin'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">followRedirect</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isStatusCode</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'module'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'product'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'action'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'index'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">checkResponseElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'body'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'!/Einloggen/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">checkResponseElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'body'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/Ausloggen/'</span><span style="color: #009900;">&#41;</span>
<span style="color: #339933;">;</span></pre></div></div>

<p>Nach der Authentifizierung, leitet die <i>signin</i>-Action den Benutzer bzw. Browser auf die Startseite. Wir überprüfen dann, dass der &#8220;Einloggen&#8221;-Link nicht mehr existiert und durch einen &#8220;Ausloggen&#8221;-Link ersetzt wurde.</p>
<p>Jetzt wo wir eingeloggt sind, können wir auf den &#8220;Produkt editieren&#8221;-Link klicken. Aber auf der Startseite sind mehrere Links mit diesem Namen. Wir nehmen also an, wir wollen auf den zweiten Link klicken:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Das position-Attribute ist neu in Symfony 1.2</span>
<span style="color: #000088;">$browser</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">click</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Edit this product'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'position'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isStatusCode</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'module'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'product'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'action'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'edit'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">checkResponseElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'h2'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/Ferngesteuerter Wall-E/'</span><span style="color: #009900;">&#41;</span>
<span style="color: #339933;">;</span></pre></div></div>

<p>Nach ein paar grundlegenden Überprüfungen auf der Seite, sind wir bereit das Formular abzuschicken:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$browser</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">click</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Save'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'product'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'price'</span>  <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'10'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'image'</span>  <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/../../../web/images/products/eve.jpg'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'is_new'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">,</span>
  <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
<span style="color: #339933;">;</span></pre></div></div>

<p>Wenn man mit <i>click()</i> einen Button anklickt, kann man die Werte für Felder, die wir überschreiben wollen, mit übergeben. In diesem Beispiel ändern wir die Werte der Felder <i>price</i>, <i>is_new</i> und wir laden ein Bild hoch in dem wir den vollständigen Pfad zu der Datei angeben, die wir hochladen wollen.</p>
<p>Nachdem wir überprüft haben, dass wir wieder auf die Startseite weitergeleitet worden sind, können wir testen ob unsere Änderungen aufgenommen wurden:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$browser</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRedirected</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">followRedirect</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isStatusCode</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'module'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'product'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'action'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'index'</span><span style="color: #009900;">&#41;</span>
  checkResponseElement<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'h2:contains(&quot;NEU&quot;)'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">checkResponseElement</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">sprintf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'img[src$=&quot;%s&quot;]'</span><span style="color: #339933;">,</span> <span style="color: #990000;">sha1</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'eve.jpg'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'.jpg'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
<span style="color: #339933;">;</span></pre></div></div>

<p>Jetzt können wir uns ausloggen:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$browser</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">click</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Ausloggen'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'module'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'user'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'action'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'signout'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRedirected</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">followRedirect</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isStatusCode</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'module'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'product'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'action'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'index'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">checkResponseElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'body'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/Einloggen/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">checkResponseElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'body'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'!/Ausloggen/'</span><span style="color: #009900;">&#41;</span>
<span style="color: #339933;">;</span></pre></div></div>

<p>Ab jetzt, immer wenn wir Änderungen am Code vornehmen, lassen wir die Funktionstests laufen, um sicher zu sein, dass wir keine Features dabei kaputt gemacht haben:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ php symfony <span style="color: #7a0874; font-weight: bold;">test</span>:functional frontend productActions</pre></div></div>

<h2>Anwendungsspezifische Browser</h2>
<p>Die Funktionstests, die wir geschrieben haben, sind relativ simpel und natürlich müssen wir noch etwas mehr Code schreiben um alle Features der Webseite abzudecken. Und während die Test-Suite wächst, werden wir voraussichtlich einiges an Code kopieren und mehrfach nutzen. So zum Beispiel der Einloggen- und Ausloggen-Prozess. Um zu verhindern den selben Prozess, immer und immer wieder zu wiederholen, ist es eine gute Idee, eine, auf die Anwendung zugeschnittene, Browser-Klasse zu schreiben:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> StoreBrowser <span style="color: #000000; font-weight: bold;">extends</span> sfTestBrowser
<span style="color: #009900;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> signin<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// einloggen</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/user/signin'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">isRedirected</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'module'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'user'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'action'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'signin'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">followRedirect</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">isStatusCode</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'module'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'product'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'action'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'index'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">checkResponseElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'body'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'!/Einloggen/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">checkResponseElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'body'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/Ausloggen/'</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> signout<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #666666; font-style: italic;">// ausloggen</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>
&nbsp;
      <span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/user/signout'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'module'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'user'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'action'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'signout'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">isRedirected</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">followRedirect</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">isStatusCode</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">200</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'module'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'product'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">isRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'action'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'index'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">checkResponseElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'body'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/Einloggen/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
      <span style="color: #004000;">checkResponseElement</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'body'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'!/Ausloggen/'</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></div></div>

<p>Hier ist ein simpler Test, der sich nur einloggt und dann wieder ausloggt:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">include</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">dirname</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/../../bootstrap/functional.php'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Datenbank mit fixtures initialisieren</span>
<span style="color: #000088;">$databaseManager</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfDatabaseManager<span style="color: #009900;">&#40;</span><span style="color: #000088;">$configuration</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$loader</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfPropelData<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$loader</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">loadData</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_data_dir'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/fixtures'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$browser</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> StoreBrowser<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$browser</span><span style="color: #339933;">-&gt;</span>
  <span style="color: #004000;">signin</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// tue etwas während eingeloggt</span>
&nbsp;
  signout<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #339933;">;</span></pre></div></div>

<p>Das ist alles für Heute. Da wir nun von unserer Test-Suite unterstützt werden, kann Vince bequem in Teil 3 mit der Refaktorisierung anfangen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/09/24/refaktorisierung-mit-symfony-teil-25/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Refaktorisierung mit Symfony (Teil 1/5)</title>
		<link>http://www.anti-hype.de/2008/09/20/refaktorisierung-mit-symfony-teil-15</link>
		<comments>http://www.anti-hype.de/2008/09/20/refaktorisierung-mit-symfony-teil-15#comments</comments>
		<pubDate>Sat, 20 Sep 2008 12:43:48 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Refactoring]]></category>
		<category><![CDATA[Refaktorisierung]]></category>

		<guid isPermaLink="false">http://www.anti-hype.de/?p=245</guid>
		<description><![CDATA[
Im offiziellen Symfony-Blog wird derzeit eine fünfteilige Artikelserie über das Thema Refaktorisierung (Refactoring) veröffentlicht. Da die Inhalte sehr interessant sind, habe ich mich entschieden eine deutsche Version der Artikel zu entwerfen.
Dies ist also Teil 1 von &#8220;Refaktorisierung mit Symfony&#8221;, eine freie, deutsche Übersetzung und leicht abgewandelte Version des Originalartikels &#8220;Call the expert: A refactoring story [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.anti-hype.de/wp-content/uploads/2008/09/symfony.png" alt="" title="Symfony" width="200" height="54" class="alignleft size-full wp-image-263" align="left" hspace="10" vspace="5"/></p>
<p>Im offiziellen <a href="http://www.symfony-project.org/blog/">Symfony-Blog</a> wird derzeit eine fünfteilige Artikelserie über das Thema <strong>Refaktorisierung</strong> (Refactoring) veröffentlicht. Da die Inhalte sehr interessant sind, habe ich mich entschieden eine deutsche Version der Artikel zu entwerfen.</p>
<p>Dies ist also Teil 1 von &#8220;Refaktorisierung mit Symfony&#8221;, eine freie, deutsche Übersetzung und leicht abgewandelte Version des Originalartikels &#8220;<a href="http://www.symfony-project.org/blog/2008/09/18/call-the-expert-a-refactoring-story-part-1-5">Call the expert: A refactoring story (Part 1/5)</a>&#8221; veröffentlicht im offziellen Symfony-Blog.</p>
<p><span id="more-245"></span></p>
<p>Wikipedia über <a href="http://de.wikipedia.org/wiki/Refaktorisierung">Refaktorisierung</a>:</p>
<blockquote><p><i>&#8220;Refactoring (deutsch auch Refaktorisierung, Refaktorierung oder schlicht Umgestaltung) bezeichnet in der Software-Entwicklung die manuelle oder automatisierte Strukturverbesserung von Programm-Quelltexten unter Beibehaltung des beobachtbaren Programm-Verhaltens. Dabei sollen die Lesbarkeit, Verständlichkeit, Wartbarkeit und Erweiterbarkeit verbessert werden, mit dem Ziel, den jeweiligen Aufwand für Fehleranalyse und funktionale Erweiterungen deutlich zu senken.&#8221;</i></p></blockquote>
<h2>Die Geschichte</h2>
<p>Vor einiger Zeit fragte Vince, ein erfahrener PHP-Entwickler, den Symfony-Entwickler Fabien Potencier, ob er einen Blick auf sein erstes Symfony-Projekt, ein Onlineshop, werfen könnte.</p>
<p>Sein Kunde war sehr glücklich, dass die Webseite problemlos lief. Auch Vince war zufrieden, da er die Webseite pünktlich fertigstellte. Aber er war sich nicht so sicher über die Qualität seines Codes.</p>
<p>Also schrieb er Fabien an, um Feedback zu der Qualität seines Codes zu bekommen. Statt ihm nur per E-Mail zu antworten, lud ihn Fabien zu Sensio Labs ein um an einer echten Refactoring-Session teilzunehmen.</p>
<p>Da manche seiner Fehler recht häufig in Projekten passieren, hat sich Fabien entschieden den Ablauf des Refactoring im offiziellen Symfony-Blog wiederzugeben, in der Hoffnung, das andere Symfony-Entwickler ebenso davon lernen können, wie es Vince getan hat.</p>
<p>Heute, in Teil 1, beschreiben wir ein paar Features der Webseite und schauen uns ein paar kurze Codeabschnitte an. Der eigentliche Refacorting-Prozess beginnt dann in Teil 2.</p>
<p>Das Projekt wurde mit <strong>Symfony 1.1</strong> entwickelt.</p>
<h2>Das Schema</h2>
<p>Das Datenbankschema besteht aus zwei Tabellen, einer Produkt-Tabelle (product) und einer Kategorie-Tabelle (category):</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"># config/schema<span style="color: #6666ff;">.yml</span>
propel<span style="color: #00AA00;">:</span>
  product<span style="color: #00AA00;">:</span>
    title<span style="color: #00AA00;">:</span>       <span style="color: #00AA00;">&#123;</span> type<span style="color: #00AA00;">:</span> varchar<span style="color: #00AA00;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #00AA00;">&#41;</span><span style="color: #00AA00;">,</span> required<span style="color: #00AA00;">:</span> true <span style="color: #00AA00;">&#125;</span>
    image<span style="color: #00AA00;">:</span>       varchar<span style="color: #00AA00;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #00AA00;">&#41;</span>
    description<span style="color: #00AA00;">:</span> longvarchar
    price<span style="color: #00AA00;">:</span>       <span style="color: #00AA00;">&#123;</span> type<span style="color: #00AA00;">:</span> <span style="color: #993333;">decimal</span><span style="color: #00AA00;">,</span> required<span style="color: #00AA00;">:</span> true <span style="color: #00AA00;">&#125;</span>
    is_new<span style="color: #00AA00;">:</span>      boolean
    is_in_stock<span style="color: #00AA00;">:</span> boolean
    created_at<span style="color: #00AA00;">:</span>  timestamp
    category_id<span style="color: #00AA00;">:</span> ~
&nbsp;
  category<span style="color: #00AA00;">:</span>
    name<span style="color: #00AA00;">:</span> varchar<span style="color: #00AA00;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #00AA00;">&#41;</span></pre></div></div>

<h2>Die Startseite</h2>
<p>Die Startseite der Webseite besteht aus einer Liste aller verfügbaren Produkte (<i>is_in_stock</i> auf <i>true</i> gesetzt).</p>
<p><img src="http://www.anti-hype.de/wp-content/uploads/2008/09/refacoring_hp1.png" alt="Die Startseite" title="refacoring_hp1" width="320" height="359" class="size-full wp-image-247" /></p>
<p>Alle Features, die wir später refaktorisieren, werden vom Produktmodul (product) gesteuert.</p>
<p>Hier ist die <i>index</i>-Action, welche die Startseite steuert:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// apps/frontend/modules/product/actions/actions.class.php</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> executeIndex<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$criteria</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Criteria<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$criteria</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">add</span><span style="color: #009900;">&#40;</span>ProductPeer<span style="color: #339933;">::</span><span style="color: #004000;">IS_IN_STOCK</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$criteria</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addAscendingOrderByColumn</span><span style="color: #009900;">&#40;</span>ProductPeer<span style="color: #339933;">::</span><span style="color: #004000;">PRICE</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$criteria</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLimit</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">10</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;">products</span> <span style="color: #339933;">=</span> ProductPeer<span style="color: #339933;">::</span><span style="color: #004000;">doSelectJoinCategory</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$criteria</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;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setTitle</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Alle Produkte'</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;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addStylesheet</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'homepage.css'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #b1b100;">return</span> sfView<span style="color: #339933;">::</span><span style="color: #004000;">SUCCESS</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Und das dazugehörige Template <i>indexSucess.php</i>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&nbsp;
&lt;h1&gt;Unsere Produkte&lt;/h1&gt;
&nbsp;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$products</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$product</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
  &lt;div&gt;
    &lt;h2&gt;
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTitle</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getIsNew</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: #000000; font-weight: bold;">?&gt;</span>&lt;span style=&quot;margin-left: 10px; color: #e55&quot;&gt;NEU!&lt;/span&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;/h2&gt;
    &lt;div style=&quot;margin-bottom: 10px&quot;&gt;
      &lt;em&gt;Kategorie&lt;/em&gt;: <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getCategory</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span> -
      &lt;em&gt;Preis&lt;/em&gt;: Only $<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPrice</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span> - 
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sf_user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'favorites'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        &lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> url_for<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'product/removeFromFavorites?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;&lt;img src=&quot;/images/favorite.png&quot; /&gt;&lt;/a&gt;
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">else</span><span style="color: #339933;">:</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        &lt;small&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> link_to<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Zu den Favoriten hinzufügen'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'product/addToFavorites?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/small&gt;
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;/div&gt;
    &lt;div&gt;
      &lt;div style=&quot;float: left&quot;&gt;
        &lt;img width=&quot;100px&quot; src=&quot;/images/products/<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getImage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; /&gt;
      &lt;/div&gt;
      &lt;p&gt;
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getDescription</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$sf_user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isAuthenticated</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: #000000; font-weight: bold;">?&gt;</span>
          &lt;p style=&quot;text-align: right&quot;&gt;&lt;a href=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> url_for<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'product/edit?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot;&gt;Produkt editieren&lt;/a&gt;&lt;/p&gt;
        <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endif</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
      &lt;/p&gt;
      &lt;br style=&quot;clear: both&quot; /&gt;
    &lt;/div&gt;
    &lt;div style=&quot;text-align: right&quot;&gt;
      <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> link_to<span style="color: #009900;">&#40;</span>image_tag<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/images/add_to_cart.png'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'product/buy?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;/div&gt;
    &lt;hr /&gt;
  &lt;/div&gt;
<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">endforeach</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></pre></div></div>

<h2>Die Favoriten</h2>
<p>Wie du eventuell schon auf dem Screenshot gesehen hast, kann der Benutzer Produkte zu seinen Favoriten hinzufügen. Das Feature ist recht einfach: Man klickt auf den &#8220;Zu den Favoriten hinzufügen&#8221;-Link um ein Produkt seinen Favoriten hinzuzufügen und man klickt auf das Sternsymbol um es wieder zu entfernen.</p>
<p>Die Favoriten werden von den Methoden <i>executeAddToFacorites()</i> und <i>executeRemoveFromFavorites()</i> des Produktmoduls verarbeitet:</p>

<div class="wp_syntax"><div 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> executeAddToFavorites<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$product</span> <span style="color: #339933;">=</span> ProductPeer<span style="color: #339933;">::</span><span style="color: #004000;">retrieveByPk</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequestParameter</span><span style="color: #009900;">&#40;</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: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">forward404Unless</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$product</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$favorites</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'favorites'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #000088;">$favorites</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'favorites'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$favorites</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;">redirect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'product/index'</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> executeRemoveFromFavorites<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$product</span> <span style="color: #339933;">=</span> ProductPeer<span style="color: #339933;">::</span><span style="color: #004000;">retrieveByPk</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequestParameter</span><span style="color: #009900;">&#40;</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: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">forward404Unless</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$product</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000088;">$favorites</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'favorites'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$favorites</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</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;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setAttribute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'favorites'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$favorites</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;">redirect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'product/index'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h2>Produkte editieren</h2>
<p>Als eingeloggter Administrator können die Produktinformationen auch editiert werden.</p>
<p><img src="http://www.anti-hype.de/wp-content/uploads/2008/09/refactoring_hp2.png" alt="Produkt editieren" title="refactoring_hp2" width="322" height="230" class="alignnone size-full wp-image-249" /></p>
<p>Diese Seite wird von der <i>edit</i>-Action verarbeitet:</p>

<div class="wp_syntax"><div 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> executeEdit<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;">product</span> <span style="color: #339933;">=</span> ProductPeer<span style="color: #339933;">::</span><span style="color: #004000;">retrieveByPk</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequestParameter</span><span style="color: #009900;">&#40;</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: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_null</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">product</span><span style="color: #009900;">&#41;</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;">forward404</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: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ProductForm<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">product</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>sfRequest<span style="color: #339933;">::</span><span style="color: #004000;">POST</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getMethod</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: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRequestParameter</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'product'</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;">getRequest</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getFiles</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'product'</span><span style="color: #009900;">&#41;</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;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isValid</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: #666666; font-style: italic;">// aktuelles produkt holen</span>
      <span style="color: #000088;">$product</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$image</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'image'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$currentImage</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getImage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// altes bild entfernen</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">file_exists</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span> <span style="color: #339933;">=</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_web_dir'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/images/products/'</span><span style="color: #339933;">.</span><span style="color: #000088;">$currentImage</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
          <span style="color: #990000;">unlink</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
      <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #666666; font-style: italic;">// produkt aktualisieren</span>
      <span style="color: #000088;">$product</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">form</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">updateObject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// bild speichern</span>
        <span style="color: #000088;">$filename</span> <span style="color: #339933;">=</span> <span style="color: #990000;">sha1</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOriginalName</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: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getExtension</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOriginalExtension</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: #000088;">$image</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">save</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_web_dir'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">'/images/products/'</span><span style="color: #339933;">.</span><span style="color: #000088;">$filename</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setImage</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$filename</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
      <span style="color: #b1b100;">else</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setImage</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$currentImage</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
&nbsp;
      <span style="color: #666666; font-style: italic;">// produkt speichern</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>
&nbsp;
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getUser</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setFlash</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'notice'</span><span style="color: #339933;">,</span> <span style="color: #990000;">sprintf</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Das Produkt &quot;%s&quot; wurde erfolgreich aktualisiert.'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTitle</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</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;">redirect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'product/index'</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></pre></div></div>

<p>Und das Template <i>editSuccess.php</i>:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;h1&gt;Editieren &quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getTitle</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; &lt;small&gt;#<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/small&gt;&lt;/h1&gt;
&nbsp;
&lt;p&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> link_to<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Zurück zur Homepage'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'@homepage'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/p&gt;
&nbsp;
&lt;form action=&quot;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> url_for<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'product/edit?id='</span><span style="color: #339933;">.</span><span style="color: #000088;">$product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&quot; method=&quot;POST&quot; enctype=&quot;multipart/form-data&quot;&gt;
  &lt;table cellspacing=&quot;0&quot;&gt;
    <span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #b1b100;">echo</span> <span style="color: #000088;">$form</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>
    &lt;tr&gt;
      &lt;td colspan=&quot;2&quot; style=&quot;text-align: right&quot;&gt;&lt;input type=&quot;submit&quot; value=&quot;Speichern&quot; /&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
&lt;/form&gt;</pre></div></div>

<p>Dies ist alles für Heute. Der eigentliche Refactoring-Prozess beginnt im nächsten Teil. In der Zwischenzeit nimm dir die Zeit den Code zu lesen und überleg dir, was du refaktorisieren würdest, wie und warum.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/09/20/refaktorisierung-mit-symfony-teil-15/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Vorschau auf Symfony 1.2</title>
		<link>http://www.anti-hype.de/2008/09/05/vorschau-auf-symfony-12</link>
		<comments>http://www.anti-hype.de/2008/09/05/vorschau-auf-symfony-12#comments</comments>
		<pubDate>Fri, 05 Sep 2008 07:10:05 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Framework]]></category>

		<guid isPermaLink="false">http://derantihype.wordpress.com/?p=209</guid>
		<description><![CDATA[Die Entwickler von Symfony arbeiten zur Zeit fleissig am zukünftigen Release von Symfony 1.2. Im offiziellen Symfony-Blog wird nach uns nach im vorraus über geplante Features informiert.
Bisherige Auswahl:

New in symfony 1.2: Small things matter
New in symfony 1.2: Toward a RESTful architecture (Part 1)
New in symfony 1.2: Customize the Web Debug Toolbar
Propel 1.3, Doctrine 1.0, and [...]]]></description>
			<content:encoded><![CDATA[<p>Die Entwickler von Symfony arbeiten zur Zeit fleissig am zukünftigen Release von Symfony 1.2. Im offiziellen Symfony-Blog wird nach uns nach im vorraus über geplante Features informiert.</p>
<p>Bisherige Auswahl:</p>
<ul>
<li><a href="http://www.symfony-project.org/blog/2008/09/02/new-in-symfony-1-2-small-things-matter">New in symfony 1.2: Small things matter</a></li>
<li><a href="http://www.symfony-project.org/blog/2008/09/04/new-in-symfony-1-2-toward-a-restful-architecture-part-1">New in symfony 1.2: Toward a RESTful architecture (Part 1)</a></li>
<li><a href="http://www.symfony-project.org/blog/2008/08/27/new-in-symfony-1-2-customize-the-web-debug-toolbar">New in symfony 1.2: Customize the Web Debug Toolbar</a></li>
<li><a href="http://www.symfony-project.org/blog/2008/08/21/propel-1-3-doctrine-1-0-and-symfony-1-2">Propel 1.3, Doctrine 1.0, and symfony 1.2</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/09/05/vorschau-auf-symfony-12/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Das Warten ist vorbei!</title>
		<link>http://www.anti-hype.de/2008/07/01/das-warten-ist-vorbei</link>
		<comments>http://www.anti-hype.de/2008/07/01/das-warten-ist-vorbei#comments</comments>
		<pubDate>Tue, 01 Jul 2008 10:47:44 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://derantihype.wordpress.com/?p=141</guid>
		<description><![CDATA[Es ist endlich soweit! Symfony 1.1 ist fertig! Freude! Mal sehen ob ich heute noch Zeit habe damit zu spielen. Die letzten Vorab-Versionen waren schon sehr brauchbar!
]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" style="margin-left:10px;margin-right:10px;" src="http://img179.imageshack.us/img179/7008/200pxsymfonysvgqa8.png" alt="" width="200" height="54" />Es ist endlich soweit! <a href="http://www.symfony-project.org/blog/2008/06/30/the-wait-is-over-symfony-1-1-released">Symfony 1.1 ist fertig</a>! Freude! Mal sehen ob ich heute noch Zeit habe damit zu spielen. Die letzten Vorab-Versionen waren schon sehr brauchbar!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/07/01/das-warten-ist-vorbei/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony 1.1 RC 1</title>
		<link>http://www.anti-hype.de/2008/05/08/symfony-11-rc-1</link>
		<comments>http://www.anti-hype.de/2008/05/08/symfony-11-rc-1#comments</comments>
		<pubDate>Thu, 08 May 2008 13:01:01 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[rc]]></category>

		<guid isPermaLink="false">http://derantihype.wordpress.com/?p=132</guid>
		<description><![CDATA[Der erste Release-Candidate von Symfony 1.1 ist ab sofort da! Das Release kommt immer näher. Hoffentlich arbeiten auch die Plugin-Entwickler an der Portierung.
Ich wollte die Tage das sfFeed2Plugin benutzen und musste feststellen, dass auf dem einfachen Weg über den &#8220;symfony&#8221;-Befehl die Installation verweigert wird, weil das Plugin für 1.0 ist. Musste ich mir leider kurzer [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" style="float:left;margin-left:10px;margin-right:10px;" src="http://img179.imageshack.us/img179/7008/200pxsymfonysvgqa8.png" alt="" width="200" height="54" />Der erste Release-Candidate von Symfony 1.1 ist ab sofort da! Das Release kommt immer näher. Hoffentlich arbeiten auch die Plugin-Entwickler an der Portierung.</p>
<p>Ich wollte die Tage das sfFeed2Plugin benutzen und musste feststellen, dass auf dem einfachen Weg über den &#8220;symfony&#8221;-Befehl die Installation verweigert wird, weil das Plugin für 1.0 ist. Musste ich mir leider kurzer Hand was eigenes Basteln um die News in einen RSS-Feed zu quetschen.</p>
<p>Weiteres zum RC1 gibt&#8217;s im Symfony-Blog: <a href="http://www.symfony-project.org/blog/2008/05/07/symfony-1-1-0-rc1-is-out">Symfony 1.1.0 RC1 is out</a>.</p>
<p>P.S.: In den folgenden Wochen ist mit einem RC2 zu rechnen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/05/08/symfony-11-rc-1/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony: Dynamische Meta-Tags</title>
		<link>http://www.anti-hype.de/2008/05/06/symfony-dynamische-meta-tags</link>
		<comments>http://www.anti-hype.de/2008/05/06/symfony-dynamische-meta-tags#comments</comments>
		<pubDate>Tue, 06 May 2008 12:11:27 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[meta]]></category>
		<category><![CDATA[tags]]></category>

		<guid isPermaLink="false">http://derantihype.wordpress.com/?p=130</guid>
		<description><![CDATA[Bei Symfony kann man ja in der view.yml diverse Meta-Tags definieren, zum Beispiel &#8220;description&#8221; und &#8220;keywords&#8221;. Häufig ist es aber sinnvoller wenn diese auch dynamisch wären. Dies geht relativ einfach wenn man wie beim Artikel zu dynamischen Seitentiteln die sfActions Klasse erweitert:
class myActions extends sfActions
{
  public function setDescription($description)
  {
  	$response = $this-&#62;getResponse();
 [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft" style="float:left;margin-left:10px;margin-right:10px;" src="http://img179.imageshack.us/img179/7008/200pxsymfonysvgqa8.png" alt="" width="200" height="54" />Bei Symfony kann man ja in der view.yml diverse Meta-Tags definieren, zum Beispiel &#8220;description&#8221; und &#8220;keywords&#8221;. Häufig ist es aber sinnvoller wenn diese auch dynamisch wären. Dies geht relativ einfach wenn man wie beim <a href="http://derantihype.wordpress.com/2008/01/14/dynamische-seitentitel-mit-symfony/">Artikel zu dynamischen Seitentiteln</a> die sfActions Klasse erweitert:</p>
<pre><span style="color:#666699;">class myActions extends sfActions
{
  public function setDescription($description)
  {
  	$response = $this-&gt;getResponse();
  	$response-&gt;addMeta('description', $description);
  }

  public function setKeywords($keywords)
  {
  	$response = $this-&gt;getResponse();
  	$response-&gt;addMeta('keywords', $keywords);
  }
}</span></pre>
<p>Nun lassen sich in jeder &#8220;Action&#8221;, die von myActions abgeleitet ist statt direkt von sfActions, die Meta-Tags für Keywords und Beschreibungen bequem dynamisch anpassen, z.B.:</p>
<pre><span style="color:#666699;">public function executeMyAction()
{
  $this-&gt;setDescription('.... beschreibung .... ');
  $this-&gt;setKeywords('foo, bar, foobar, ...');
}</span>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/05/06/symfony-dynamische-meta-tags/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony 1.1 Beta 3</title>
		<link>http://www.anti-hype.de/2008/04/11/symfony-11-beta-3</link>
		<comments>http://www.anti-hype.de/2008/04/11/symfony-11-beta-3#comments</comments>
		<pubDate>Fri, 11 Apr 2008 19:06:54 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>

		<guid isPermaLink="false">http://derantihype.wordpress.com/?p=123</guid>
		<description><![CDATA[Die dritte Beta-Version von Symfony 1.1 ist draußen. Die fertige Version kommt immer näher! Hach das ist wie Weihnachten  
]]></description>
			<content:encoded><![CDATA[<p>Die <a href="http://www.symfony-project.org/blog/2008/04/11/symfony-1-1-beta3-is-out">dritte Beta-Version von Symfony 1.1</a> ist draußen. Die fertige Version kommt immer näher! Hach das ist wie Weihnachten <img src='http://www.anti-hype.de/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/04/11/symfony-11-beta-3/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony 1.0.11</title>
		<link>http://www.anti-hype.de/2008/01/22/symfony-1011</link>
		<comments>http://www.anti-hype.de/2008/01/22/symfony-1011#comments</comments>
		<pubDate>Tue, 22 Jan 2008 11:45:04 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Framework]]></category>

		<guid isPermaLink="false">http://derantihype.wordpress.com/2008/01/22/symfony-1011/</guid>
		<description><![CDATA[Symfony 1.0.11 wurde heute veröffentlicht und ist damit das erste Release in 2008.
Ich warte ja immer noch ganz sehnlich auf Symfony 1.1, das viele Neuerungen mitbringen wird. Zur Zeit migriere ich eine private Bastelei von 1.0.* auf 1.1 (svn) und es ist doch einiges zu beachten. Zwar bringt Symfony 1.1 ein Plugin mit, das die [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://img179.imageshack.us/img179/7008/200pxsymfonysvgqa8.png" align="left" hspace="10" />Symfony 1.0.11 wurde heute veröffentlicht und ist damit das erste Release in 2008.</p>
<p>Ich warte ja immer noch ganz sehnlich auf Symfony 1.1, das viele Neuerungen mitbringen wird. Zur Zeit migriere ich eine private Bastelei von 1.0.* auf 1.1 (svn) und es ist doch einiges zu beachten. Zwar bringt Symfony 1.1 ein Plugin mit, das die Kompatibilität zu 1.0.* herstellt, aber wenn man das Projekt direkt auf 1.1 ohne Rückwärtskompatibilitäten umstellen möchte, dann gibt&#8217;s viel zu beachten und zu entdecken <img src='http://www.anti-hype.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>Aber zurück zu Symfony 1.0.11 und den Neuerungen/Änderungen:</p>
<blockquote>
<ul>
<li>r6765, r6766: fixed error message in getPresentationFor() (closes #1527)</li>
<li>r6764: fixed logic error in sfPager class affects haveToPaginate() method (closes #1512)</li>
<li>r6768, r6769: added mime types caching in sfWebRequest (closes #1811, #1846)</li>
<li>r6761, r6762: fixed content type charset on non text/* content-type (closes #1811, #1968)</li>
<li>r6743: doc: fixed typos (closes #2580, #2596, #2518)</li>
<li>r6740, r6741: fixed sequences bug for postgresql (closes #2584)</li>
<li>r6987, r6988: fixed caching-Bug of file sfWebresponse.class.php (#2764)</li>
<li>r6649: fixed value for &#8216;Content-Type&#8217; HTTP meta header is repeated (closes #1756, #2557, #2402, #2398)</li>
<li>r6648: fixed call to undefined method sfResponse::sendHttpHeaders (closes #2412)</li>
</ul>
</blockquote>
<p><a href="http://www.symfony-project.org/blog/2008/01/22/symfony-1-0-11-is-out">Symfony Blog: symfony 1.0.11 is out</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/01/22/symfony-1011/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamische Seitentitel mit Symfony</title>
		<link>http://www.anti-hype.de/2008/01/14/dynamische-seitentitel-mit-symfony</link>
		<comments>http://www.anti-hype.de/2008/01/14/dynamische-seitentitel-mit-symfony#comments</comments>
		<pubDate>Mon, 14 Jan 2008 21:46:54 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[seitentitel]]></category>

		<guid isPermaLink="false">http://derantihype.wordpress.com/2008/01/14/dynamische-seitentitel-mit-symfony/</guid>
		<description><![CDATA[Für manche Seiten ist es notwenig, dass der Seitentitel dynamisch angepasst wird. Das sieht zum einen schöner aus und ist weiterhin auch praktisch für Suchmaschinen und diverse Bookmarking-Dienste.
Eine Lösung bietet der Artikel Dynamically adjusting your page title in symfony. Mit ein wenig Anpassung kann man damit auch mehrere Ebenen unterstützen:

class myActions extends sfActions

{

  public function [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://img170.imageshack.us/img170/5631/symfonywz3.gif" align="left" height="54" hspace="10" width="200" />Für manche Seiten ist es notwenig, dass der Seitentitel dynamisch angepasst wird. Das sieht zum einen schöner aus und ist weiterhin auch praktisch für Suchmaschinen und diverse Bookmarking-Dienste.</p>
<p>Eine Lösung bietet der Artikel <a href="http://spindrop.us/2007/07/18/dynamically-adjusting-your-page-title-in-symfony/">Dynamically adjusting your page title in symfony</a>. Mit ein wenig Anpassung kann man damit auch mehrere Ebenen unterstützen:</p>
<pre>
<font color="#003366">class myActions extends sfActions

{

  public function setPageTitle($titles)

  {

    $response = $this-&gt;getResponse();

    if(!is_array($titles)) $titles = array($titles);

    $mainTitle = sfConfig::get('app_title');

    $delimeter = ' '.sfConfig::get('app_delimeter', '»').' ';

    $response-&gt;setTitle($mainTitle.$delimeter.implode($delimeter, $titles), false);

  }

}</font></pre>
<p>Jede actions-Klasse, die jetzt von myActions abgeleitet ist, statt von sfActions kann nun einen dynamischen Titel setzen:</p>
<pre>
<font color="#003366">class moduleActions extends myActions

{

  public function executeIndex()

  {

    $this-&gt;setPageTitle(array(

      'Blogs',

      'Antihype',

      'Seite 5'

    ));

    return sfView::SUCCESS;

  }

}</font></pre>
<p>Der Seitenname und das Trennzeichen werden in der app.yml angegeben:</p>
<pre><font color="#003366">
app:

  title:         wordpress.com

  delimeter:     »</font></pre>
<p>Mit dieser Konfiguration würde das obige Beispiel folgenden Seitentitel setzen:</p>
<p><font color="#003366">wordpress.com » Blogs » AntiHype » Seite 5</font></p>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/01/14/dynamische-seitentitel-mit-symfony/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mehrsprachigkeit mit Subdomains und Symfony</title>
		<link>http://www.anti-hype.de/2008/01/14/mehrsprachigkeit-mit-subdomains-und-symfony</link>
		<comments>http://www.anti-hype.de/2008/01/14/mehrsprachigkeit-mit-subdomains-und-symfony#comments</comments>
		<pubDate>Mon, 14 Jan 2008 16:01:51 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[I18N]]></category>
		<category><![CDATA[L10N]]></category>
		<category><![CDATA[Subdomains]]></category>

		<guid isPermaLink="false">http://derantihype.wordpress.com/2008/01/14/mehrsprachigkeit-mit-subdomains-und-symfony/</guid>
		<description><![CDATA[Bei einem Projekt benötigte ich die Möglichkeit mehrere Sprachversionen über Subdomains zu ermöglichen. Bekannt ist dieses System von Wikipedia: de.wikipedia.org beheimatet die deutschsprachige Wikipedia, unter en.wikipedia.org ist die englischsprachige Wikipedia zu Hause und so gibt es für alle unterstützte Sprachen eine Subdomain.
Für Mehrsprachigkeit bietet Symfony ja schon einiges an Möglichkeiten (The Definitive Guide to symfony [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://img170.imageshack.us/img170/5631/symfonywz3.gif" align="left" height="54" hspace="10" width="200" />Bei einem Projekt benötigte ich die Möglichkeit mehrere Sprachversionen über Subdomains zu ermöglichen. Bekannt ist dieses System von Wikipedia: de.wikipedia.org beheimatet die deutschsprachige Wikipedia, unter en.wikipedia.org ist die englischsprachige Wikipedia zu Hause und so gibt es für alle unterstützte Sprachen eine Subdomain.</p>
<p>Für Mehrsprachigkeit bietet <a href="http://www.symfony-project.org/">Symfony</a> ja schon einiges an Möglichkeiten (<a href="http://www.symfony-project.org/book/1_0/13-I18n-and-L10n">The Definitive Guide to symfony &#8211; Chapter 13 &#8211; I18n And L10n</a>). Mittels der Methode <i>setCulture</i> kann einem Besucher eine &#8220;Sprache&#8221; zugeordnet werden und mit Hilfe von XLIFF-Dateien können verschiedene Sprachversionen der Webseite angelegt werden. Was also nur noch fehlt ist eine Möglichkeit die &#8220;Culture&#8221; entsprechend der Subdomain zu setzen.</p>
<p>Den entsprechenden Hinweis bietet dabei das <a href="http://www.symfony-project.org/askeet/1_0/18">Askeet-Tutorial Tag 18</a>. Ein Filter ermöglicht vor Ausführung des Controllers eigenen Code auszuführen. Dort können wir den Hostnamen auslesen und entsprechend der Subdomain die &#8220;Culture&#8221; des Besuchers setzen.</p>
<p>In einzelnen Schritten bedeutet dies also:</p>
<p>1. Filter deklarieren in /<font color="#993300"><i>projekt</i></font>/apps/<font color="#993300"><i>frontend</i></font>/config/filters.yml</p>
<pre><font color="#008000">
<font color="#003366">languageFilter:

  class: languageFilter</font></font></pre>
<p>2. Filter Klasse anlegen in /<font color="#993300"><i>projekt</i></font>/apps/<font color="#993300"><i>frontend</i></font>/lib/<i><font color="#993300">languageFilter</font></i>.php</p>
<pre>
<font color="#003366">class languageFilter extends sfFilter

{</font>
<font color="#003366">
  public function execute($filterChain)

  {

     if($this-&gt;isFirstCall())

     {

       $hostname = $this-&gt;getContext()-&gt;getRequest()-&gt;getHost();

       if($pos = strpos($hostname, '.'))

       {

          $language = substr($hostname, 0, $pos);

          $this-&gt;getContext()-&gt;getUser()-&gt;setCulture($language);

       }

     }

     $filterChain-&gt;execute();

  }

}</font></pre>
<p>Was passiert im Code? Mittels $this-&gt;isFirstCall() wird überprüft ob dies der erste Aufruf des Filters ist, denn durch die Nutzung von forward() im Controller wird der Filter sonst jedes mal ausgeführt, dies ist allerdings nicht nötig.</p>
<p>Mittels strpos und substr wird überprüft ob der Hostname einen Punkt &#8220;.&#8221; enthält und falls ja wird alles vor dem ersten Punkt extrahiert und als &#8220;Culture&#8221; gesetzt.</p>
<p>Damit die Kette von Filtern nicht unterbrochen wird muss ein Filter immer mit $filterChain-&gt;execute(); enden, damit der nächste Filter ausgeführt wird.</p>
<p>Dieser Code soll nur kurz die Möglichkeit skizzieren. Für eine sinnvolle Nutzung fehlen noch ein paar Elemente:</p>
<ul>
<li> In den meisten Fällen dürfte nicht jede Subdomain sinnvoll sein und sollte daher auch nicht zugelassen sein. Ein Abgleich mit einer Liste von &#8216;erlaubten&#8217; Subdomains sollte dabei helfen.</li>
<li>Man sollte sich überlegen was in Fällen passiert in denen keine Subdomain definiert ist. Möglichkeiten wäre eine Sprachauswahl-Seite oder eine automatische Weiterleitung auf eine Sprachversion.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/01/14/mehrsprachigkeit-mit-subdomains-und-symfony/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symfony Framework</title>
		<link>http://www.anti-hype.de/2008/01/14/symfony-framework</link>
		<comments>http://www.anti-hype.de/2008/01/14/symfony-framework#comments</comments>
		<pubDate>Mon, 14 Jan 2008 15:22:02 +0000</pubDate>
		<dc:creator>AntiHype</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Symfony]]></category>
		<category><![CDATA[Framework]]></category>
		<category><![CDATA[MVC]]></category>

		<guid isPermaLink="false">http://derantihype.wordpress.com/2008/01/14/symfony-framework/</guid>
		<description><![CDATA[Auf der Suche nach einem PHP-Framework bin ich vor einiger Zeit bei Symfony hängen geblieben und bin damit mehr als glücklich geworden.
Nachdem ich inzwischen schon ein wenig Erfahrung mit dem Framework sammeln konnte, möchte ich diese jetzt nutzen um den ein oder anderen Artikel auch symfony zu widmen.
Zunächst bleibt erstmal der Hinweis auf die gute [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://img170.imageshack.us/img170/5631/symfonywz3.gif" align="left" height="54" hspace="10" width="200" />Auf der Suche nach einem PHP-Framework bin ich vor einiger Zeit bei <a href="http://www.symfony-project.org/">Symfony</a> hängen geblieben und bin damit mehr als glücklich geworden.</p>
<p>Nachdem ich inzwischen schon ein wenig Erfahrung mit dem Framework sammeln konnte, möchte ich diese jetzt nutzen um den ein oder anderen Artikel auch symfony zu widmen.</p>
<p>Zunächst bleibt erstmal der Hinweis auf die gute und umfangreiche <a href="http://www.symfony-project.org/doc/1_0/">Dokumentation</a> und den kurzen Überblick bei <a href="http://de.wikipedia.org/wiki/Symfony">Wikipedia</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.anti-hype.de/2008/01/14/symfony-framework/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
