<?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>ROAE-Blog &#187; Projekt</title>
	<atom:link href="http://blog.root-of-all-evil.com/category/projekt/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.root-of-all-evil.com</link>
	<description>Studium, Codeing und Gedachtes</description>
	<lastBuildDate>Mon, 30 Jan 2012 22:58:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Mac OS X zur Webentwicklung nutzen: Schnell und einfach Apache, PHP, MySql und SVN einrichten.</title>
		<link>http://blog.root-of-all-evil.com/2010/08/mac-os-x-zur-webentwicklung-nutzen-schnell-und-einfach-apache-php-mysql-und-svn-einrichten/</link>
		<comments>http://blog.root-of-all-evil.com/2010/08/mac-os-x-zur-webentwicklung-nutzen-schnell-und-einfach-apache-php-mysql-und-svn-einrichten/#comments</comments>
		<pubDate>Sun, 29 Aug 2010 10:20:06 +0000</pubDate>
		<dc:creator>Philipp</dc:creator>
				<category><![CDATA[Codeschnipsel]]></category>
		<category><![CDATA[Erklärungen]]></category>
		<category><![CDATA[Guides]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[entwickler]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[mac os x]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[webserver]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=826</guid>
		<description><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/08/mac-os-x-zur-webentwicklung-nutzen-schnell-und-einfach-apache-php-mysql-und-svn-einrichten/" title="Mac OS X zur Webentwicklung nutzen: Schnell und einfach Apache, PHP, MySql und SVN einrichten."></a>Unter Mac OS X entwickeln macht Spaß. Und das eigenen System einzurichten geht erstaunlich schnell, da Mac OS X bereits mit einem Apache 2.2 Webserver, PHP 5 und auch mit einem SVN Server ausgeliefert wird. Wie diese unkompliziert eingerichtet werden &#8230;<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/08/mac-os-x-zur-webentwicklung-nutzen-schnell-und-einfach-apache-php-mysql-und-svn-einrichten/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/08/mac-os-x-zur-webentwicklung-nutzen-schnell-und-einfach-apache-php-mysql-und-svn-einrichten/" title="Mac OS X zur Webentwicklung nutzen: Schnell und einfach Apache, PHP, MySql und SVN einrichten."></a><p>Unter Mac OS X entwickeln macht Spaß. Und das eigenen System einzurichten geht erstaunlich schnell, da Mac OS X bereits mit einem Apache 2.2 Webserver, PHP 5 und auch mit einem SVN Server ausgeliefert wird. Wie diese unkompliziert eingerichtet werden können soll hier gezeigt werden.</p>
<p><span id="more-826"></span></p>
<h2>Apache Webserver unter Mac OS X starten</h2>
<p><a href="http://blog.root-of-all-evil.com/wp-content/uploads/2010/08/Bildschirmfoto-2010-08-28-um-19.03.55.png" rel="lightbox[826]"><img class="alignright size-thumbnail wp-image-828" title="Bildschirmfoto 2010-08-28 um 19.03.55" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/08/Bildschirmfoto-2010-08-28-um-19.03.55-150x125.png" alt="" width="150" height="125" /></a>Den Apache Webserver zu starten geht erstaunlich einfach. Dazu kann entweder unter <em>Systemeinstellungen</em> &gt; <em>Freigaben</em> die so genannte Webfreigabe aktiviert werden. Ich empfehle, den Apache Server auf diesem Wege zu starten. Natürlich kann man im Terminal kann auch folgenden Befehl eingegeben, doch fehlt dann der entsprechende visuelle Status unter Systemeinstellungen.</p>
<pre>sudo httpd -k start</pre>
<p>Das so genannte htdocs Verzeichnis (das Verzeichnis, dass von außen über den Apache 2 Server angesprochen wird) findet sich standardmäßig unter <em>/Library/Webserver/Documents</em>.</p>
<h2>PHP 5 unter Mac OS X einrichten</h2>
<p><a href="http://blog.root-of-all-evil.com/wp-content/uploads/2010/08/Bildschirmfoto-2010-08-28-um-19.37.08.png" rel="lightbox[826]"><img class="alignright size-thumbnail wp-image-833" title="Bildschirmfoto 2010-08-28 um 19.37.08" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/08/Bildschirmfoto-2010-08-28-um-19.37.08-150x89.png" alt="" width="150" height="89" /></a>Wer mit PHP 5 entwickeln möchte, der muss das entsprechende Apache Modul zunächst aktivieren. Dazu muss die <em>httpd.conf</em> Datei editiert werden. Sie findet sich unter <em>/etc/apache2</em>. Um auf die Systemverzeichnisse wie beispielsweise etc oder usr über den Finder zuzugreifen wählt man im Menu des Finders <em>Gehe zu</em> &gt; <em>Gehe zu Ordner</em>. Alternativ kann natürlich auch über das Terminal und cd Befehlen zu den entsprechenden Verzeichnissen navigiert werden.</p>
<p>In der <em>httpd.conf</em> Datei muss die Zeile 116</p>
<pre>LoadModule php5_module        libexec/apache2/libphp5.so</pre>
<p>entkommentiert werden. Wer möchte kann in Zeile 215 einstellen, dass .htaccess Dateien Parameter ändern können. Das ist für die reibungslose Funktion von mod_rewrite notwendig.</p>
<pre>&lt;Directory /Library/WebServer/Documents&gt;
  AllowOverride All
&lt;/Directory&gt;</pre>
<p>In Zeile 230 muss hinzugefügt werden, dass auch index.php Dateien als Directory Indexes erkannt werden:</p>
<pre>&lt;IfModule dir_module&gt;
  DirectoryIndex index.html index.php
&lt;/IfModule&gt;</pre>
<p>Zu guter letzt muss der Webserver neu gestartet werden. Dies kann über die Systemeinstellungen (siehe oben) oder mit folgendem Befehl geschehen:</p>
<pre>sudo httpd -k restart</pre>
<p>Um zu testen, ob PHP läuft kann eine index.php und folgendem Inhalt im htdocs Verzeichnis abgelegt werden. Mit http://localhost/index.php im Browser sollte eine Übersicht über das installierte PHP Modul erscheinen.</p>
<pre>&lt;?php phpinfo(); ?&gt;</pre>
<p>Um Default-Eigenschaften zu überschreiben (error reporting, max upload etc.) muss eine <em>php.ini</em> Datei unter <em>/etc/</em> angelegt werden. Meine php.ini enthält das Folgende:</p>
<pre>max_execution_time = 60
memory_limit = 256M
display_errors = On
post_max_size = 32M
upload_max_filesize = 32M
date.timezone = Europe/Berlin</pre>
<h2>MySQL unter Mac OS X einrichten</h2>
<p>Einen MySQL-Server unter Mac OS X einzurichten geht denkbar einfach. Hierfür gibt es fertige Installer, die über <a href="http://dev.mysql.com/downloads/mysql/" target="_blank">http://dev.mysql.com/downloads/mysql/</a> bezogen werden können. Zusätzlich kommt das MySQL Package mit einem Startup-Item. Wird es installiert, so startet MySQL bei jeden Systemstart automatisch. Installiert wird mysql unter <em>/usr/local/mysql</em>. Um MySQL manuell zu starten genügt folgender Befehl:</p>
<pre>sudo mysqld_safe</pre>
<p>Um einen unkomplizierten Umgang mit MySQL zu gewährleisten empfehle ich, das <em>/usr/local/mysql/bin</em> Verzeichnis zur $PATH hinzuzufügen. Tut man dies nicht, wird der mysql Befehl im Terminal nicht gefunden. Diese drei Schritte helfen:</p>
<p>1. Eine neue Datei <em>/etc/paths.d/mysql</em> erzeugen:</p>
<pre>sudo touch /etc/paths.d/mysql</pre>
<p>2. Die Datei bearbeiten und das MySQL bin Verzeichnis erstellen:</p>
<pre>sudo vim /etc/paths.d/mysql</pre>
<p>3. Den  MySQL-bin Pfad einfügen und speichern.</p>
<pre>/usr/local/mysql/bin</pre>
<p>Wer mit vim noch nicht gearbeitet hat:<em> i</em> drücken um in die Datei zu schreiben, den Pfad eingeben, <em>ESC</em> drücken und dann <em>:wq</em> eingeben und mit <em>Enter</em> bestätigen. Nach einem Neustart sind alle im <em>/usr/local/mysql/bin</em> Verzeichnis befindenden Programme auffindbar.</p>
<p>Achtung: Anfangs besitzt der MySQL root Account kein Passwort! Zur einfachen Verwaltung empfehle ich <a href="http://www.phpmyadmin.net/home_page/downloads.php" target="_blank">phpmyadmin</a> &#8211; ein WebGUI.</p>
<h2>Einen SVN Server unter Mac OS X einrichten</h2>
<p>SVN wird bereits mit Mac OS X ausgeliefert. Damit der SVN Server auch von außen ansprechbar ist muss in erster Linie der Apache Webserver konfiguriert werden. Ich verwalte meine SVN Repositories im Ordner <em>/usr/local/svn/</em>. Um die Repositories von außen ansprechbar zu machen muss eine Datei namens <em>svn.conf</em> im Ordner <em>/etc/apache2</em>/other angelegt werden. Sie besitzt folgenden Inhalt:</p>
<pre>LoadModule dav_svn_module /usr/libexec/apache2/mod_dav_svn.so
&lt;Location /svn&gt;
  DAV svn
  SVNParentPath /usr/local/svn
&lt;/Location&gt;</pre>
<p>Nachdem Apache neu gestartet wurde sind die Repositories in <em>/usr/local/svn/</em> unter <em>http://localhost/svn</em> ansprechbar. Beim Anlegen eines neuen Repositories namens foo mit</p>
<pre>sudo svnadmin create /usr/local/svn/foo</pre>
<p>Muss darauf geachtet werden, dass Apache und das SVN Modul auch darauf zugreifen können. Dazu ändern wir zuvor den Besitzer der Dateien in www um:</p>
<pre>sudo chown -R www:www /usr/local/svn</pre>
<p>Damit ist SVN bereits fertig eingerichtet. Ich empfehle die Absicherung des SVN Verzeichnisses. Dazu muss zunächst eine htpasswd Datei erzeugt werden:</p>
<pre>htpasswd -cm /etc/apache2/svn.auth benutzername</pre>
<p>Die svn.conf Datei muss um folgendes erweitert werden:</p>
<pre>LoadModule dav_svn_module /usr/libexec/apache2/mod_dav_svn.so
&lt;Location /svn&gt;
  DAV svn
  SVNParentPath /usr/local/svn
  AuthType Basic
  AuthName "Subversion Login"
  AuthUserFile /etc/apache2/svn.auth
  Require valid-user
&lt;/Location&gt;</pre>
<p>Die Repositories sind jetzt unter http://localhost/svn erreichbar. Zur einfachen Verwaltung empfehle ich <a href="http://www.websvn.info/download/" target="_blank">WebSVN</a> &#8211; ein WebGUI.</p>
<p><strong>Update:</strong> Sollte der Apache Server mit der obigen svn Konfiguration nicht mehr starten, muss darauf geachtet werden, dass die Apache Module <em>mod_dav.so</em> und <em>mod_dav_fs.so</em> auch geladen werden. Danke an Alexander für diesen Tip.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/08/mac-os-x-zur-webentwicklung-nutzen-schnell-und-einfach-apache-php-mysql-und-svn-einrichten/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Setting up SVN on Mac OS X &#8211; Quick &amp; Easy</title>
		<link>http://blog.root-of-all-evil.com/2010/08/setting-up-svn-on-mac-os-x-quick-easy/</link>
		<comments>http://blog.root-of-all-evil.com/2010/08/setting-up-svn-on-mac-os-x-quick-easy/#comments</comments>
		<pubDate>Thu, 26 Aug 2010 16:48:22 +0000</pubDate>
		<dc:creator>Philipp</dc:creator>
				<category><![CDATA[Codeschnipsel]]></category>
		<category><![CDATA[Erklärungen]]></category>
		<category><![CDATA[Guides]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[mac os]]></category>
		<category><![CDATA[mac os x]]></category>
		<category><![CDATA[setup]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[svn server]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=822</guid>
		<description><![CDATA[You'll find quite a lot of guides showing you how to install an svn server on your Mac OS X machine. But most of them don't tell you, that Mac OS X ships with a fully functional svn system. This is how you configure it.<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/08/setting-up-svn-on-mac-os-x-quick-easy/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/08/setting-up-svn-on-mac-os-x-quick-easy/" title="Setting up SVN on Mac OS X - Quick &amp; Easy"></a><p>You&#8217;ll find quite a lot of guides showing you how to install an svn server on your Mac OS X machine. But most of them don&#8217;t tell you, that Mac OS X ships with a fully functional svn system. This is how you configure it.</p>
<p><span id="more-822"></span>Start of by opening Terminal and creating a new folder holding your future svn repositories:</p>
<pre>sudo mkdir /usr/local/svn</pre>
<p>Make sure you change the folder&#8217;s owner to &#8220;www&#8221; in order to make it accesable through apache:</p>
<pre>sudo chown -R www:www /usr/local/svn</pre>
<p>Now create a new repository:</p>
<pre>sudo svnserve create /user/local/svn/foo</pre>
<p>where foo is your repository&#8217;s name.</p>
<p>Make sure, apache is running by checking your system preferences and enabling <em>web sharing</em>.</p>
<p><a href="http://blog.root-of-all-evil.com/wp-content/uploads/2010/08/Bildschirmfoto-2010-08-26-um-18.42.30.png" rel="lightbox[822]"><img class="aligncenter size-medium wp-image-823" title="Bildschirmfoto 2010-08-26 um 18.42.30" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/08/Bildschirmfoto-2010-08-26-um-18.42.30-300x132.png" alt="" width="300" height="132" /></a>Now create a new file named <em>svn.conf</em> and place it in <em>/etc/apache2/other</em>. Type the following into the file:</p>
<pre>LoadModule dav_svn_module /usr/libexec/apache2/mod_dav_svn.so
&lt;Location /svn&gt;
  DAV svn
  SVNParentPath /usr/local/svn
&lt;/Location&gt;</pre>
<p>Restart apache by typing</p>
<pre>sudo apachectl graceful</pre>
<p>into your terminal. And you&#8217;re ready and set. Access your repository through <em>http://localhost/svn</em>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/08/setting-up-svn-on-mac-os-x-quick-easy/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Entwickeln mit Zend &#8211; Teil 1, Einführung</title>
		<link>http://blog.root-of-all-evil.com/2010/03/entwickeln-mit-zend-teil-1-einfuhrung/</link>
		<comments>http://blog.root-of-all-evil.com/2010/03/entwickeln-mit-zend-teil-1-einfuhrung/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 14:27:59 +0000</pubDate>
		<dc:creator>Felix</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekt]]></category>
		<category><![CDATA[Framework]]></category>
		<category><![CDATA[Projekt mit Zend]]></category>
		<category><![CDATA[Zend]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend Server]]></category>
		<category><![CDATA[Zend Studio]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=447</guid>
		<description><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/03/entwickeln-mit-zend-teil-1-einfuhrung/" title="Entwickeln mit Zend - Teil 1, Einführung"></a>In dieser Reihe von Publizierungen werden alle notwendigen Schritte beschrieben, eine professionelle Entwicklungsumgebung aufzusetzen mit welcher mit dem Zend Framework entwickelt werden kann. Als ZF-Projekt soll beispielhaft ein Gästebuch mit Administrationsbereich erstellt werden. Hierfür wird zuerst auf dem System (Windows &#8230;<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/03/entwickeln-mit-zend-teil-1-einfuhrung/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/03/entwickeln-mit-zend-teil-1-einfuhrung/" title="Entwickeln mit Zend - Teil 1, Einführung"></a><p>In dieser Reihe von Publizierungen werden alle notwendigen Schritte beschrieben, eine professionelle Entwicklungsumgebung aufzusetzen mit welcher mit dem <a href="http://framework.zend.com/">Zend Framework</a> entwickelt werden kann. Als ZF-Projekt soll beispielhaft ein Gästebuch mit Administrationsbereich erstellt werden.</p>
<p>Hierfür wird zuerst auf dem System (Windows 7) Apache, MySQL und PHP installiert (Zend Community Server) und der Apache entsprechend konfiguriert, dass das zukünftige Projekt über Virtual Hosts ansprechbar ist. Um den Code komfortabel zu verwalten verwenden wir das Versionskontrollsystem Subversion welches wir gegen unbefugte Benutzung absichern werden. Anschließend wird eine Entwicklungsumgebung (Zend Studio für Eclipse) installiert, welche komfortabel mit der Versionsverwaltung und dem Server zusammenarbeiten kann.</p>
<p>Letzlich wird begonnen das eigentliche Projekt, die Programmierung des Gästebuchs, mit Hilfe von verschiedenen Pattern (z.B. MVC) umzusetzen.</p>
<h3><span id="more-447"></span>Was ist das Zend Framework</h3>
<p>Das Zend Framework (oft abgekürzt mit ZF) ist ein komponentenorientieres Framework für PHP 5, welches zahlreiche Klassen bereit stellt mit welchen sehr komfortabel Anwendungen entwickelt werden können.<br />
Komponentenorientiert in diesen Zusammenhang heißt, dass neue Anwendungen komplett auf dem Framework bassierend entwickelt werden können- alternativ können zu bestehenden Anwendungen aber auch nur bestimmte Funktionen, z.B. Cacheing, Authentifizierung, von dem Framework genutzt werden.<br />
Im März 2006 wurde die erste Pre-Alpha-Version 0.1.1 vorgestellt und wird seit dem stetig von Zend Technologies &#8211; den Entwicklern von PHP &#8211; weiterentwickelt.</p>
<h3>Warum das Zend Framework</h3>
<p>Frameworks sind mehrere dutzende verfügbar, eine Wahl fällt hier auf den ersten Blick sehr schwer. Stellt man jedoch eine Reihe von Kriterien auf, wird die Auswahl schnell auf wenige eingeschränkt. Ich möchte hier nur ein Paar der zahlreichen Vorteile listen, welche ich bei dem Zend Framework gegenüber anderen Frameworks sehe:</p>
<ul>
<li>Komponentenbasierend<br />
Wie bereits im Paragraphen &#8220;Was ist das Zend Framework&#8221; beschrieben. Um das ZF zu nutzen müssen bestehende Anwendungen nicht neu geschrieben werden, sondern es können bestimmte Funktionalitäten ohne großen Aufwand genutzt werden.<br />
Zahlreiche Standardaufgaben wie Formularerstellung und -validierung, E-Mailversandt oder Templates werden durch die Komponenten abgedeckt.<br />
Durch  durchgehend benutzte Design Patterns (&#8220;Entwicklungsmuster&#8221;) und Adapter (ein Art abkopelbarer Zwischenschritt) können sehr schnell durch wenige Zeilen Code große Teile der Anwendung umgeschrieben werden.  So ist es z.B. innerhalb weniger Sekunden möglich die Anwendung so umzuschreiben, dass diese zukünftig in einer ini-/ xml-Datei oder SQLite-DB statt in einer Oracle-/ MySQL-Datenbank Fehlermeldungen protokolliert.</li>
</ul>
<ul>
<li>Community<br />
Das ZF hat eine sehr große Community die von Zend selbst wiederum stark gefördert wird (siehe <a href="http://framework.zend.com/wiki/display/ZFDEV/Home">Zend Framework Wiki</a>). Es existieren zahlreiche, natürlich auch deutschsprachige, Foren, Blogs und Tutorials die sich mit dem ZF beschäftigen.</li>
</ul>
<ul>
<li>Dokumentation<br />
Das ZF ist vorbildhaft dokumentiert. Die Dokumentation wird von Zend selbst immer auf den neusten Stand gehalten, ist in zahlreichen Sprachen verfügbar und verfügt über zahlreiche Beispiele und Tutorials.</li>
</ul>
<ul>
<li>Web 2.0<br />
Es stehen zahlreiche Klassen bereit, mit welchen man die Services von Google, Delicous, YouTube, Flickr, Yahoo, Amazon etc. ohne hohe Einarbeitungszeit nutzen kann.</li>
</ul>
<ul>
<li>Ajax<br />
Das <a href="http://www.dojotoolkit.org/">Dojo Toolkit</a> ist in das ZF integriert. Hierdurch können sehr schnell Ajax-Applikationen erstellt werden.<br />
Auch hier gilt wieder &#8211; Dojo kann verwendet werden, muss aber nicht. Sind sie bereits ein anderes Framework gewohnt, können Sie dieses ebenfalls mit dem ZF nutzen.</li>
</ul>
<ul>
<li>Weiterentwicklung<br />
Da hinter dem ZF die Zend Technologies steht, ist eine in Zukunft Weiterentwicklung gesichert &#8211; ein großer Pluspunkt im Vergleich zu anderen Frameworks.</li>
</ul>
<ul>
<li>Lizenzierung/Kosten<br />
Das ZF steht unter der <a href="http://de.wikipedia.org/wiki/BSD-Lizenz">BSD-Lizenz.</a> Kosten entstehen also nicht.</li>
</ul>
<ul>
<li>Testbasis<br />
Alle Komponenten werden über Unit-Tests getestet. Auch ist es so dem Entwickler möglich, mit relativ wenig Aufwand Tests für seine Applikation zu schreiben.</li>
</ul>
<h3>Warum Zend-Software</h3>
<p>In der Einleitung war schon abzulesen, dass hier fast nur Software von Zend verwendet wird. Hintergrund für diese Wahl ist, dass ich persönlich von den Zend-Produkten überzeugt bin: sie zeichnen sich aus durch eine komfortable, leicht zu erlernende Bedienung und zahlreiche kleine Tools welche die tägliche Arbeit stark erleichtern.</p>
<p><strong>Vorteile</strong></p>
<p>So ist es z.B. beim Zend Server möglich über eine Web-GUI schnell die Konfiguration zu ändern (z.B. bestimmte PHP-Extensions oder Error-Logging zu (de)aktivieren) und weil alles &#8220;aus einer Hand&#8221; kommt wird beim ersten Start von Zend Studio (nur eines von zahlreichen weiteren Beispielen) automatisch der Zend Server gefunden und das Debugging konfiguriert. Natürlich stell Zend Studio auch zahlreiche Tools bereit welche das Arbeiten mit dem ZF noch mehr beschleunigen. Mit Zend Tools ist übrigens ein Server-debugging möglich, das heißt der Code kann auf dem Server selbst, unabhängig vom Code in der Entwicklungsumgebung inspiziert werden.<br />
Zend Studio setzt auf Eclipse auf &#8211; es können also die Plugins welche man bereits in Eclipse verwendet hat bzw. kennt, auch in Zend Studio verwenden.</p>
<p><strong>Nachteile</strong></p>
<p>Nach viel Lob und Tadel sollen natürlich auch die negativen Aspekte beleuchtet werden: Zend Studio (Eclipse)  benötigt relativ viel Arbeitsspeicher. Sind mehrere große Projekte parallel geöffnet kann dies den Rechner schon stark belasten (insbesondere wenn Tools wie der HTML-Validator aktiv sind).<br />
Zahlreiche Kinderkrankheiten wurden in Verison 7.1 behoben, welches ein Update auf diese Version obligatorisch ist.<br />
Eine offizielle 64-Bit Version für Linux ist noch nicht verfügbar &#8211; zwar kann man die 32-Bit Version installieren, dies läuft aber instabil.<br />
Die Entwicklungsumgebung mag hin und wieder ein wenig oversized wirken: man kann wirklich alles damit machen. Über SSH auf einen Server zugreifen und direkt Remote Dateien editieren oder direkt Datenbanken entwickeln &#8211; dies ist aber manchmal einfach zuviel des guten wenn man nur &#8220;ein paar Zeilen Code&#8221; schreiben will.<br />
Auch arbeiten manche Funktionen, z.B. die Codevervollständigung in Javascript, nicht fehlerfrei; andere Funktionen welche z.B. den Code auf (logische) Korrektheit prüfen arbeiten suboptimal, sodass nach einem Import eines Projektes mehrere 1000 angbliche Fehler gelistet werden &#8211; dabei steht aber z.B. der schließende Tag in einer includeten-Datei, was Zend natürlich nicht weiß.</p>
<p><strong>Kosten</strong></p>
<p>Der Zend Server ist in der sog. Community Edition (eingeschränkter Fuktionsumfang) kostenlos erhältich. Für die Entwicklung reichen die Funktionen jedoch voll und ganz aus. Zend Studio kostet mit einem 1-Jahres-Abo für Updates und Support 399€, dies ist jedoch verglichen mit Funktionsumfang ok. Eine Testversion für 30 Tage ist verfügbar.</p>
<h3>Ausblick</h3>
<p>Im nächsten Beitrag werden wir den Zend Server CE herunterladen und installieren. Es wird ein kurzer Überblick über die Funktionen gegeben. Anschließend werden wir noch zwei Virtual Hosts einrichten (live, development) über welche unsere zukünftige Anwendung dann erreichbar sein wird.</p>
<p><strong>Wichtige Links</strong></p>
<ul>
<li><a href="http://www.ralfeggert.de/">http://www.zend.com/de/</a> &#8211; Zend Technologies, Download von Zend Studio und Zend Server CE.</li>
<li><a href="http://framework.zend.com ">http://framework.zend.com </a>- Zend Framework, die offizielle Seite von ZF. Mit Links zur Dokumentation, Tutorials und dem ZF Wiki.</li>
<li><a href="http://www.dojotoolkit.org/">http://www.dojotoolkit.org/</a> &#8211; Dojo Toolkit, das in ZF integrierte Ajax-Toolkit</li>
<li><a href="http://www.zfforums.com/">http://www.zfforums.com/</a> &#8211; ZF Forum, englischsprachiges ZF Forum.</li>
<li><a href="http://www.ralfeggert.de/">http://www.ralfeggert.de/</a> &#8211; Blog von Ralf Eggert, blogt über das ZF und PHP allgemein.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/03/entwickeln-mit-zend-teil-1-einfuhrung/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thumbnails erzeugen und Durchschnittsfarbe in PHP ermitteln</title>
		<link>http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln/</link>
		<comments>http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 19:36:22 +0000</pubDate>
		<dc:creator>Philipp</dc:creator>
				<category><![CDATA[Codeschnipsel]]></category>
		<category><![CDATA[Guides]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekt]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[Durchschnittsfarbe]]></category>
		<category><![CDATA[Imagecolorat]]></category>
		<category><![CDATA[Imagecopyresampled]]></category>
		<category><![CDATA[Thumbnails generieren]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=435</guid>
		<description><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln/" title="Thumbnails erzeugen und Durchschnittsfarbe in PHP ermitteln"></a>Eines meiner etwas zurückliegenden Projekte zwang mich externe Bilder durch meinen Server zu laden, zu verkleinern und schließlich auch die Durchschnittsfarbe zu berechnen. Aus Gründen der Performancesteigerung war ich nie ein Fan davon die Durchschnittsfarbe Pixel für Pixel des Originalbildes &#8230;<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln/" title="Thumbnails erzeugen und Durchschnittsfarbe in PHP ermitteln"></a><p>Eines meiner etwas <a title="qolors.net Visual Bookmarking" href="http://www.qolors.net" target="_blank">zurückliegenden Projekte</a> zwang mich externe Bilder durch meinen Server zu laden, zu verkleinern und schließlich auch die Durchschnittsfarbe zu berechnen. Aus Gründen der Performancesteigerung war ich nie ein Fan davon die Durchschnittsfarbe Pixel für Pixel des Originalbildes zu berechnen. <a href="http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln#durchschnittsfarbe" title="zum Berechnen der Durchschnittsfarbe springen">Es gibt eine viel elegantere und fast genauso exakte Lösung</a>:</p>
<p><span id="more-435"></span>Unser Ziel: Wir möchten ein Bild (jpg, gif, png) über einen HTTP-Stream laden,  dieses lokal auf dem Server speichern, ein entsprechendes Thumbnail  (eine verkleinerte Version) erzeugen, speichern und schlussendlich die  dominierende &#8211; oder auch durchschnittliche &#8211; Farbe im Bild berechnen und  abspeichern. Eventuell möchten wir zusätzlich alles in einer Datenbank  hinterlegen &#8211; das soll aber zunächst außerhalb unserer Betrachtung  liegen.</p>
<p>Für das Berechnen der Durchschnittsfarbe gibt es einen wunderbar  einfachen Trick. Doch dazu später mehr. Beginnen wir zunächst einmal mit  einer Konstante und einer Funktion, die wir später noch benötigen:</p>
<pre class="php" title="code">DEFINE('CTX', stream_context_create(array(
    'http' =&gt; array(
        'timeout' =&gt; 20,
        'method' =&gt; 'get',
        'header' =&gt; 'Referer: XYZ'
    )
)));</pre>
<p>Unsere Konstante CTX ist also ein array. Wir benötigen es für unsere  HTTP-Anfrage, mit der wir das gewünschte Bild auf unseren Server laden.  Für diese Anfrage verwenden wir die HTTP-GET-Methode, definieren einen  Timeout von maximal 20 Sekunden und senden einen Referer im Header, den  ich hier mal einfach nur &#8220;XYZ&#8221; genannt habe.</p>
<pre class="php" title="code">function randomstring_creator($len = 20) {
    $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $string = '';
    mt_srand((double) microtime() * 1000000);
    for($i = 0; $i &lt; $len; $i++) {
        $string .= $chars{mt_rand(0, strlen($chars))};
    }
    return($string);
}</pre>
<p>Die Funktion randomstring_creator() generiert uns eine zufällige Zeichenfolge mit einer beliebigen Länge. Wir benötigen diese Funktion, da wir in diesem Beispiel die Bilder lokal unter einem zufälligem Namen speichern werden.</p>
<p>Weiter geht es mit unseren Klassen. Beginnen wir mit der Klasse <em>Image</em>:</p>
<pre class="php" title="code">class Image {
    var $img;
    var $source;
    var $local;
    var $dimX;
    var $dimY;
    var $avg_colour;
    function get($source, $quality = 90) {
// siehe unten
    }
    function calc_avg_colour() {
// siehe unten
    }
}</pre>
<p>Unsere Klasse besitzt also die Eigenschaften <em>source </em>(die Url,  von der das Bild stammt), <em>local </em>(den lokalen Speicherpfad), <em>dimX</em>,  <em>dimY </em>(die Abmessungen des Bildes in Pixel) und <em>avg_colour</em> (den farblichen Durchschnittswert als HEX-Code in der Form rrggbb). Die  Eigenschaft <em>img </em>ist eine Referenz auf das Image-Objekt, dass ich  aber später noch näher beleuchten werde.</p>
<p>Die beiden Funktionen <em>get()</em> und <em>calc_avg_colour()</em> der  Klasse sollten selbsterklärend sein. Mit der Funktion <em>get()</em>, die  gleichzeitig auch als Konstruktor dient, laden wir das Bild, dass unter <em>source </em>zu finden ist, auf unseren Server und speichern es in der  gewünschten JPEG-Qualität (90 als Standard) lokal.</p>
<p><em>calc_avg_colour()</em> berechnet &#8211; wie der Name schon sagt &#8211; die  Durchschnittsfarbe des in der Eigenschaft <em>img</em> gespeicherten  Bildes.</p>
<p>Wir wollen zusätzlich aber auch kleine Abbilder des Originalbildes  erstellen und erweitern dazu unsere <em>Image</em>-Klasse um die Klasse <em>Thumbnail</em>:</p>
<pre class="php" title="code">class Thumbnail extends Image {
    function create($parent, $X = 300, $Y = 300, $quality = 60) {
// siehe unten
    }
}</pre>
<p>Diese Erweiterung besitzt zunächst nur eine Funktion, mit der das  Thumbnail erstellt wird. Die übergebene Variable <em>parent </em>enthält  dabei eine bereits existierende <em>Image</em>-Klasse, die  herunterskaliert werden soll. Die maximale Breite und Höhe werden mit  den Variablen <em>X</em> und <em>Y</em> (standard bei 300 Pixel) übergeben.  Die JPEG-Qualität beträgt standardmäßig nur 60.</p>
<p>Das eigentliche Programm sieht dann nur noch so aus:</p>
<pre class="php" title="code">$imgurl = 'original.jpg';
// neues Objekt der Klasse Image erzeugen
$img = new Image;
// Bild aus der imgurl laden
if($img-&gt;get($imgurl)) {
    // ein Objekt der Klasse Thumbnail erzeugen
    $thumb = new Thumbnail;
    // und ein Thumbnail des oben definierten Objektes der Klasse Image generieren
    $thumb-&gt;create($img, 300, 300);
    // dann noch die Durschschnittsfarbe berechnen
    $thumb-&gt;calc_avg_colour();
    // und Daten ausgeben... fertig
    echo('Image: ' . $img-&gt;source . "\n");
    echo('Thumbnail: ' . $thumb-&gt;source . "\n");
    echo('Average colour: #' . $thumb-&gt;avg_colour . "\n");
} else {
    echo('Could not get the image.');
}</pre>
<p>So, dann sehen wir uns also mal unsere Funktionen der Klassen an.  Beginnen wir mit der Funktion <em>get()</em>:</p>
<pre class="php" title="code">function get($source, $quality = 90) {
    $this-&gt;source = $source;
    // wir laden das Bild von $source:
    if(($file = file_get_contents($this-&gt;source, false, CTX))) {
        // wenn erfolgreich, erzeugen wir mit den geladenen Daten
        // ein neues Bild und speichern dieses in der Eigenschaft img
        $this-&gt;img = imagecreatefromstring($file);
        // wir lesen die Höhe und Breite des Bildes aus
        $this-&gt;dimX = imagesx($this-&gt;img);
        $this-&gt;dimY = imagesy($this-&gt;img);
        // und speichern das Bild unter zufälligem Namen mit imagejpeg lokal im Ordner "raw"
        $this-&gt;local = 'raw/' . randomstring_creator() . '.jpg';
        imagejpeg($this-&gt;img, $this-&gt;local, $quality);
        // bei Erfolg true zurückgeben
        return(true);
    } else {
        // false, wenn das Bild nicht geladen werden konnte
        return(false);
    }
}</pre>
<p>Ein Thumbnail erzeugen wir mit dieser Funktion der Klasse <em>Thumbnail</em>:</p>
<pre class="php" title="code">function create($parent, $X = 300, $Y = 300, $quality = 60) {
    // zunächst die vorläufigen Abmessungen speichern
    $this-&gt;dimX = $X;
    $this-&gt;dimY = $Y;
    // die Abmessungen und deren Verhältnis des Originalbildes holen
    $origX = $parent-&gt;dimX;
    $origY = $parent-&gt;dimY;
    $ratio = $origX / $origY;
    // wenn das Originalbild breiter als hoch ist, kürzen wir die Höhe
    if($X / $Y &gt; $ratio) {
        $this-&gt;dimX = $Y * $ratio;
    } else {
    // wenn das Originalbild höher als breit ist, kürzen wir die Breite
        $this-&gt;dimY = $X / $ratio;
    }
    // hier erstellen wir ein neues Bild mit den oben berechneten Abmessungen
    $this-&gt;img = imagecreatetruecolor($this-&gt;dimX, $this-&gt;dimY);
    // und kopieren das Originalbild einfach in das eben erstellte kleinere, dabei wird es verkleinert
    imagecopyresampled($this-&gt;img, $parent-&gt;img, 0, 0, 0, 0, $this-&gt;dimX, $this-&gt;dimY, $origX, $origY);
    // jetzt speichern wir das neue Thumbnail noch unter zufälligem Namen im Ordner "thumb"
    $this-&gt;source = $parent-&gt;local;
    $this-&gt;local = 'thumb/' . randomstring_creator() . '.jpg';
    imagejpeg($this-&gt;img, $this-&gt;local, $quality);
}</pre>
<p>Das Herzstück: Wir wollen die  Durchschnittsfarbe ermitteln. Dazu könnten wir einfach alle Farbwerte  aller Pixel zusammen addieren und dann durch die Anzahl der Pixel  teilen. Bei einem Thumbnail von der Größe 300 x 300 Pixel, würden wir  aber eine Schleife mit 90.000 Durchläufen benötigen. Es gibt einen  besseren Weg &#8211; einen ganz logischen Trick.<br />
<a name="durchschnittsfarbe"></a><br />
<h3>Durchschnittsfarbe berechnen</h3>
<p>Wir haben oben beim Erstellen des Thumbnails die Funktion <em>imagecopyresampled()</em> verwendet. Was wenn wir unser Thumbnail einfach auf eine Größe von 1&#215;1  Pixel skalieren? Genau: Es bleibt ein Pixel mit der Durschnittsfarbe  übrig. Dessen Farbe auszulesen ist mit <em>imagecolorat()</em> dann nur  noch eine Kleinigkeit. Los gehts:</p>
<pre class="php" title="code">function calc_avg_colour() {
    // ein temporäres Bild mit den Abmessungen 1x1 Pixel erstellen
    $avrg = imagecreatetruecolor(1, 1);
    // Das Thumbnail einfach reinkopieren, dabei auf 1x1 Pixel skalieren
    imagecopyresampled($avrg, $this-&gt;img, 0, 0, 0, 0, 1, 1, $this-&gt;dimX, $this-&gt;dimY);
    // Die Farbe des verbleibenden Pixels auslesen
    $rgb = imagecolorat($avrg, 0, 0);
    // Das temporäre Bild wieder löschen
    imagedestroy($avrg);
    // Und die Farbe in HEX umwandeln
    $r = dechex($rgb &gt;&gt; 16);
    $g = dechex($rgb &gt;&gt; 8 &amp; 255);
    $b = dechex($rgb &amp; 255);
    if(strlen($r) &lt; 2) $r = 0 . $r;
    if(strlen($g) &lt; 2) $g = 0 . $g;
    if(strlen($b) &lt; 2) $b = 0 . $b;
    // tataaaa... da ist unsere Durchschnittsfarbe:
    $this-&gt;avg_colour = $r . $g . $b;
}</pre>
<p>Super. Das wäre es. Ende und aus.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Das Zend Framework und die eBay trading API – Teil 4</title>
		<link>http://blog.root-of-all-evil.com/2010/02/das-zend-framework-und-die-ebay-trading-api-%e2%80%93-teil-4/</link>
		<comments>http://blog.root-of-all-evil.com/2010/02/das-zend-framework-und-die-ebay-trading-api-%e2%80%93-teil-4/#comments</comments>
		<pubDate>Thu, 11 Feb 2010 16:09:35 +0000</pubDate>
		<dc:creator>Philipp</dc:creator>
				<category><![CDATA[Codeschnipsel]]></category>
		<category><![CDATA[Guides]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekt]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[eBay]]></category>
		<category><![CDATA[Guide]]></category>
		<category><![CDATA[trading API]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Zend]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=370</guid>
		<description><![CDATA[Wir werden einen Prozess schaffen, der es dem Nutzer erlaubt den eBay User Consent Flow mit Hilfe unserer Webapplikation zu durchschreiten. Dieser Prozess soll möglichst unkompliziert, direkt und intuitiv bedienbar sein. Ich empfehle also die Verwendung von Ajax-Methoden um das User Interface und den darzustellenden Prozess zu visualisieren. Wie das Zend Framework mit Ajax Anfragen umgehen kann wird hier also auch Thema sein.<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/02/das-zend-framework-und-die-ebay-trading-api-%e2%80%93-teil-4/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/02/das-zend-framework-und-die-ebay-trading-api-%e2%80%93-teil-4/" title="Das Zend Framework und die eBay trading API – Teil 4"></a><p>Die ersten drei Teile dieser Reihe hatten sich mit der theoretischen und praktischen Implementierung des User Consent Flow Prozesses, der für die Authentifizierung des Nutzers mit und der Verwendung der eBay Trading API notwendig ist, befasst. Im vierten und letzten Teil sollen die Implementierungen der letzten drei Teile (<a title="Zum ersten Teil dieses Guides" href="http://blog.root-of-all-evil.com/?p=131" target="_self">Teil 1</a>, <a title="Teil zwei dieser Reihe" href="http://blog.root-of-all-evil.com/?p=161" target="_self">Teil 2</a>, <a title="Der dritte Teil dieser Reihe" href="http://blog.root-of-all-evil.com/?p=205" target="_self">Teil 3</a>) dieser Reihe in die Controller und Views umgesetzt und so ein visueller Anmelde- und Authentifizierungsprozess geschaffen werden.</p>
<h3>Was wird Teil 4 dieses Guides zeigen?</h3>
<p>Wir werden einen Prozess schaffen, der es dem Nutzer erlaubt den eBay User Consent Flow mit Hilfe unserer Webapplikation zu durchschreiten. Dieser Prozess soll möglichst unkompliziert, direkt und intuitiv bedienbar sein. Ich empfehle also die Verwendung von Ajax-Methoden um das User Interface und den darzustellenden Prozess zu visualisieren. Wie das Zend Framework mit Ajax Anfragen umgehen kann wird hier also auch Thema sein.<span id="more-370"></span></p>
<h3>Warum Ajax?</h3>
<p>Wenn wir uns eben an den Ablauf des (<a title="Teil 1" href="http://blog.root-of-all-evil.com/?p=131" target="_blank">in Teil 1 ausführlich beschriebenen</a>) Consent Flow Prozesses erinnern: Der Benutzer muss selbst nur wenige Klicks und Eingaben machen &#8211; namentlich die Anmeldung auf der eBay Login-Seite zu der er weitergeleitet wird. Im Hintergrund muss unsere Applikation allerdings zwei Anfragen machen. (1) Eine SessionID von der eBay trading API anfragen und (2) nach der Rückkehr des Benutzers<a href="http://blog.root-of-all-evil.com/wp-content/uploads/2010/01/ebayConsentFlow.jpg" rel="lightbox[370]"><img class="alignright size-thumbnail wp-image-139" title="eBayUserConsentFlow" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/01/ebayConsentFlow-150x150.jpg" alt="Der eBay User Consent Flow" width="150" height="150" /></a> zur Applikation den mit der SessionID verknüpften Auth-Token anfragen.</p>
<p>Hier empfehle ich Ajax: Dem Benutzer soll visualisiert werden, dass sich hinter den Kulissen etwas tut und nicht lange auf den Seitenaufbau warten müssen (die API-Anfragen dauern ein paar wenige Sekunden). Wir werden also die Seite ausliefern, und von dieser eine Ajax-Anfrage starten, die die getSessionID und später die fetchToken Actionen anstoßen wird. Der Benutzer wird ein Lade-Grafik sehen und damit merken, dass sich etwas tut. Die Weiterleitung soll vollautomatisch erfolgen. Das Ergebnis sieht also keinerlei Actionen vom Benutzer auf unserer Applikation vor. Er muss lediglich warten bis er zu eBay weiter geleitet wird und sich dort anmelden kann.</p>
<p><img class="aligncenter size-full wp-image-374" title="consentFlowGUI" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/02/consentFlowGUI.jpg" alt="" width="500" height="220" /></p>
<h3>Die benötigten Actions</h3>
<p>Wie in Teil 2 bereits aufgestellt brauchen wir neben dem Ebayauth Controller folgende fünf Actions:</p>
<ul>
<li><em>index</em> (stößt den Consent Flow an)<em><br />
</em></li>
<li><em>step1</em> (ist Ziel eines Ajax-Requests &#8211; übernimmt getSessionID)</li>
<li><em>success </em>(bei erfolgreichem Login auf eBay wird der Benutzer hierhin  weitergeleitet)</li>
<li><em>step2 </em>(ist Ziel eines Ajax-Requests &#8211; übernimmt fetchToken)</li>
<li>und <em>denied</em> (bei fehlgeschlagenem oder abgebrochenen Login)<em><br />
</em></li>
</ul>
<p>und vier Views für den Controller <em>Ebayauth</em>:</p>
<ul>
<li><em>index.phtml</em></li>
<li><em>step1.ajax.phtml</em></li>
<li><em>success.phtml<br />
</em></li>
<li><em>step2.ajax.phtml</em></li>
<li>und <em>denied.phtml</em></li>
</ul>
<h3>Ajax Requests erkennen und entsprechend handeln</h3>
<p>Um die Unterscheidung zwischen &#8216;normalem&#8217; Request und einem Ajax-Request können wir einen Context-Switcher verwenden, den uns das Zend Framework zur Verfügung stellt. Dieser muss in der init()-Methode des Controllers initialisiert werden uns sieht in unserem Fall so aus:</p>
<pre class="php" title="code">$contextSwitch = $this-&gt;_helper-&gt;getHelper('AjaxContext');
$contextSwitch-&gt;addActionContext('step1', 'html') // wir geben html zurück
              -&gt;addActionContext('step2', 'html') // möglich wäre auch xml oder json
              -&gt;initContext();

// Das übrige Layout abschalten
if($this-&gt;_request-&gt;isXmlHttpRequest()) {
     $this-&gt;_helper-&gt;layout-&gt;disableLayout();
}</pre>
<p>Unsere zwei step Actions benötigen noch eine kleine Fallunterscheidung. Wir möchten sie nur ausführen lassen, wenn es sich tatsächlich um einen Ajax-Request handelt:</p>
<pre class="php" title="code">if(!$this-&gt;_request-&gt;isXmlHttpRequest()) {
    $this-&gt;_redirect('/ebayauth/index'); // zum Start des Auth-Prozesses umleiten
}</pre>
<h3>Der Controller Ebayauth</h3>
<p>Springen wir gleich in den Code:</p>
<pre class="php" title="code">public function indexAction() {}

public function step1Action()
{
    if(!$this-&gt;_request-&gt;isXmlHttpRequest()) {
        $this-&gt;_redirect('/ebayauth/index');
    }

    // die getSessionID API-Anfrage durchführen
    $tokenAdapter = new Ebay_Auth_ConsentFlow();
    $return = $tokenAdapter-&gt;getSessionID();

    // Wir müssen die SessionID in einer Datenbank oä. zwischenspeichern
    $modelAccount = new Model_Account();

    if($return != false) {
        // zwischenspeichern - bitte durch eigenen Implementierung ersetzen
        $modelAccount-&gt;writeEbaySessionId($this-&gt;accountID, $return['sessionId']);
        if(isset($return-&gt;ShortMessage)) {
            // bei Fehler ist ShortMessage teil der API Rückgabe
            $this-&gt;view-&gt;error = (string)$return-&gt;ShortMessage;
        } else {
            $this-&gt;view-&gt;redirectURL = $return['redirectUrl'];
        }
    } else {
        $this-&gt;view-&gt;error = 'Keine Verbindung zu eBay.';
    }
}

public function successAction() {}

public function step2Action()
{
    if(!$this-&gt;_request-&gt;isXmlHttpRequest()) {
        $this-&gt;_redirect('/ebayauth/index');
    }

    // die im step1 zwischengespeicherte SessionID aus der Datenbank holen
    $modelAccount = new Model_Account();
    $sessionId = $modelAccount-&gt;getEbaySessionId($this-&gt;accountID);

    // die fetchToken API Anfrage ausführen
    $tokenAdapter = new Ebay_Auth_ConsentFlow();
    $return = $tokenAdapter-&gt;getToken($sessionId);

    if($return != false) {
        // auch hier wieder eigenen Implementierung Verwenden
        $modelAccount-&gt;writeEbayTokenId($this-&gt;accountID, $return['token'], $return['expiration']);
        if(isset($return-&gt;ShortMessage)) {
            $this-&gt;view-&gt;error = (string)$return-&gt;ShortMessage;
        } else {
            // Hier festlegen wohin umgeleitet werden soll
            $this-&gt;view-&gt;redirectURL = '/'; // zurück zur Startseiten
            $this-&gt;view-&gt;expiration = $return['expiration'];
        }
    } else {
        $this-&gt;view-&gt;error = 'Keine Verbindung zu eBay';
    }
}

public function deniedAction() {}</pre>
<p>Die drei Actions index, success und denied benötigen keine Methoden im Controller. Der JavaScript, der den Ajax-Request anstößt coden wir einfach fest in die views ein.</p>
<h3>Die Views</h3>
<p>Das hier ist der index view (<em>index.phtml</em>). Wir binden ein JavaScript ein und rufen die Funktion <em>shootAjaxHtml()</em> auf.</p>
<pre class="php" title="code">&lt;div&gt;
    &lt;div id="loader" class="redirect"&gt;&lt;img src="/images/preloader.gif" /&gt; Weiterleitung an eBay wird vorbereitet ...
        &lt;script type="text/javascript"&gt;shootAjaxHtml('/ebay/step1', 'loader')&lt;/script&gt;
    &lt;/div&gt;
&lt;/div&gt;</pre>
<p>Der <em>step1.ajax.phtml</em> View:</p>
<pre class="php" title="code">&lt;?php if(isset($this-&gt;redirectURL)) { ?&gt;
&lt;p&gt;Automatische Weiterleitung zu eBay in wenigen Sekunden. &lt;a href="&lt;?php echo($this-&gt;redirectURL); ?&gt;" title="Weiterleitung"&gt;Oder hier klicken.&lt;/a&gt;&lt;/p&gt;
&lt;script type="text/javascript"&gt;window.location = '&lt;?php echo($this-&gt;redirectURL); ?&gt;';&lt;/script&gt;
&lt;?php } elseif(isset($this-&gt;error)) { ?&gt;
&lt;p class="error"&gt;&lt;strong&gt;Fehler:&lt;/strong&gt; &lt;?php echo $this-&gt;error; ?&gt;&lt;/p&gt;
&lt;?php } ?&gt;</pre>
<p><em>success.phtml</em>:</p>
<pre class="php" title="code">&lt;div&gt;
    &lt;div id="loader" class="redirect"&gt;&lt;img src="&lt;?php echo SKINPATH; ?&gt;/images/preloader.gif" /&gt; eBay Anmeldung wird abgeschlossen ...
        &lt;script type="text/javascript"&gt;shootAjaxHtml('/ebay/authgettoken', 'loader')&lt;/script&gt;
    &lt;/div&gt;
&lt;/div&gt;</pre>
<p>Und <em>step2.ajax.phtml</em>:</p>
<pre class="php" title="code">&lt;?php if(isset($this-&gt;redirectURL)) { ?&gt;
&lt;p class="info"&gt;Die Verknüpfung des Benutzerkontos mit eBay verliert am &lt;?php echo date('d.m.Y', strtotime($this-&gt;expiration)); ?&gt; um &lt;?php echo date('H:m', strtotime($this-&gt;expiration)); ?&gt; Uhr seine Gültigkeit.&lt;/p&gt;
&lt;p&gt;&lt;a href="/ebay" class="black" title="Zurück zur Startseite"&gt;Weiter&lt;/a&gt;&lt;/p&gt;
&lt;?php } elseif(isset($this-&gt;error)) { ?&gt;
&lt;p class="error"&gt;&lt;strong&gt;Fehler:&lt;/strong&gt; &lt;?php echo $this-&gt;error; ?&gt;&lt;/p&gt;
&lt;?php } ?&gt;</pre>
<p>Im denied View gebe ich nur eine Fehlermeldung wie &#8220;Anmeldung fehlgeschlagen&#8221;.</p>
<h3>Der JavaScript (mit mootools):</h3>
<pre class="javascript" title="code">function shootAjaxHtml(action, loaderid)
{
    var remote = new Request.HTML({
        url: action + "?format=html",
        onSuccess: function(html) {
            $(loaderid).getParent('div').empty().adopt(html);
        },
        onFailure: function(xhr) {
            $(loaderid).getParent('div').empty().adopt(new Element('p').set('text', 'Es ist ein Fehler aufgetreten: ' +xhr.status +' ' +xhr.statusText).addClass('error'));
        }}).get();
}</pre>
<p>Und damit sind wir auch schon fertig.</p>
<p>Ich hoffe die ersten drei Teile dieser Einführung in eine Mögliche Implementierung des Consent Flows der eBay trading API in eine Webapplikation mit dem Zend Framework waren gut verständlich und konnten einen guten Überblick über die benötigten Implementierungsschritte geben. Teil vier hat anhand von Codebeispielen gezeigt, wie man den Consent Flow möglichst benutzerfreundlich umsetzen kann.</p>
<p>Empfehlungen, Anmerkungen, Verbesserungsvorschläge? Dazu sind die Kommentare da!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/02/das-zend-framework-und-die-ebay-trading-api-%e2%80%93-teil-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Serverseitig den Webseitenaufbau mit DNS CNAMES und mehr parallele HTTP-Verbindungen beschleunigen</title>
		<link>http://blog.root-of-all-evil.com/2010/02/serverseitig-den-webseitenaufbau-mit-dns-cnames-und-mehr-parallele-http-verbindungen-beschleunigen/</link>
		<comments>http://blog.root-of-all-evil.com/2010/02/serverseitig-den-webseitenaufbau-mit-dns-cnames-und-mehr-parallele-http-verbindungen-beschleunigen/#comments</comments>
		<pubDate>Sat, 06 Feb 2010 13:44:43 +0000</pubDate>
		<dc:creator>Philipp</dc:creator>
				<category><![CDATA[Codeschnipsel]]></category>
		<category><![CDATA[Guides]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekt]]></category>
		<category><![CDATA[beschleunigen]]></category>
		<category><![CDATA[bilder]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[cnames]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[media]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=380</guid>
		<description><![CDATA[Man stelle sich folgendes Szenario vor: Es existiert eine Webseite, die eine Vielzahl von Grafiken, die auf dem gleichem Server hinterlegt sind, einbindet. Diese Webseite wird erfahrungsgemäß eine überdurchschnittlich lange Ladezeit haben. Aber nicht nur aufgrund der zu übertragenen Datenmengen, sondern auch aufgrund der maximalen Anzahl von Verbindungen, die ein Browser auf ein und denselben Server erlaubt. Hier werde ich etwas über die Beschleunigung vom Aufbau von Webseiten schreiben. Dabei verwende ich gewisse DNS Einstellungen, so genannte CNAME-Records mit denen ich serverseitig mehrere parallele HTTP-Verbindungen erlauben kann und so das Laden der Webseite durch den Browser des Nutzers beschleunige.<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/02/serverseitig-den-webseitenaufbau-mit-dns-cnames-und-mehr-parallele-http-verbindungen-beschleunigen/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/02/serverseitig-den-webseitenaufbau-mit-dns-cnames-und-mehr-parallele-http-verbindungen-beschleunigen/" title="Serverseitig den Webseitenaufbau mit DNS CNAMES und mehr parallele HTTP-Verbindungen beschleunigen"></a><p>Man stelle sich folgendes Szenario vor: Es existiert eine Webseite, die eine Vielzahl von Grafiken, die auf dem gleichem Server hinterlegt sind, einbindet. Diese Webseite wird erfahrungsgemäß eine überdurchschnittlich lange Ladezeit haben. Aber nicht nur aufgrund der zu übertragenen Datenmengen, sondern auch aufgrund der maximalen Anzahl von Verbindungen, die ein Browser auf ein und denselben Server erlaubt. Hier werde ich etwas über die Beschleunigung vom Aufbau von Webseiten schreiben. Dabei verwende ich gewisse DNS Einstellungen, so genannte CNAME-Records mit denen ich serverseitig mehrere parallele HTTP-Verbindungen erlauben kann und so das Laden der Webseite durch den Browser des Nutzers beschleunige.<br />
<span id="more-380"></span></p>
<p>Standardmäßig sind moderne Browser mit maximalen Anzahl von <a href="http://stevesouders.com/ua/report.php?v=top&amp;nosparse=1" target="_blank">sechs Verbindungen (IE 6 und IE 7 maximal zwei Verbindungen)</a> zu ein und demselben Host begrenzt. Das führt dazu, dass das Laden von Dateien (Bilder, HTML-Seiten, JavaScripts oder Stylesheets) von einer Webseite in Blöcken unterteilt wird. Dabei würde es um einiges schneller gehen können, wenn ich die zu ladenden Dateien auf verschiedene Hostnamen verteile. So können für jeden Hostnamen mehr Verbindungen gleichzeitig ermöglicht werden.</p>
<p>Man betrachte zum Beispiel Google Maps. Die angezeigte Karte besteht aus einer vielzahl von so genannten Tiles. Tiles sind einfach Kacheln. Jede Kachel stellt einen Kartenausschnitt dar:</p>
<p><img class="aligncenter size-full wp-image-383" title="2009-08-13_1515-526x395" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/02/2009-08-13_1515-526x395.png" alt="" width="526" height="395" /></p>
<p>Damit die Karte schnellstmöglich trotz der Browserbegrenzung von sechs Verbindungen geladen werden kann, verteilt Google Maps die zu ladenden Kacheln auf verschiedene Hostnamen (Subdomains). Google verwendet vier Subdomains: mt0, mt1, mt2 und mt3.google.de:</p>
<p><img class="aligncenter size-full wp-image-384" title="2009-08-13_1520-526x326" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/02/2009-08-13_1520-526x326.png" alt="" width="526" height="326" /></p>
<p>Grundsätzlich ist es kein großes Problem verschiedene Subdomains anzulegen und die Dateien einer Webseite auf diese Subdomains zu verteilen. Allerdings besteht so recht schnell die Gefahr, dass man als Administrator den Überblick verliert, wo welche Dateien abgespeichert sind. Einfacher wäre es, zB. alle Mediendateien (zB. Bilder, Videos) unter einer Subdomain abzuspeichern. Um das Laden der Startseite erheblich zu beschleunigen, aber ohne zahlreiche Subdomains zu arbeiten kann man wie folgt vorgehen:</p>
<ol>
<li> Ich lege unter der Hauptdomain eine einzige subdomain namens  media.domain an. Hier speichere ich alle Bilder ab.</li>
<li>Ich lege so genannte CNAMES Einträge in meinen DNS Einstellungen an.  Ein CNAME ist &#8211; einfach erklärt &#8211; ein Domain-Alias. In meinem Fall  wähle ich zwei CNAME-Einträge namens &#8220;media0.domain.de&#8221; und  &#8220;media1.domain.de&#8221; an. Am einfachsten geht es über die Adminoberfläche  Plesk und sieht folgendermaße aus:<img class="aligncenter size-full wp-image-385" title="2009-08-13_1601" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/02/2009-08-13_1601.png" alt="" width="520" height="209" /></li>
<li>Diese beiden Einträge bewirken, dass media0.domain.de und  media1.domain.de auf die gleiche subdomain media.domain.de umleiten. Ich  habe jetzt also eine Subdomain, die auf drei unterschiedliche Weisen  erreicht werden kann. Der Browser des Nutzers interpretiert die drei  Domains als drei unterschiedliche Adressen, die aber auf den gleichen  Speicherort verweisen. So sind drei mal so viele Verbindungen zum eigentlich  gleichen Host möglich. Der Browser wird einfach ausgetrickst.</li>
<li>Bei der Einbindung der Bilder in die Webseite muss ich jetzt nur die  zwei verschiedenen &#8220;subdomains&#8221; media0 und media1 verteilen. Ich löse  das über einen Zufallsgenerator in meinem PHP Script, dass den HTML-Code  generiert. Dieser könnte zB. so aussehen:</li>
</ol>
<pre class="php" title="code">$media_domains = array('media0', 'media1');
foreach($bilder as $bild) {
  shuffle($media_domains);
  echo('&lt;img src="' . $media_domains[0] . '.domain.tld/img/'. $bild . '" /&gt;');
}</pre>
<p>Und fertig. Kommentare, Verbesserungsvorschlage? Dazu sind die Kommentare da.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/02/serverseitig-den-webseitenaufbau-mit-dns-cnames-und-mehr-parallele-http-verbindungen-beschleunigen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Das Zend Framework und die eBay trading API – Teil 3</title>
		<link>http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-%e2%80%93-teil-3/</link>
		<comments>http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-%e2%80%93-teil-3/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 20:40:45 +0000</pubDate>
		<dc:creator>Philipp</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Projekt]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[eBay]]></category>
		<category><![CDATA[Guide]]></category>
		<category><![CDATA[trading API]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Zend]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=205</guid>
		<description><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-%e2%80%93-teil-3/" title="Das Zend Framework und die eBay trading API – Teil 3"></a>In den beiden ersten Teilen dieses Guides habe ich einen Überblick über die Funktionsweise und den Aufbau des user Consent Flow von eBay Applikationen in Verbindung mit der eBay trading API geschaffen (zum ersten Teil dieses Guides) und den Aufbau &#8230;<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-%e2%80%93-teil-3/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-%e2%80%93-teil-3/" title="Das Zend Framework und die eBay trading API – Teil 3"></a><p>In den beiden ersten Teilen dieses Guides habe ich einen Überblick über die Funktionsweise und den Aufbau des user Consent Flow von eBay Applikationen in Verbindung mit der eBay trading API geschaffen (<a title="Zum zweiten Teil dieses Guides" href="../?p=131" target="_self">zum ersten Teil dieses Guides</a>) und den Aufbau unseres Ebay API Adapters und die Implementierung mit Hilfe des Zend Frameworks erläutert (<a title="Zum ersten Teil dieses Guides" href="../?p=161" target="_self">zum zweiten Teil dieses Guides</a>).</p>
<h3>Was werde ich hier in Teil 3 beschreiben?</h3>
<p>Dieser Teil beschäftigt sich mit der Implementierung des Auth bzw. des Consent Flow Prozesses der eBay trading API. Wir werden uns einen Überblick über die benötigten Klassen und Methoden schaffen und diese dann mit Hilfe des Zend Frameworks in unser bereits vorhandenes Projekt implementieren. Unsere Aufmerksamkeit widmen wir der <em>Ebay_Auth_ConsentFlow</em> Klasse und deren Methoden <em>GetSessionID()</em> und <em>fetchToken()</em>. Außerdem werden wir anhand dieser zwei API-Anfragen die API-Rückgabe untersuchen.<span id="more-205"></span></p>
<h3>Die Klasse Ebay_Auth_ConsentFlow<a href="http://blog.root-of-all-evil.com/wp-content/uploads/2010/01/ebayConsentFlow.jpg" rel="lightbox[205]"><img class="alignright size-thumbnail wp-image-139" title="eBayUserConsentFlow" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/01/ebayConsentFlow-150x150.jpg" alt="Der eBay User Consent Flow" width="150" height="150" /></a></h3>
<p>Wir benötigen die Klasse Ebay_Auth_ConsentFlow um das Ziel, einen validen AuthToken von der eBay trading API zu erhalten. Wie in <a title="Zu Teil 1 dieses Guides" href="http://blog.root-of-all-evil.com/?p=131" target="_blank">Teil 1 dieses Guides</a> beschrieben läuft der eBay User Consent Flow in drei Schritten ab: (1) Session ID anfragen, (2) User zum eBay Anmeldeformular weiterleiten und (3) AuthToken anfragen. Erst mit dem AuthToken können wir im Namen des Nutzers Aktionen mit der eBay trading API durchführen.</p>
<p>Auf Schritt 2 haben wir mit unserer Implementierung keinen Einfluss. Viel mehr müssen wir uns um die beiden API-Anfragen <em>GetSessionID</em> (1) und <em>ConsentFlow</em> (2) kümmern. Die <em>GetSessionID </em>Anfrage implementieren wir in gleichnamiger Methode unserer <em>Ebay_Auth_ConsentFlow</em> Klasse. Die <em>FetchToken </em>Anfrage werden wir analog in der Methode <em>fetchToken()</em> unterbringen. Hier noch einmal der Ablauf:</p>
<ol>
<li><strong>Ebay_Auth_ConsentFlow-&gt;getSessionID() aufrufen</strong><br />
und bei der trading API eine sessionID anfragen</li>
<li><strong>Ebay_Auth_ConsentFlow-&gt;fetchToken($sessionID)  aufrufen</strong><br />
und &#8211; vorausgesetzt der Benutzer hat sich erfolgreich auf eBay eingelogged &#8211; den zur sessionID gehörigen AuthToken erhalten</li>
</ol>
<p>Zur Erinnerung:</p>
<ul>
<li>Die <em>getSessionID </em>Methode wird direkt vom Controller aufgerufen und muss im Erfolgsfall die eBay Signin URL &#8211; an die der Benutzer weiter geleitet werden soll &#8211; zurück geben.</li>
<li>Die <em>callApi </em>Methode erwartet die folgenden Parameter:
<pre>callApi($verb, $request, $aditionalXml = true, $requestCredentials = true, $serverUrl = null)
</pre>
<p>Die GetSessionID Anfrage benötigt keine zusätzlichen XML Paramter und auch keine requestCredentials.</li>
<li>Die <em>callApi </em>Methode gibt ein zweielementiges Array zurück. Einen Statusflag (&#8216;<em>Success</em>&#8216;) und die Originalantwort (&#8216;<em>Response</em>&#8216;) der eBay API.</li>
</ul>
<h3>Die Implementierung der getSessionID Methode</h3>
<p>Werfen wir nun einen Blick auf die <em>getSessionID()</em> Methode:</p>
<pre class="php">class Ebay_Auth_ConsentFlow extends Ebay_Abstract
{
    public function getSessionID()
    {
        $callVerb = 'GetSessionID';
        $xmlBody  = '&lt;RuName&gt;' . $this-&gt;_apiAdapter-&gt;_ruName . '&lt;/RuName&gt;';
        $response = $this-&gt;_apiAdapter-&gt;callApi($callVerb, $xmlBody, false, false);

        if($response['Success'] == false) {
            $return = $response['Response']-&gt;shortMessage;
        } else {
            $return = array(
                'redirectUrl' =&gt; $this-&gt;_apiAdapter-&gt;_signinUrl .
                                 '&amp;RuName=' . $this-&gt;_apiAdapter-&gt;_ruName .
                                 '&amp;SessID=' . $response['Response']-&gt;SessionID,
                'sessionId'   =&gt; $response['Response']-&gt;SessionID
            );
            return $return;
        }
    }
}</pre>
<p>Der Vollständigkeit halber und um die Referenz auf $this-&gt;_apiAdapter in Zeile 6 erklären zu können hier noch die rudimentäre <em>Ebay_Abstract</em> Klasse. <em>Ebay_Auth_ConsentFlow</em> und alle anderen Ebay API Request Klassen erben den folgende Konstruktor:</p>
<pre class="php">class Ebay_Abstract
{
    protected $_apiAdapter;

    public function __construct()
    {
        if(!isset($this-&gt;_apiAdapter)) {
            $this-&gt;_apiAdapter = Ebay_Api_Adapter::getInstance();
        }
    }
}</pre>
<p>Wie zu sehen ist, ist der eigentliche Aufbau des API-Request denkbar einfach.  Wir erstellen den XML-String und setzen mit <em>$callVerb</em> (Zeile 5) den korrekten Anfragen-Namen. Alles weitere macht unsere <em>CallApi </em>Methode der Klasse <em>Ebay_Api_Adapter</em>. Die getSessionID Anfrage benötigt als einzigen Paramter den ruNamen der Applikation um das mit der SessionID verknüpfte eBay Login-Formular mit dem Logo und der Beschreibung unserer Applikation zu versehen.</p>
<p>Als Rückgabe an den Controller sollte uns die <em>getSessionID()</em> Methode eine Sandbox Signin-URL der Form <em>https://signin.sandbox.ebay.com/ws/eBayISAPI.dll?SignIn&amp;RuName=ruNameDerApplikation&amp;SessID=dieAngefragteSessionID</em> zurückgeben.</p>
<p>Wie der Controller und die Views aussehen erkläre ich später in Teil 4 dieses Guides. Nur so viel vorweg: Ich muss zwangsläufig die SessionID mit dem Benutzer Account verknüpfen, damit später sichergestellt werden kann, dass die korrekte SessionID des Benutzers der Methode <em>fetchToken() </em>übergeben wird. Der Benutzer verlässt unsere Seite zwangsläufig für den Login-Prozess für einen kurzen Augenblick. Wir möchten ihn auch nicht aus den Augen verlieren und seine SessionID wieder vergessen.</p>
<h3>Die Implementierung der fetchToken Methode</h3>
<p>Steigen wir direkt ein &#8211; viel Neues gibt es hier nicht:</p>
<pre class="php">public function fetchToken($sessionID)
{
    $callVerb  = 'FetchToken';
    $xmlBody   =
        '&lt;SessionID&gt;' . $sessionID . '&lt;/SessionID&gt;';
    $response  = $this-&gt;_apiAdapter-&gt;callApi($callVerb, $xmlBody, false, false);

    if($response['Success'] == false) {
        return $response['Response']-&gt;ShortMessage;
    } else {
        return array(
            'token' =&gt; $response['Response']-&gt;eBayAuthToken,
            'expiration' =&gt; date('Y-m-d H:i:s', strtotime($response['Response']-&gt;HardExpirationTime))
        );
    }
}</pre>
<p>Auch die fetchToken() Methode rufen wir direkt aus dem Controller auf. Wir übergeben die SessionID und erhalten im Idealfall ein zweielementiges Array mit Token und Gültigkeitsdauer des Tokens zurück.</p>
<h3>Die Rückgabe der eBay trading API</h3>
<p>Anhand dieser zwei API-Anfragen möchte ich hier die beiden XML API-Rückgaben vorstellen:</p>
<h4>GetSessionID-Anfrage:</h4>
<pre>RuName =
'ruNameUnsererApplikation'</pre>
<p>Der einzige hier zu übergebende Parameter ist der ruName unserer Applikation.</p>
<h4>GetSessionID-Antwort:</h4>
<pre>Timestamp =
'2010-01-26T20:35:46.118Z'
Ack =
'Success'
Version =
637
Build =
'E637_INTL_BUNDLED_10223050_R1'
SessionID =
'b0**...*f74'</pre>
<p>Als Antwort erhalten wir die SessionID.</p>
<h4>FetchToken-Anfrage:</h4>
<pre>SessionID =
'b0**...*f74'</pre>
<p>Auch hier muss nur ein Paramter &#8211; die SessionID &#8211; übergeben werden.</p>
<h4>FetchToken-Antwort:</h4>
<pre>Timestamp =
'2010-01-26T20:31:58.283Z'
Ack =
'Success'
Version =
637
Build =
'E637_INTL_BUNDLED_10223050_R1'
eBayAuthToken =
'AuthToken'
HardExpirationTime =
'2011-07-20T20:27:32.000Z'
</pre>
<p>Die Antwort enthält den AuthToken und seine Gültigkeitsdauer.</p>
<p>Unsere Api_Adapter und User Consent Flow Implementierung ist damit fast fertig. Wie Controller und Views &#8211; und damit unser Frontend &#8211; implementiert werden, das soll Thema von <a title="Zu Teil Vier springen" href="http://blog.root-of-all-evil.com/?p=370" target="_self">Teil 4 dieses Guides</a> sein.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-%e2%80%93-teil-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Das Zend Framework und die eBay trading API &#8211; Teil 2</title>
		<link>http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-teil-2/</link>
		<comments>http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-teil-2/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 22:09:47 +0000</pubDate>
		<dc:creator>Philipp</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Projekt]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[eBay]]></category>
		<category><![CDATA[Guide]]></category>
		<category><![CDATA[trading API]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Zend]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=161</guid>
		<description><![CDATA[Dieser Teil widmet sich dem Aufbau und Implementierung der Ebay_Api_Adapter Klasse, die wir verwenden werden um Anfragen an die eBay trading API zu senden. Wir benötigen Methoden zur Generierung und Auslieferung der Anfragen und eine geeignete Fehlerbehandlung. Exemplarisch und anhand von Code-Beispielen soll das hier in Teil 2 gezeigt werden.<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-teil-2/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-teil-2/" title="Das Zend Framework und die eBay trading API - Teil 2"></a><p><a title="Zum ersten Teil" href="http://blog.root-of-all-evil.com/?p=131" target="_blank">Im ersten Teil dieses Guides</a> hatten wir uns einen Überblick über den Consent Flow und eBay Authentifizierung unserer Nutzer geschaffen und so die Voraussetzung zur praktischen Umsetzung mit dem Zend Framework geschaffen.</p>
<h3>Was werde ich hier in Teil 2 beschreiben?</h3>
<p>Dieser Teil widmet sich dem Aufbau und Implementierung der Ebay_Api_Adapter Klasse, die wir verwenden werden um Anfragen an die eBay trading API zu senden. Wir benötigen Methoden zur Generierung und Auslieferung der Anfragen und eine geeignete Fehlerbehandlung. Exemplarisch und anhand von Code-Beispielen soll das hier in Teil 2 gezeigt werden.</p>
<p><span id="more-161"></span></p>
<p>Unsere Webapplikation muss nicht nur Anfragen an die eBay API senden, sondern auch den Überblick über SessionIDs und Tokens seiner Benutzer behalten. Wir sind also gezwungen diese &#8211; in unserem Fall in einer Datenbank &#8211; zwischen zu speichern:</p>
<p style="text-align: center;"><a href="http://blog.root-of-all-evil.com/wp-content/uploads/2010/01/ebayConsentFlow_app1.jpg" rel="lightbox[161]"><img class="aligncenter" title="ebayCohttp://blog.root-of-all-evil.com/wp-admin/post.php?action=edit&amp;post=161nsentFlow_app" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/01/ebayConsentFlow_app1.jpg" alt="" width="400" height="341" /></a></p>
<p>Das bedeutet sogleich, dass unsere Applikation auch ein User-System haben muss, so dass die zurückgegebenen SessionIDs und Tokens mit den korrekten Benutzern verknüpft werden können. Ich möchte dies hier nicht noch ausführlich herleiten, sondern setze dieses Feature in der Basis-Applikation voraus. Ich nutze dafür <a title="Eine Einführung in Zend_Acl" href="http://framework.zend.com/manual/de/zend.acl.introduction.html" target="_blank">Zend_Acl</a> und ein klassisches User-System mit Register-, Login- und Logout Funktionen. Um voraus zu planen und es eventuell später mehren Nutzern gleichzeitig zu ermöglichen mit einem eBay Account zu arbeiten wird es in meiner <em>Users </em>Tabelle eine <em>account_id</em> und eine n:1 Verknüpfung mit der <em>id </em>des eBay Accounts in der Tabelle <em>Accounts geben</em>. Der Controller <em>User </em>und die dazugehörigen Funktionen existieren also schon.</p>
<h3>Die benötigten Controller und Klassen</h3>
<p>Für unsere eBay Applikation brauchen wir einen neuen Controller (Ebayauth) und eine neue Library (Ebay) in der wir unsere eBay spezifischen Klassen unterbringen. Wir benötigen:</p>
<ul>
<li>Einen Controller <em>Ebayauth</em></li>
<li>Fünf Actions (<em>index</em>, <em>step1</em>, <em>step2</em>, <em>success </em>und <em>denied</em>) und fünf Views für den Controller <em>Ebayauth</em>:<em> index.phtml</em>, <em>step1.ajax.phtml</em>, <em>step2.ajax.phtml</em>, <em>success.phtml</em> und <em>denied.phtml</em></li>
<li>Eine neue Library mit Namespace <em>Ebay_ </em>(nicht vergessen einen Autoloader im bootstrap anzupassen)</li>
<li>Zwei <em>Ebay_</em> Klassen: <em>Ebay_Api_Adapter</em> und <em>Ebay_Auth_ConsentFlow</em></li>
<li>Eine <em>keys.xml</em> in der Library Ebay</li>
</ul>
<h3>Die Klasse Ebay_Api_Adapter</h3>
<p>Die keys.xml erlaubt es uns unsere API-Keys in einer schönen, ausgelagerten XML zu verwalten anstatt sie hardcoded in der Klasse zu lagern. Werfen wir zunächst einen Blick auf den Constructor, die setOptions Methode und die keys.xml:</p>
<pre name="code" class="php">class Ebay_Api_Adapter
{
    public function __construct($configfile = 'keys.xml')
    {
        $configfile = '../library/Ebay/' . $configfile;
        $configXml = new Zend_Config_Xml($configfile);
        $this-&gt;setOptions($configXml-&gt;keys-&gt;toArray());
        $this-&gt;setOptions($configXml-&gt;options-&gt;toArray());
    }

    // statische Instanz-Rückgabe
    public static function getInstance()
    {
        if (self::$_instance === null) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    private function setOptions($options = array())
    {
        if(is_array($options)) {
            foreach($options as $key =&gt; $value) {
                $key = '_' . $key;
                $this-&gt;$key = $value;
            }
        }
    }
}</pre>
<pre name="code" class="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;ebay&gt;
&lt;keys&gt;
    &lt;devId&gt;hier-eintragen&lt;/devId&gt;
    &lt;appId&gt;hier-eintragen&lt;/appId&gt;
    &lt;certId&gt;hier-eintragen&lt;/certId&gt;
    &lt;ruName&gt;hier-eintragen&lt;/ruName&gt;
&lt;/keys&gt;
&lt;options&gt;
    &lt;siteId&gt;77&lt;/siteId&gt;
    &lt;warningLevel&gt;High&lt;/warningLevel&gt;
    &lt;compatLevel&gt;647&lt;/compatLevel&gt;
    &lt;errorLanguage&gt;77&lt;/errorLanguage&gt;
    &lt;serverUrl&gt;&lt;![CDATA[https://api.sandbox.ebay.com/ws/api.dll]]&gt;&lt;/serverUrl&gt;
    &lt;signinUrl&gt;&lt;![CDATA[https://signin.sandbox.ebay.com/ws/eBayISAPI.dll?SignIn]]&gt;&lt;/signinUrl&gt;
&lt;/options&gt;&lt;/ebay&gt;
</pre>
<p>Zu den Optionen in der keys.xml möchte ich noch ein paar Worte loswerden:</p>
<ul>
<li>siteID 77 entspricht eBay.de und errorLanguage 77 entspricht Deutsch</li>
<li>warningLevel ist während wir mit der Sandbox arbeiten auf High gesetzt.</li>
<li>compatLevel 647 ist die aktuelle eBay trading API Version mit der wir arbeiten möchten.</li>
<li>serverURL ist unser Ansprechpartner für sämtliche API-Requests.</li>
<li>signinURL verwenden wir für die Weiterleitung des Benutzers zum Consent Flow.</li>
</ul>
<p>Für den HTTP-Request (POST) an die eBay trading API nutzen wir Zend_Http_Client. Die API möchte von uns eine Reihe HTTP-Header gesetzt sehen, bevor sie antworten wird. Dazu folgende Funktion:</p>
<pre name="code" class="php">private function setHeaders()
{
    $this-&gt;_headers = array (
        // Die eBay trading API Version, die wir unterstützen
        'X-EBAY-API-COMPATIBILITY-LEVEL: ' . $this-&gt;_compatLevel,

        // Unsere Keys und Zertifikate
        'X-EBAY-API-DEV-NAME: '    . $this-&gt;_devId,
        'X-EBAY-API-APP-NAME: '    . $this-&gt;_appId,
        'X-EBAY-API-CERT-NAME: '   . $this-&gt;_certId,

        // Der Name jeder eBay API Anfrage muss im Header noch einmal benannt werden
        'X-EBAY-API-CALL-NAME: '   . $this-&gt;_callVerb,
        'X-EBAY-API-SITEID: '      . $this-&gt;_siteId,

        // Wichtig: Den Content Type der Daten, die wir senden
        'Content-Type: text/xml; charset=utf-8'
    );
    $this-&gt;_request = new Zend_Http_Client();
    $this-&gt;_request-&gt;setUri($this-&gt;_serverUrl);
    $this-&gt;_request-&gt;setHeaders($this-&gt;_headers);
}</pre>
<p>Sind die Header gesetzt, so können wir mit dem Zend_Http_Client Object ($this-&gt;_request) eine Anfrage senden. Der eigentliche Inhalt der Anfrage wird mittels POST mitgesendet. Das eigentliche Herzstück unseres API Adapters ist die Methode callApi, die wie folgt Abläuft:</p>
<ol>
<li><strong>Die Header setzen</strong><br />
Wir übergeben der callApi Methode die Bezeichnung des Requests als Parameter und rufen damit die setHeaders() Methode auf. Diese baut die Header zusammen und erstellt ein neues Zend_Http_Client Objekt (siehe oben).</li>
<li><strong>Den Request Body zusammensetzen</strong><br />
Abhängig vom Typ der API Anfrage müssen wir den String des Request-Bodys (xml) zusammensetzen. Eine getSessionID verlangt andere (und weniger) Optionen als eine reguläre Anfrage.</li>
<li><strong>Den Http_Client mit dem Request Body versehen und absenden</strong><br />
Den zuvor in der setHeaders() Methode erstellten Http_Client übergeben wir den Request Body und senden den Request mittels POST an den API-Server. Die Rückgabe speichern wir in einer Variable.</li>
<li><strong>Die Rückgabe auswerten und Fehler abfangen</strong><br />
Die Rückgabe (xml) hat je nach API Anfrage eine bestimmte Form, die wir auswerten müssen. Hier muss auch unsere Fehlerbehandlung implementiert werden.</li>
</ol>
<p>Hier die Implementierung der callApi Methode der Klasse Ebay_Api_Adapter:</p>
<pre name="code" class="php">public function callApi($verb, $request, $aditionalXml = true, $requestCredentials = true, $serverUrl = null)
{

    if($serverUrl == null) {
        $serverUrl = $this-&gt;_serverUrl;
    }

    $this-&gt;_callVerb = $verb;

    $this-&gt;setHeaders();

    $requestBody =
        '&lt;?xml version="1.0" encoding="utf-8"?&gt;' .
        '&lt;' . $verb . ' xmlns="urn:ebay:apis:eBLBaseComponents"&gt;';

    // request Credentials werden nur bei regulären, nicht bei
    // getSessionID oder fetchToken Anfragen benötigt
    if($requestCredentials) {
        $requestBody .=
            '&lt;RequesterCredentials&gt;' .
            '&lt;eBayAuthToken&gt;&lt;![CDATA[' . $this-&gt;getToken() . ']]&gt;&lt;/eBayAuthToken&gt;' .
            '&lt;/RequesterCredentials&gt;';
    }

    // Auch diese Optionen benötigen wir nur für reguläre Anfragen
    if($aditionalXml) {
        $requestBody .=
            '&lt;ErrorLanguage&gt;' . $this-&gt;_errorLanguage . '&lt;/ErrorLanguage&gt;' .
            '&lt;WarningLevel&gt;'  . $this-&gt;_warningLevel  . '&lt;/WarningLevel&gt;';
    }

    $requestBody .=
        $request . '&lt;/' . $verb . '&gt;';

    $this-&gt;_request-&gt;setUri($serverUrl);
    $this-&gt;_request-&gt;setRawData($requestBody);
    $response = $this-&gt;_request-&gt;request('POST');

    $this-&gt;responseHeader   = $response-&gt;getHeaders();
    $this-&gt;responseBody     = $response-&gt;getBody();

    // die Rückgabe wandeln wir in ein (hoffentlich gültiges)
    // XML Element um
    $xml = @simplexml_load_string($this-&gt;responseBody);

    // Existiert in der Rückgabe kein ACK-Feld (zB. weil der ebay
    // Server nicht geantwortet hat) oder ist es nicht 'Success',
    // so ist etwas schief gelaufen
    if(!isset($xml-&gt;Ack) || $xml-&gt;Ack != 'Success') {
        $errors = 'Keine Antwort von eBay';
        if(isset($xml-&gt;Errors))
            $errors = $xml-&gt;Errors;
        return array('Success' =&gt; false, 'Response' =&gt; $errors);
    }

    return array('Success' =&gt; true, 'Response' =&gt; $xml);
}</pre>
<p>Die in Zeile 21 verwendete gettoken() Methode (siehe unten) gibt mir den mit dem User Account verknüpften Token zurück (Siehe Schaubild oben), ist aber optional und setzt ein User-Model voraus. Alternativ oder zu Testzwecken lässt sich der Token auch in der keys.xml hinterlegen und der Funktionsaufruf in Zeile 21 durch ein $this-&gt;_token() ersetzen.</p>
<pre name="code" class="php">public function getToken()
{
    $accountId        = Zend_Auth::getInstance()-&gt;getIdentity()-&gt;account_id;
    $modelAccount    = new Model_Account();
    return $modelAccount-&gt;getEbayToken($accountId);
}</pre>
<p>Mit dieser Implementierung können wir nun beliebige eBay trading API Anfragen versenden. <a title="Zum dritten Teil" href="http://blog.root-of-all-evil.com/?p=205" target="_self">Im dritten Teil dieses Guides beschreibe ich die Implementierung der Klasse Ebay_Auth_ConsentFlow</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-teil-2/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Das Zend Framework und die eBay trading API &#8211; Teil 1</title>
		<link>http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-teil-1/</link>
		<comments>http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-teil-1/#comments</comments>
		<pubDate>Sat, 23 Jan 2010 13:42:49 +0000</pubDate>
		<dc:creator>Philipp</dc:creator>
				<category><![CDATA[Guides]]></category>
		<category><![CDATA[Projekt]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[eBay]]></category>
		<category><![CDATA[Guide]]></category>
		<category><![CDATA[trading API]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[Zend]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=131</guid>
		<description><![CDATA[Webapplikationen, die die eBay trading API verwenden und damit für einen eBay Nutzer in seinem Namen Aktionen auf der eBay-Webseite durchführen, müssen einen Authorisationsprozess durchlaufen. Nutzer der Webapplikation müssen sich als eBay Nutzer identifizieren und die Applikation authorisieren Aktionen in ihrem Namen durchzufüren. Diesen Prozess möchte ich hier exemplarisch in einer Webapplikation mit Hilfe des Zend Framework abbilden und so den ersten Teil einer jeden eBay-Webapplikation beispielhaft beschreiben.<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-teil-1/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-teil-1/" title="Das Zend Framework und die eBay trading API - Teil 1"></a><p>Erst mit guter Dokumentation macht es Sinn.</p>
<p>Und gut dokumentiert, das ist sowohl das <a title="Die umfangreiche Zend Framework Dokumentation" href="http://framework.zend.com/docs/" target="_blank">Zend Framework</a>, wie auch die <a title="Die eBay Trading API Dokumentation" href="http://developer.ebay.com/DevZone/XML/docs/WebHelp/wwhelp/wwhimpl/js/html/wwhelp.htm" target="_blank">eBay trading API</a>. Sinn macht es also beide zu kombinieren um schnell große eBay-Webapplikationen zu schaffen. Das Zend Framework erlaubt ein rapid PHP development und die eBay trading API ermöglicht es so ziemlich alles, was der Nutzer auf der eBay-Webseite sowieso schon tun kann in die eigenen Webapplikation zu klonen. Natürlich gibt es auch hier best practices &#8211; wie ich das ganze angegangen bin, dass möchte ich hier im folgenden beschreiben.</p>
<h3>Was werde ich hier in Teil 1 beschreiben?</h3>
<p>Webapplikationen, die die eBay trading API verwenden und damit für einen eBay Nutzer in seinem Namen Aktionen auf der eBay-Webseite durchführen, müssen einen Authorisationsprozess durchlaufen. Nutzer der Webapplikation müssen sich als eBay Nutzer identifizieren und die Applikation authorisieren Aktionen in ihrem Namen durchzufüren. Diesen Prozess möchte ich hier exemplarisch in einer Webapplikation mit Hilfe des Zend Framework abbilden und so den ersten Teil einer jeden eBay-Webapplikation beispielhaft beschreiben.<span id="more-131"></span></p>
<h3>Was benötigen wir um mit der eBay trading API zu arbeiten?</h3>
<ol>
<li><strong>Einen eBay Developers Program Account</strong> (<a title="Sofort beim eBay Developers Program anmelden" href="https://developer.ebay.com/join/Default.aspx" target="_blank">https://developer.ebay.com</a>)<br />
Das eBay Developers Program bietet Zugriff auf die eBay APIs und eine umfangreiche Dokumentation und Support. Es existieren Foren, Referenzen und zahlreiche Code-Beispiele. Ein solcher Account ist zwingen notwendig um die eBay trading API überhaupt ansprechen und nutzen zu können.</li>
<li><strong>Mindestens einen eBay Sandbox Account</strong> (<a title="Sofort bei der eBay Sandbox einen Account anlegen" href="https://scgi.sandbox.ebay.com/ws/eBayISAPI.dll?RegisterEnterInfo&amp;siteid=0&amp;UsingSSL=1&amp;co_partnerId=2" target="_blank">https://sandbox.ebay.com</a>)<br />
Es ist notwendig seine Applikationen in der eBay Sandbox zu entwickeln. Die Sandbox ist eine der original eBay Umgebung ähnelnde Spielwiese in der man zunächst einmal nichts kaputt machen und nach Lust und Laune seine Programme entwickeln und testen kann. Mindestens einen Account brauchen wir hier um in dessen Namen die trading API nutzen zu können. Empfehlen kann ich auch einen zweiten Account um beispielsweise und zu testzwecken Produkte des ersten Accounts zu ersteigern.</li>
<li><strong>Ein Set Sandbox API Keys</strong> (werden über den developers Account angelegt)<br />
Dazu zählen:</p>
<ul>
<li>Die <em>devID</em> &#8211; sie identifiziert uns als Entwickler beim Verwenden der eBay trading API</li>
<li>Die <em>AppID</em> &#8211; sie identifiziert unsere Applikation beim Verwenden der eBay trading API</li>
<li>Eine <em>CertID</em> &#8211; ein Zertifikat, dass wir beim Ansprechen der eBay trading API benötigen</li>
<li>Ein<em> RuName </em>- mit dem wir das eBay Anmeldeformular beim Authorisierungsprozess gestalten können<br />
Der RuName wird beim Konfigurieren des<em> Consent Flow</em> (der Authorisierungsprozess) im developers Account generiert. Uns wird beispielsweise die Möglichkeit gegeben das Anmeldeformular mit einem Logo unserer Applikation zu versehen.</li>
</ul>
</li>
</ol>
<h3>Was benötigen wir um mit dem Zend Framework zu arbeiten?</h3>
<ol>
<li>Eine aktuelle Version des <a title="Der Zend Server in der kostenlose Community Edition" href="http://www.zend.com/de/community/zend-server-ce" target="_blank">Zend Servers (Community Edition)</a> und das dazugehörige <a title="Das Zend Framework herunterladen" href="http://framework.zend.com/" target="_blank">Zend Framework</a>. Ich verwende das Zend Framework in der Version 1.9.5 und den Zend Server mit der PHP Version 5.2.11.</li>
<li>Ich empfehle das Entwicklertool <a title="Das Zend Studio Entwicklertool" href="http://www.zend.com/de/products/studio/downloads" target="_blank">Zend Studio</a> und Erfahrung, was das Arbeiten mit PHP, XML, dem Zend Framework und die Konfiguration eines Webservers angeht. Sollte das Zend Framework bis jetzt völlig unbekannt sein, dann möchte ich zunächst auf die zahlreichen Bücher zum Thema und die vielen Tutorials im Internet verweisen. Ich werde hier keine Einführung in das Framework geben.</li>
</ol>
<h3>Was benötigen wir sonst noch für unsere eBay Webapplikation?</h3>
<ol>
<li>Einen MySQL Server oder eine andere Datenbank. Ich verwende hier eine MySQL Datenbank in Verbindung mit der Zend_Db_Table Class, die eine abstraktion Layer besitzt und damit auch für andere Datenbanktypen verwendet werden kann.</li>
<li>Ein JavaScript Framework für unsere Ajax-Calls. Natürlich ist kein Framework notwendig, aber es macht die Frontendentwicklung und vor allem unsere Ajax Funktionen wunderbar einfach zu implementieren. Ich verwende <a title="Mootools JavaScript Framework" href="http://mootools.net/" target="_blank">mootools</a>, kann aber auch <a title="Das jQuery Javascript Framework" href="http://jquery.com" target="_blank">jQuery</a> empfehlen. Wichtig bei der Auswahl des Frameworks ist es, dass die Ajax-Requests ein XmlHttpRequest-Header mitsenden.</li>
<li>Eine Basis-Applikation mit einem eingerichtetem Layout, die es dem Benutzer erlaubt sich in unserer Applikation einzuloggen.</li>
</ol>
<h3>Der eBay User Consent Flow</h3>
<p>Wenn all das geklärt wurde, dann werden wir hier in Teil1 zunächst mit der Theorie beginnen: Wie sieht der User Consent Flow bei eBay aus? Dazu folgende Grafik:<a href="http://blog.root-of-all-evil.com/wp-content/uploads/2010/01/ebayConsentFlow.jpg" rel="lightbox[131]"><img class="aligncenter size-full wp-image-139" title="eBayUserConsentFlow" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/01/ebayConsentFlow.jpg" alt="Der eBay User Consent Flow" width="384" height="377" /></a></p>
<ol>
<li><strong>Schritt</strong><br />
Unsere Applikation wird die eBay API nach einer SessionID beten. Dazu schicken wir den ruName unserer Applikation mit, damit eBay das konfigurierte Anmeldeformular (inklusive unseres tollen Applikationslogos und der Redirect-URLs) generieren und mit der SessionID verknüpfen kann. Als Antwort erhalten wir also eine SessionID, die wir dann verwenden um die Parameter der URL des Anmeldeformulars zu generieren und den Benutzer dann im zweiten Schritt &#8230;<span style="color: #888888;"> </span></li>
<li><strong>Schritt</strong><br />
&#8230; an diese URL weiterzuleiten. Dort gibt er sein eBay Passwort und Nutzernamen ein und bestätigt, dass er unserer Webapplikation erlaubt in seinem Namen auf eBay Aktionen durchzuführen. Hat er bestätigt, leitet eBay den Benutzer wieder zurück zu unserer Applikation, die daraufhin im dritten Schritt &#8230;</li>
<li><strong>Schritt</strong><br />
&#8230; eine fetchToken Anfrage an die eBay API senden kann. Mit der fetchToken Anfrage geben wir gleich die zuvor erhaltene SessionID mit. Wurde diese SessionID verwendet und hat sich der Nutzer mit dieser SessionID im Zuge des Schritt 2 auch korrekt angemeldet, so erhalten wir einen ca. 900 Zeichen langes Token zurück gibt. Dieses Token muss unsere Applikation bei jeder API-Anfrage mitsenden und sich so autorisieren.</li>
</ol>
<p>Wie die Theorie mit dem Zend Framework möglichst schnell und unkompliziert in die Praxis umgesetzt werden kann werde ich<a title="Zum zweiten Teil dieses Guides" href="http://blog.root-of-all-evil.com/?p=161" target="_self"> im zweiten Teil dieses Guides</a> beschreiben. Ich gehe konkret auf die benötigten Klassen ein und werde zahlreiche Code-Beispiele geben.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/01/das-zend-framework-und-die-ebay-trading-api-teil-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

