<?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>Lorem Ipsum Ges.m.b.H. &#187; Daniel Leeb</title>
	<atom:link href="http://www.loremipsum.at/author/daniel-leeb/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.loremipsum.at</link>
	<description>Der Onlineauftritt der Lorem Ipsum Medienges.m.b.H.</description>
	<lastBuildDate>Wed, 11 Jan 2012 08:14:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>Softphone GreenJ mit neuer Heimat auf GitHub</title>
		<link>http://www.loremipsum.at/blog/news/softphone-greenj-mit-neuer-heimat-auf-github/</link>
		<comments>http://www.loremipsum.at/blog/news/softphone-greenj-mit-neuer-heimat-auf-github/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 08:14:18 +0000</pubDate>
		<dc:creator>Daniel Leeb</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[GitHub]]></category>
		<category><![CDATA[GreenJ]]></category>
		<category><![CDATA[Open-Source]]></category>
		<category><![CDATA[Softphone]]></category>
		<category><![CDATA[VoIP]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=3630</guid>
		<description><![CDATA[Letzten Monat haben wir unser Open-Source Softphone GreenJ bereits auf unserer Seite zum Download freigegeben und ihm auch eine eigene Domain &#8211; greenj.org &#8211; spendiert. GreenJ ist eine plattformunabhängige Voice-over-IP Applikation, welche es einem Webentwickler ermöglicht, mittels einer einfachen Schnittstelle, &#8230; <a href="http://www.loremipsum.at/blog/news/softphone-greenj-mit-neuer-heimat-auf-github/">weiterlesen <span class="meta-nav">&#187;</span></a><div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/produkte/greenj/" rel="bookmark">GreenJ</a></li>
		<li><a href="http://www.loremipsum.at/produkte/greenj/introduction/" rel="bookmark">Einführung / Introduction</a></li>
		<li><a href="http://www.loremipsum.at/blog/news/upgrade-auf-27-neues-design-online/" rel="bookmark">Upgrade auf 2.7 + neues Design online</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Letzten Monat haben wir unser <strong>Open-Source Softphone GreenJ</strong> bereits auf unserer Seite zum <a href="http://www.loremipsum.at/produkte/greenj/introduction/#downloadde">Download</a> freigegeben und ihm auch eine eigene Domain &#8211; <a href="http://www.greenj.org">greenj.org</a> &#8211; spendiert. GreenJ ist eine plattformunabhängige Voice-over-IP Applikation, welche es einem Webentwickler ermöglicht, mittels einer <a href="http://www.loremipsum.at/produkte/greenj/library/">einfachen Schnittstelle</a>, eine Webseite als Telefonsystem zu erstellen. Unser Programm bietet die nötigen Telefonfunktionen und kann eine beliebige Oberfläche durch den integrierten Browser darstellen. Mehr Informationen sowie Downloads des Programms, Quellcodes und der Dokumentation können in der <a href="http://www.loremipsum.at/produkte/greenj/introduction/">Einführung zu GreenJ</a> gefunden werden.</p>
<p><a href="http://www.loremipsum.at/wp-content/uploads/2011/09/screen_licc.png"><img src="http://www.loremipsum.at/wp-content/uploads/2011/09/screen_licc-300x173.png" alt="A callcenter application in GreenJ" title="Screenshot GreenJ Callcenter" width="300" height="173" class="alignnone size-medium wp-image-3538" /></a></p>
<h3>GreenJ auf GitHub</h3>
<p>Um die Verfügbarkeit noch zu verbessern, befindet sich GreenJ ab sofort als <a href="https://github.com/danleeb/GreenJ">Repository auf GitHub.com</a> und kann auch von dort heruntergeladen werden.</p>
<p>Etwa indem man das GreenJ Repository klont:</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">$ git clone git://github.com/danleeb/GreenJ.git</div></td></tr></tbody></table></div>
<p>In der mitgelieferten Readme, siehe auf GitHub unterhalb der Dateiliste, findet man auch eine kurze Schritt für Schritt Anleitung, um GreenJ unter Ubuntu 11.10 (32-bit Linux) zu kompilieren. Natürlich lässt sich GreenJ auch unter einer anderen Linux Distribution oder unter Windows kompilieren und verwenden. Bei Interesse einfach unsere <a href="http://www.loremipsum.at/produkte/greenj/">GreenJ Produktseite</a> besuchen.</p>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/produkte/greenj/" rel="bookmark">GreenJ</a></li>
		<li><a href="http://www.loremipsum.at/produkte/greenj/introduction/" rel="bookmark">Einführung / Introduction</a></li>
		<li><a href="http://www.loremipsum.at/blog/news/upgrade-auf-27-neues-design-online/" rel="bookmark">Upgrade auf 2.7 + neues Design online</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/news/softphone-greenj-mit-neuer-heimat-auf-github/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Doctrine 2 SQL Profiler in Debugleiste</title>
		<link>http://www.loremipsum.at/blog/code/doctrine-2-sql-profiler-in-debugleiste/</link>
		<comments>http://www.loremipsum.at/blog/code/doctrine-2-sql-profiler-in-debugleiste/#comments</comments>
		<pubDate>Wed, 21 Dec 2011 15:12:17 +0000</pubDate>
		<dc:creator>Daniel Leeb</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Profiler]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Zend]]></category>
		<category><![CDATA[ZF]]></category>
		<category><![CDATA[ZFDebug]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=3608</guid>
		<description><![CDATA[Auch wenn es sich um ein sehr spezielles Thema handelt, möchte ich hier kurz zusammenfassen, wie man einen Doctrine 2 SQL Logger/Profiler in einer Zend Framework Umgebung umsetzen kann. Da die Kombination aus ZF und Doctrine 2 durchaus beliebt zu &#8230; <a href="http://www.loremipsum.at/blog/code/doctrine-2-sql-profiler-in-debugleiste/">weiterlesen <span class="meta-nav">&#187;</span></a><div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/code/integration-von-doctrine-in-eine-modul-basierte-zend-anwendung/" rel="bookmark">Integration von Doctrine in eine modulbasierte Zend Anwendung</a></li>
		<li><a href="http://www.loremipsum.at/blog/sem/neues-wordpress-plugin-affiliando-vergleichsrechner-1-0/" rel="bookmark">Neues WordPress Plugin: Affiliando Vergleichsrechner 1.0</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/rundungsfehler-in-magento-beheben/" rel="bookmark">Rundungsfehler in Magento beheben</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Auch wenn es sich um ein sehr spezielles Thema handelt, möchte ich hier kurz zusammenfassen, wie man einen <strong>Doctrine 2 SQL Logger/Profiler</strong> in einer <strong>Zend Framework</strong> Umgebung umsetzen kann. Da die Kombination aus <a href="http://framework.zend.com/" title="Zend Framework">ZF</a> und <a href="http://www.doctrine-project.org/" title="Doctrine Project">Doctrine 2</a> durchaus beliebt zu sein scheint, zumindest wenn man von Blogeinträgen und Tutorials im Internet ausgeht, könnte dieser Beitrag für manch einen hilfreich sein.<span id="more-3608"></span> Vorweg möchte ich auch noch auf eine praktische Lösung hinweisen, um Doctrine 2.x mit dem Zend Framework 1.x zu verbinden: Und zwar <strong>Bisna von Guilherme Blanco</strong>, zu finden in seinem <a href="https://github.com/guilhermeblanco/ZendFramework1-Doctrine2" title="Bisna GitHub Repository">GitHub Repository</a>. Danach lässt sich Doctrine mittels Zend_Config (ini, xml, etc.) konfigurieren.</p>
<h3>SQL Queries in der ZFDebug-Leiste</h3>
<p>Nach der Integration von Doctrine in unsere neue Webapplikation basierend auf dem Zend Framework fehlte uns noch eine einfache Möglichkeit SQL Queries anzuzeigen. Da wir bereits <strong>ZFDebug</strong> verwenden, lag ein zusätzliches Plugin für die Ausgabe in der Debugleiste für uns nahe. <a href="http://code.google.com/p/zfdebug/" title="ZFDebug auf Google-Code">ZFDebug</a> wurde leider seit Mitte 2009 nicht mehr aktualisiert, funktioniert jedoch immer noch sehr gut, liefert hilfreiche Informationen rund um die Webapplikation und lässt sich sehr einfach erweitern. Daher werde ich hier zeigen, wie man den Doctrine 2 Profiler in einem ZFDebug Plugin verwenden kann.</p>
<h3>Profiler</h3>
<p>Doctrine bietet mit <strong>Doctrine\DBAL\Logging\SQLLogger</strong> bereits ein Interface um einen Logger mit einer Datenbank-Verbindung zu verknüpfen. Wir implementieren dieses Interface mit den beiden Methoden <strong>startQuery()</strong> und <strong>stopQuery()</strong> und speichern einfach alle Queries in ein Array das wir später in der Debugleiste ausgeben werden.</p>
<p><strong>DoctrineExtensions/Profiler/ZFDebugProfiler.php:</strong></p>
<div class="codecolorer-container php geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">namespace</span> DoctrineExtensions\Profiler<span style="color: #339933;">;</span><br />
<br />
<span style="color: #000000; font-weight: bold;">class</span> ZFDebugProfiler implements \Doctrine\DBAL\Logging\SQLLogger<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$totalTime</span> <span style="color: #339933;">=</span> <span style="color:#800080;">0.0</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000088;">$queries</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><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$_curQuery</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> startQuery<span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #000088;">$params</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span> <span style="color: #000088;">$types</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_curQuery <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> \stdClass<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_curQuery<span style="color: #339933;">-&gt;</span><span style="color: #004000;">sql</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$sql</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_curQuery<span style="color: #339933;">-&gt;</span><span style="color: #004000;">params</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$params</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_curQuery<span style="color: #339933;">-&gt;</span><span style="color: #990000;">time</span> <span style="color: #339933;">=</span> \<span style="color: #990000;">microtime</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> stopQuery<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$executionTime</span> <span style="color: #339933;">=</span> \<span style="color: #990000;">microtime</span><span style="color: #009900;">&#40;</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;">$this</span><span style="color: #339933;">-&gt;</span>_curQuery<span style="color: #339933;">-&gt;</span><span style="color: #990000;">time</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">totalTime</span> <span style="color: #339933;">+=</span> <span style="color: #000088;">$executionTime</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">queries</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'time'</span> &nbsp; <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$executionTime</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'sql'</span> &nbsp; &nbsp;<span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_curQuery<span style="color: #339933;">-&gt;</span><span style="color: #004000;">sql</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'params'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_curQuery<span style="color: #339933;">-&gt;</span><span style="color: #004000;">params</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Nun müssen wir Doctrine noch mitteilen, dass unser Profiler verwendet werden soll. Wird Bisna eingesetzt, kann dies ganz einfach in der Konfiguration (hier beispielsweise in einer ini-Datei) erledigt werden:</p>
<div class="codecolorer-container php geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">resources<span style="color: #339933;">.</span>doctrine<span style="color: #339933;">.</span>dbal<span style="color: #339933;">.</span>connections<span style="color: #339933;">.</span><span style="color: #b1b100;">default</span><span style="color: #339933;">.</span>sqlLoggerClass <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;DoctrineExtensions\Profiler\ZFDebugProfiler&quot;</span></div></td></tr></tbody></table></div>
<p>Im Hintergrund wird der Konfiguration der DBAL-Verbindung eine neue Instanz unseres SQL Loggers übergeben:</p>
<div class="codecolorer-container php geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$configuration</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Doctrine\DBAL\Configuration<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$configuration</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setSQLLogger</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> DoctrineExtensions\Profiler\ZFDebugProfiler<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$connection</span> <span style="color: #339933;">=</span> Doctrine\DBAL\DriverManager<span style="color: #339933;">::</span><span style="color: #004000;">getConnection</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$connectionParams</span><span style="color: #339933;">,</span> <span style="color: #000088;">$configuration</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Natürlich lässt sich statt des ZFDebugProfilers auch einfach ein LogProfiler oder FirebugProfiler implementieren, welche die Queries direkt in eine Datei schreiben bzw. im Firebug ausgeben. Wir verwenden unseren Profiler hingegen, um die SQL Queries in einem ZFDebug Plugin aufzulisten.</p>
<h3>ZFDebug Plugin</h3>
<p>Nachdem der SQL Logger an Doctrine übergeben wurde, werden alle SQL Queries, deren Parameter und die Dauer der einzelnen Queries gespeichert. Ausgeben wollen wir das Ganze in unserer ZFDebug Leiste, wir erstellen also zunächst ein Plugin, indem wir das Interface <strong>ZFDebug_Controller_Plugin_Debug_Plugin_Interface</strong> implementieren:</p>
<p><strong>ZFDebug/Controller/Plugin/Debug/Plugin/Doctrine.php:</strong></p>
<div class="codecolorer-container php geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br />73<br />74<br />75<br />76<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">class</span> ZFDebug_Controller_Plugin_Debug_Plugin_Doctrine implements ZFDebug_Controller_Plugin_Debug_Plugin_Interface<br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$_identifier</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'doctrine'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$_profilers</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><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> __construct<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span> <span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'profiler'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_profilers <span style="color: #339933;">=</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'profiler'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_profilers<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_profilers <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_profilers<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getIdentifier<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_identifier<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getTab<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_profilers<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #0000ff;">'No Profiler'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_profilers <span style="color: #b1b100;">as</span> <span style="color: #000088;">$profiler</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$profilerInfo</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$profiler</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">queries</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">' in '</span> <span style="color: #339933;">.</span> <span style="color: #990000;">round</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$profiler</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">totalTime</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">1000</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span> &nbsp;<span style="color: #339933;">.</span> <span style="color: #0000ff;">' ms'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">' / '</span><span style="color: #339933;">,</span> <span style="color: #000088;">$profilerInfo</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getPanel<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$html</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_profilers<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$html</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'No Profiler'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_profilers <span style="color: #b1b100;">as</span> <span style="color: #000088;">$index</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$profiler</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$html</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;h4&gt;Profiler ['</span><span style="color: #339933;">.</span><span style="color: #000088;">$index</span><span style="color: #339933;">.</span><span style="color: #0000ff;">']&lt;/h4&gt;&lt;ol&gt;'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$profiler</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">queries</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$query</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$html</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;li&gt;&lt;b&gt;['</span> <span style="color: #339933;">.</span> <span style="color: #990000;">round</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$query</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'time'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">1000</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">' ms]&lt;/b&gt; '</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$html</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">highlightSql</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">htmlspecialchars</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$query</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'sql'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">empty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$query</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'params'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$html</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;br/&gt;&lt;i&gt;bindings:&lt;/i&gt;'</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">listBindings</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$query</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'params'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$html</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;/li&gt;'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$html</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;/ol&gt;'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$html</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> listBindings<span style="color: #009900;">&#40;</span><span style="color: #000088;">$bindings</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$html</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'&lt;ol&gt;'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$bindings</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$binding</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$html</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;li&gt;'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">is_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$binding</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$html</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">listBindings</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$binding</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$html</span> <span style="color: #339933;">.=</span> <span style="color: #000088;">$binding</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$html</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'&lt;/li&gt;'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #000088;">$html</span> <span style="color: #339933;">.</span> <span style="color: #0000ff;">'&lt;/ol&gt;'</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">function</span> highlightSql<span style="color: #009900;">&#40;</span><span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$statements</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'SELECT'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'UPDATE'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'INSERT'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'FROM'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'WHERE'</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'LEFT JOIN'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'JOIN'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'ORDER BY'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'GROUP BY'</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'OFFSET'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'LIMIT'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'SET'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'VALUES'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #b1b100;">return</span> <span style="color: #990000;">preg_replace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'/('</span><span style="color: #339933;">.</span><span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'|'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$statements</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">')/'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'&lt;b&gt;\1&lt;/b&gt;'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$sql</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Da wir auch ein wenig Wert auf die Formatierung legen, ist der Code des Plugins etwas umfangreicher ausgefallen. Wichtig sind die <strong>getTab()</strong> und <strong>getPanel()</strong> Methoden, welche die HTML Ausgabe für den Titel des Plugins in der Debugleiste und für detaillierte Informationen im Panel beim Ausklappen des Plugins zurückgeben.</p>
<p>Nun muss das Plugin noch in den Optionen von ZFDebug eingetragen werden. Beim Bootstrapping der Applikation erstellen wir das ZFDebug_Controller_Plugin_Debug und registrieren es beim Frontcontroller. Zunächst gehen wir jedoch sicher, dass die Doctrine Ressource bereits existiert und erstellen eine Liste der Profiler aller DBAL-Verbindungen, die wir anschließend unserem Plugin übergeben. In den ZFDebug Optionen tragen wir unter Plugins unsere Klasse <strong>ZFDebug_Controller_Plugin_Debug_Plugin_Doctrine</strong> mit dessen Konfiguration ein:</p>
<div class="codecolorer-container php geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bootstrap</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'doctrine'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$container</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResource</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'doctrine'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$profilers</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><br />
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$container</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getConnectionNames</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$connName</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$profiler</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$container</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getConnection</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$connName</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getConfiguration</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSQLLogger</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$profiler</span> instanceof DoctrineExtensions\Profiler\ZFDebugProfiler<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">$profilers</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$connName</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$profiler</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'plugins'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'ZFDebug_Controller_Plugin_Debug_Plugin_Doctrine'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000ff;">'profiler'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$profilers</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$debug</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ZFDebug_Controller_Plugin_Debug<span style="color: #009900;">&#40;</span><span style="color: #000088;">$options</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">bootstrap</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'frontController'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResource</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'frontController'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerPlugin</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$debug</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Nun lassen sich alle Queries von Doctrine und deren Performance übersichtlich in ZFDebug anzeigen. Zu beachten ist vielleicht, falls man Bisna verwendet, dass durch den Aufruf von $container->getConnection($name)&#8230; die DBAL-Verbindungen tatsächlich gestartet werden. Ansonsten würden sie nicht unbedingt bereits beim Bootstrapping, sondern erst bei der ersten Verwendung gestartet. Da ZFDebug aber sowieso nur im Debug-Modus laufen sollte, muss diesbezüglich nur auf den Unterschied zwischen Debug- und Production-Modus geachtet werden.</p>
<p>Verwendete Versionen:<br />
- Zend Framework 1.11.11<br />
- Doctrine 2.1.5<br />
- ZFDebug 1.5</p>
<p><a href="http://www.loremipsum.at/wp-content/uploads/2011/12/zfdebug.png"><img src="http://www.loremipsum.at/wp-content/uploads/2011/12/zfdebug-300x51.png" alt="" title="ZFDebug-Leiste mit Doctrine 2 Profiler Plugin" width="300" height="51" class="alignnone size-medium wp-image-3614" /></a></p>
<h3>Zend Framework 2</h3>
<p>Da ZF2 wohl noch einige Monate auf sich warten lässt, kann man im Moment leider noch keine vollwertige Webapplikation darauf aufbauen. Spätestens zum Release wird aber eine Umstellung fällig werden, sollte die zweite Version das einhalten was sie momentan verspricht. Es wäre daher interessant zu wissen, ob ZFDebug auch für ZF2 erscheint, was wenn man sich die Projektaktivität ansieht eher zu bezweifeln ist &#8211; oder es vielversprechende Alternativen dazu gibt?</p>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/code/integration-von-doctrine-in-eine-modul-basierte-zend-anwendung/" rel="bookmark">Integration von Doctrine in eine modulbasierte Zend Anwendung</a></li>
		<li><a href="http://www.loremipsum.at/blog/sem/neues-wordpress-plugin-affiliando-vergleichsrechner-1-0/" rel="bookmark">Neues WordPress Plugin: Affiliando Vergleichsrechner 1.0</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/rundungsfehler-in-magento-beheben/" rel="bookmark">Rundungsfehler in Magento beheben</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/code/doctrine-2-sql-profiler-in-debugleiste/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Der eigene Javascript Event Handler</title>
		<link>http://www.loremipsum.at/blog/code/der-eigene-javascript-event-handler/</link>
		<comments>http://www.loremipsum.at/blog/code/der-eigene-javascript-event-handler/#comments</comments>
		<pubDate>Mon, 17 Jan 2011 09:09:15 +0000</pubDate>
		<dc:creator>Daniel Leeb</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Codeschnippsel]]></category>
		<category><![CDATA[Event Handler]]></category>
		<category><![CDATA[Events]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Listener]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=2204</guid>
		<description><![CDATA[Besonders bei umfangreicheren Javascript-Umsetzungen zahlt es sich aus, eine kleine Bibliothek aus Hilfs-Funktionen und -Objekten zu entwickeln. Vorausgesetzt man möchte auf die Integration größerer Bibliotheken verzichten, muss man sich selbst um gewisse Grundfunktionen kümmern. Zu diesen zähle ich auch einen &#8230; <a href="http://www.loremipsum.at/blog/code/der-eigene-javascript-event-handler/">weiterlesen <span class="meta-nav">&#187;</span></a><div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/produkte/greenj/library/" rel="bookmark">Library</a></li>
		<li><a href="http://www.loremipsum.at/blog/technik/der-eigene-voip-server/" rel="bookmark">Der eigene VoIP-Server</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/rundungsfehler-in-magento-beheben/" rel="bookmark">Rundungsfehler in Magento beheben</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Besonders bei umfangreicheren Javascript-Umsetzungen zahlt es sich aus, eine kleine Bibliothek aus Hilfs-Funktionen und -Objekten zu entwickeln. Vorausgesetzt man möchte auf die Integration größerer Bibliotheken verzichten, muss man sich selbst um gewisse Grundfunktionen kümmern. Zu diesen zähle ich auch einen <strong>Event Handler</strong>.<br />
Im folgenden möchte ich eine einfache Möglichkeit zeigen, einen solchen vielseitig einsetzbaren Event Handler umzusetzen.</p>
<p>Vorab einige <strong>Anforderungen</strong> an einen Event Handler:<br />
- Jedes Objekt soll als Event Handler agieren können: Erweiterung (bzw. &#8220;Vererbung&#8221;) um Event Handler Funktionalität.<br />
- Beliebige Events.<br />
- Mehrere Listener bzw. Callbacks sollen an ein Event gebunden werden können.<br />
- Benutzerdefinierte Daten beim Auslösen eines Events an die Listener übergeben.<br />
- Übergabe von Rückgabewerten der Listener an das Event.</p>
<h3>Implementierung</h3>
<p>Zunächst ist es sinnvoll, aber natürlich nicht notwendig, ein Objekt zu erzeugen, welches als eine Art Namespace agiert, zum Beispiel:</p>
<div class="codecolorer-container javascript geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">window.<span style="color: #660066;">li</span> <span style="color: #339933;">=</span> window.<span style="color: #660066;">li</span> <span style="color: #339933;">||</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Ein leeres Objekt namens <strong>EventListener</strong> dient zum Identifizieren der Listener. Siehe dazu <strong>addListener()</strong> und <strong>deleteListener()</strong> weiter unten.</p>
<div class="codecolorer-container javascript geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">li.<span style="color: #660066;">EventListener</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Nun kommt das eigentliche Basis-Objekt, welches später von Objekten &#8220;geerbt&#8221; wird.</p>
<div class="codecolorer-container javascript geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">li.<span style="color: #660066;">BaseObject</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Wir verwenden das Javascript <strong>&#8220;prototype&#8221;</strong> Objekt, wodurch Instanzen von <strong>BaseObject</strong> um Methoden von dessen prototype erweitert werden.<br />
Die erste Methode, <strong>defaults()</strong>, ist eine kleine Hilfsfunktion, um etwas komfortabler Default-Werte von Funktionsparametern setzen zu können.</p>
<div class="codecolorer-container javascript geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">li.<span style="color: #660066;">BaseObject</span>.<span style="color: #660066;">prototype</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; defaults<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>parameter<span style="color: #339933;">,</span> defaultValue<span style="color: #339933;">,</span> type<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> type <span style="color: #339933;">===</span> <span style="color: #3366CC;">'undefined'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> parameter <span style="color: #339933;">!==</span> <span style="color: #3366CC;">'undefined'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> parameter <span style="color: #339933;">:</span> defaultValue<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> parameter <span style="color: #339933;">===</span> type<span style="color: #009900;">&#41;</span> <span style="color: #339933;">?</span> parameter <span style="color: #339933;">:</span> defaultValue<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></div></td></tr></tbody></table></div>
<p>Nun kommen die eigentlichen Methoden des Event Handlers:<br />
Mit der Methode <strong>addListener()</strong> kann einem Event mittels Name eine Callback-Funktion zugewiesen werden:</p>
<div class="codecolorer-container javascript geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; addListener<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>eventName<span style="color: #339933;">,</span> listenerCallback<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.__listeners <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">defaults</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> listenerObj <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> li.<span style="color: #660066;">EventListener</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #009900;">&#91;</span>eventName<span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">defaults</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #009900;">&#91;</span>eventName<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #009900;">&#91;</span>eventName<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; listener<span style="color: #339933;">:</span> listenerObj<span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #339933;">:</span> listenerCallback <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> listenerObj<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></div></td></tr></tbody></table></div>
<p>Um Events auszulösen und somit alle Listeners aufzurufen muss einfach die Methode <strong>trigger()</strong> mit dem entsprechenden Eventnamen aufgerufen werden. Optional können hier beliebige Daten an die Listener übergeben werden. Die Rückgabewerte der Callback-Funktionen der Listener werden als Array zurückgegeben.</p>
<div class="codecolorer-container javascript geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; trigger<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>eventName<span style="color: #339933;">,</span> data<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.__listeners <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">defaults</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; data <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">defaults</span><span style="color: #009900;">&#40;</span>data<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> <span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #009900;">&#91;</span>eventName<span style="color: #009900;">&#93;</span> <span style="color: #339933;">===</span> <span style="color: #3366CC;">'undefined'</span><span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> eventListeners <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #009900;">&#91;</span>eventName<span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> retArr <span style="color: #339933;">=</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> index <span style="color: #000066; font-weight: bold;">in</span> eventListeners<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; retArr.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span>eventListeners<span style="color: #009900;">&#91;</span>index<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">callback</span>.<span style="color: #660066;">call</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span><span style="color: #339933;">,</span> data<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> retArr<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span></div></td></tr></tbody></table></div>
<p>Die folgenden Methoden dienen nun noch zum Entfernen von Listener: entweder alle Listener, alle Listener eines Events oder ein bestimmter Listener (<strong>addListener()</strong> gibt ein <strong>EventListener</strong> Objekt zurück, welches zum Identifizieren von Listeners dient und der <strong>deleteListener()</strong> Methode übergeben werden kann).</p>
<div class="codecolorer-container javascript geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; deleteAllListeners<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.__listeners <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; deleteListeners<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>eventName<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.__listeners <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">defaults</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">typeof</span> <span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #009900;">&#91;</span>eventName<span style="color: #009900;">&#93;</span> <span style="color: #339933;">===</span> <span style="color: #3366CC;">'undefined'</span><span style="color: #009900;">&#41;</span> <span style="color: #000066; font-weight: bold;">return</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">delete</span> <span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #009900;">&#91;</span>eventName<span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; deleteListener<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>listenerObj<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.__listeners <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #660066;">defaults</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> index <span style="color: #000066; font-weight: bold;">in</span> <span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">var</span> i <span style="color: #000066; font-weight: bold;">in</span> <span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #009900;">&#91;</span>index<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #009900;">&#91;</span>index<span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">listener</span> <span style="color: #339933;">===</span> listenerObj<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.__listeners<span style="color: #009900;">&#91;</span>index<span style="color: #009900;">&#93;</span>.<span style="color: #660066;">splice</span><span style="color: #009900;">&#40;</span>i<span style="color: #339933;">,</span> <span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span> &nbsp; <br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p>Um ein Objekt, im folgenden <strong>li.MyObject</strong>, um diesen Event Handler zu erweitern kann etwa die <strong>extend()</strong>-Methode von <strong>jQuery</strong> verwendet werden:</p>
<div class="codecolorer-container javascript geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">jQuery.<span style="color: #660066;">extend</span><span style="color: #009900;">&#40;</span>li.<span style="color: #660066;">MyObject</span>.<span style="color: #660066;">prototype</span><span style="color: #339933;">,</span> li.<span style="color: #660066;">BaseObject</span>.<span style="color: #660066;">prototype</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<h3>Beispiel</h3>
<p>Mit diesen wenigen Zeilen Code erhält man einen simplen aber vielseitig einsetzbaren Event Handler. Zum Abschluss ein kurzer Beispielcode bei dem das Objekt <strong>li.MyObject</strong> wie oben beschrieben um <strong>li.BaseObject</strong> erweitert wurde und somit als Event Handler agieren kann:</p>
<div class="codecolorer-container javascript geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #003366; font-weight: bold;">var</span> obj <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> li.<span style="color: #660066;">MyObject</span><span style="color: #339933;">;</span><br />
<span style="color: #006600; font-style: italic;">// Binde eine anonyme Funktion an das Event mit dem Namen &quot;myEvent&quot;</span><br />
obj.<span style="color: #660066;">addListener</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'myEvent'</span><span style="color: #339933;">,</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>data<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">this</span>.<span style="color: #000066;">name</span> <span style="color: #339933;">=</span> data.<span style="color: #000066;">name</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">return</span> data.<span style="color: #000066;">name</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #006600; font-style: italic;">// Löse das Event &quot;myEvent&quot; aus: alle Listener werden aufgerufen und das Objekt { name: 'foo' } wird als Parameter übergeben.</span><br />
obj.<span style="color: #660066;">trigger</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'myEvent'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> <span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'foo'</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p><a href="http://www.loremipsum.at/wp-content/uploads/2011/01/eventhandler.js">Event Handler &#8211; Sourcecode</a></p>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/produkte/greenj/library/" rel="bookmark">Library</a></li>
		<li><a href="http://www.loremipsum.at/blog/technik/der-eigene-voip-server/" rel="bookmark">Der eigene VoIP-Server</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/rundungsfehler-in-magento-beheben/" rel="bookmark">Rundungsfehler in Magento beheben</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/code/der-eigene-javascript-event-handler/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Integration von Doctrine in eine modulbasierte Zend Anwendung</title>
		<link>http://www.loremipsum.at/blog/code/integration-von-doctrine-in-eine-modul-basierte-zend-anwendung/</link>
		<comments>http://www.loremipsum.at/blog/code/integration-von-doctrine-in-eine-modul-basierte-zend-anwendung/#comments</comments>
		<pubDate>Fri, 22 Oct 2010 10:49:47 +0000</pubDate>
		<dc:creator>Daniel Leeb</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[MVC]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[YAML]]></category>
		<category><![CDATA[Zend]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=1251</guid>
		<description><![CDATA[Eines der erste Dinge, die mir als Einsteiger in das Zend Framework auffielen, war die Vernachlässigung des M in Zends MVC Implementation. Views und Controller, wenngleich sie erst nach einer kleinen Einarbeitungszeit wirklich verständlich werden, bieten genau das, was eine &#8230; <a href="http://www.loremipsum.at/blog/code/integration-von-doctrine-in-eine-modul-basierte-zend-anwendung/">weiterlesen <span class="meta-nav">&#187;</span></a><div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/code/doctrine-2-sql-profiler-in-debugleiste/" rel="bookmark">Doctrine 2 SQL Profiler in Debugleiste</a></li>
		<li><a href="http://www.loremipsum.at/blog/einstieg-in-php-frameworks/" rel="bookmark">Einstieg in PHP Frameworks</a></li>
		<li><a href="http://www.loremipsum.at/blog/rechteverwaltung-alle-benutzer-sind-gleich-manche-sind-gleicher/" rel="bookmark">Rechteverwaltung &#8211; Alle Benutzer sind gleich, manche sind gleicher</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Eines der erste Dinge, die mir als Einsteiger in das <strong>Zend Framework</strong> auffielen, war die Vernachlässigung des M in Zends MVC Implementation. Views und Controller, wenngleich sie erst nach einer kleinen Einarbeitungszeit wirklich verständlich werden, bieten genau das, was eine komplexe Webanwendung benötigt. Jedoch fehlt eine wirklich umfangreiche Implementation von Models in Zend. Auch wenn diese im Moment in Arbeit ist, haben wir uns deshalb für <strong>Doctrine</strong> entschieden, welches genau diese Lücke für uns füllen soll. Es ist jedoch eine Herausforderung für sich, Doctrine in seine Zend Anwendung zu integrieren, zumal wir eine modulbasierte Struktur zugrunde liegen haben.</p>
<h3>Doctrine und Module</h3>
<p><a href="http://www.loremipsum.at/wp-content/uploads/2010/10/MVC.png"><img src="http://www.loremipsum.at/wp-content/uploads/2010/10/MVC-300x258.png" alt="" width="290" height="250" class="alignright size-medium wp-image-1297" /></a><br />
Die folgende Anleitung soll eine Möglichkeit zeigen, wie sich Doctrine und eine modulbasierte Zend Applikation verbinden lassen. Da Tutorials meist nur die simple Integration von Doctrine und Zend in einer &#8220;einfachen&#8221; Anwendung ohne Module zeigen, möchte ich hier besonders auf Module eingehen. Natürlich könnte man auch, unabhängig von Modulen, die Models einfach in einen gemeinsamen Ordner unterbringen. Dadurch geht jedoch ein zentraler Aspekt des modularen Aufbaus verloren und wir haben uns deshalb um eine andere Lösung bemüht. Des Weiteren muss angemerkt werden, dass in unserem Fall die Models eines Modules auch Beziehungen zu Models anderer Module haben können. Eine unabhängige Behandlung ist daher nicht möglich. Wäre dies nicht der Fall, könnte man auch einfach jedes Modul als eigenständige Anwendung betrachten und die oben erwähnten Tutorials zu Rate ziehen.<br />
Im Zuge der Anleitung werde ich auch gleich auf einige Vorzüge von Doctrine eingehen, empfehle jedoch die <a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/introduction/en">Doctrine-Einführung</a> durchzuarbeiten.</p>
<h3>Doctrine&#8217;s YAML Schema</h3>
<p>Um seine Models von Doctrine generieren zu lassen, bietet sich das Erstellen einer <a href="http://www.doctrine-project.org/projects/orm/1.2/docs/manual/yaml-schema-files/en">YAML-Schema-Datei</a> an. Diese kann entweder per Hand geschrieben oder aus einer existierenden Datenbank generiert werden:</p>
<div class="codecolorer-container php geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Doctrine_Manager<span style="color: #339933;">::</span><span style="color: #004000;">connection</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;mysql://user:pw@localhost/dbname&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">generateYamlFromDb</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'schema.yml'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Anschließend sollte das Schema jedoch nochmals überarbeitet werden, um eventuelle Anpassungen wie Klassennamen, Beziehungen, etc. durchzuführen. Es empfiehlt sich das Erstellen eines PHP Scripts für alle Doctrine Operationen. Auf die Erstellung eines solchen Skripts möchte ich jedoch hier nicht weiter eingehen, da dies bereits in der Doctrine Einführung und in diversen Tutorials ausführlich behandelt wird.</p>
<p>Ist das YAML-Schema erst einmal ausgearbeitet, lässt sich später auch die Datenbank daraus generieren. Änderungen im Datenbankdesign können also fortan direkt im YAML-Schema erfolgen, unabhängig von dem verwendeten Datenbanksystem.<br />
Aus der YAML-Datei lässt sich jedoch auch das <strong>Doctrine Model</strong> generieren, welches wir in unserer Webanwendung verwenden wollen. Hierfür müssen wir einige Einstellungen vornehmen, die Doctrine bei der Generierung berücksichtigen soll:</p>
<div class="codecolorer-container php geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$options</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'suffix'</span> &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'.php'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'baseClassPrefix'</span> &nbsp; &nbsp; &nbsp; <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Orm_'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'pearStyle'</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'baseClassesDirectory'</span> &nbsp;<span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #0000ff;">'generateTableClasses'</span> &nbsp;<span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span><br />
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">generateModelsFromYaml</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'schema.yml'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'models'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$options</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Der Eintrag <code class="codecolorer php geshi"><span class="php"><span style="color: #0000ff;">'baseClassPrefix'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'Orm_'</span></span></code> erweitert den Klassennamen unserer Model-Basisklassen und erzeugt durch <code class="codecolorer php geshi"><span class="php"><span style="color: #0000ff;">'pearStyle'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span></span></code> die Model-Datei im Ordner &#8216;Orm&#8217; ohne jedoch Orm_ im Dateinamen &#8211; eben im PEAR-Namensstil. Durch <code class="codecolorer php geshi"><span class="php"><span style="color: #0000ff;">'baseClassesDirectory'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">''</span></span></code> verzichten wir auf das &#8216;generated&#8217; Verzeichnis und mittels <code class="codecolorer php geshi"><span class="php"><span style="color: #0000ff;">'generateTableClasses'</span></span></code> werden zusätzlich Klassen, abgeleitet von Doctrine_Table, erzeugt.<br />
Nehmen wir an, in unserer Datenbank bzw. im YAML-Schema befinden sich die Tabellen &#8220;user&#8221; und &#8220;appointment&#8221;. Der obige Code würde dann folgendes Erzeugen:</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">models\Orm\Appointment.php &nbsp;class Orm_Appointment extends Doctrine_Record<br />
models\Orm\User.php &nbsp; &nbsp; &nbsp; &nbsp; class Orm_User extends Doctrine_Record<br />
models\Appointment.php&nbsp; &nbsp; &nbsp; class Appointment extends Orm_Appointment<br />
models\AppointmentTable.php class AppointmentTable extends Doctrine_Table<br />
models\User.php &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; class User extends Orm_User<br />
models\UserTable.php&nbsp; &nbsp; &nbsp; &nbsp; class UserTable extends Doctrine_Table</div></div>
<p>Unsere Webanwendung ist in folgender (etwas vereinfachter) Verzeichnisstruktur aufgebaut, wobei die eben aufgelisteten Dateien im Ordner /doctrine generiert werden:</p>
<p><a href="http://www.loremipsum.at/wp-content/uploads/2010/10/directories.jpg"><img src="http://www.loremipsum.at/wp-content/uploads/2010/10/directories.jpg" alt="" width="114" height="399" class="alignnone size-full wp-image-1293" /></a></p>
<p>Nun kommt ein etwas unschöner Vorgang, denn wir müssen die eben generierten Dateien in die Model-Ordner unserer Module verschieben. Um beim obigen Beispiel zu bleiben, verschieben wir User.php und UserTable.php in das &#8216;Core&#8217; Modul, also etwa modules/core/models/. Appointment.php und AppointmentTable.php verschieben wir nach modules/calendar/models/. Und den Orm Ordner können wir als Ganzes in unserem Application-Verzeichnis platzieren (wichtig ist nur, dass der Zend Autoloader die Dateien findet, mehr dazu gleich).</p>
<h3>Autoloader</h3>
<p>Da wir nun erfolgreich unsere Models generiert haben, können wir unserer Webapplikation mitteilen, wo diese zu finden sind. Folgende Methode kann zur Initialisierung von Doctrine in der Bootstrap Klasse (application/bootstrap.php) platziert werden:</p>
<div class="codecolorer-container php geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> _initDoctrine<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getApplication</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getAutoloader</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerNamespace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Doctrine'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">-&gt;</span><span style="color: #004000;">registerNamespace</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Orm'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">-&gt;</span><span style="color: #004000;">pushAutoloader</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Doctrine'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'autoload'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">-&gt;</span><span style="color: #004000;">pushAutoloader</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Doctrine'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'modelsAutoload'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #000088;">$manager</span> <span style="color: #339933;">=</span> Doctrine_Manager<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$manager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setAttribute</span><span style="color: #009900;">&#40;</span>Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">ATTR_MODEL_LOADING</span><span style="color: #339933;">,</span> Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">MODEL_LOADING_CONSERVATIVE</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$manager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setAttribute</span><span style="color: #009900;">&#40;</span>Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">ATTR_AUTOLOAD_TABLE_CLASSES</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #000088;">$manager</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">connection</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;mysql://user:pw@localhost/dbname&quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">&quot;conn&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<br />
&nbsp; &nbsp; Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">loadModels</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> APPLICATION_PATH <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/modules/core/models'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; APPLICATION_PATH <span style="color: #339933;">.</span> <span style="color: #0000ff;">'/modules/calendar/models'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></td></tr></tbody></table></div>
<p><code class="codecolorer php geshi"><span class="php">registerNamespace<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Doctrine'</span><span style="color: #009900;">&#41;</span></span></code> sorgt dafür, dass die Doctrine-Klasse in Doctrine.php geladen werden kann, vorausgesetzt der Pfad zur Doctrine-Library wurde als Include-Pfad, zum Beispiel in der index.php, gesetzt. Sollte Doctrine.php direkt inkludiert worden sein, kann man auf diese Zeile auch verzichten. <code class="codecolorer php geshi"><span class="php">registerNamespace<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Orm'</span><span style="color: #009900;">&#41;</span></span></code> ermöglicht das Autoloading der zuvor generierten Basisklassen Orm_User und Orm_Appointment. Der Ordner Orm muss dabei in einem inkludierten Pfad liegen, sodass er dem Zend Autoloader bekannt ist. Mittels den beiden pushAutoloader() Aufrufen registrieren wir die autoload() und modelsAutoload() Callbacks von Doctrine. Erstere ist für die Doctrine-Klassen zuständig, zweitere für unsere Models. Nun konfigurieren wir den Doctrine_Manager, sodass dieser unsere Models bei Bedarf (Conservative) und unsere Tables (UserTable, AppointmentTable) lädt. Mittels <code class="codecolorer php geshi"><span class="php">Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">loadModels</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span></span></code> teilen wir Doctrine die Pfade mit, in denen sich die Model-Dateien befinden. In der Praxis kann der Aufruf natürlich auch entweder in den speziellen Modul-Bootstrap-Klassen erfolgen, oder eine Methode verwendet werden, welche alle Model-Pfade der Module zurückgibt.<br />
Nun können wir die erstellten Model Klassen beliebig um eigene Methoden erweitern und in unseren Controller_Actions und Views verwenden:</p>
<div class="codecolorer-container php geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br /></div></td><td><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #666666; font-style: italic;">// class User extends Doctrine_Record</span><br />
<span style="color: #000088;">$user</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> User<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">username</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;Admin&quot;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$user</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">myMethod</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// eigene Methode in User Klasse</span><br />
<span style="color: #000088;">$user</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><br />
<br />
<span style="color: #666666; font-style: italic;">// UserTable</span><br />
<span style="color: #000088;">$usertable</span> <span style="color: #339933;">=</span> Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;User&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$usertable</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">myTableMethod</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>&nbsp; &nbsp; <span style="color: #666666; font-style: italic;">// eigene Methode in UserTable Klasse</span></div></td></tr></tbody></table></div>
<p>Falls sich das Schema ändert, sollte in den meisten Fällen ein Updaten des Orm Ordners ausreichen, dessen Dateien wir ohnehin nicht verändern wollen.</p>
<h3>Schlusswort</h3>
<p>Ob diese Variante, Doctrine in die eigene Zend Anwendung zu integrieren geeignet ist, hängt stark von den Anforderungen ab. Wir haben uns für diese Methode entschlossen, da wir zwar Abhängigkeiten zwischen den Models der Module haben, jedoch trotzdem eine prinzipielle Trennung vornehmen wollten. Jeder Teilbereich unseres Datenbankschemas wird in einer eigenen YAML-Schema-Datei definiert (also etwa core.yml und calendar.yml). Man könnte auch auf Packages (siehe Doctrine&#8217;s YAML Beschreibung) zurückgreifen, jedoch ändert sich dadurch die Namensgebung und eine weitere abstrakte Klasse wird für die Models erstellt. Der Aufwand die generierten Model-Dateien in die entsprechenden Ordner zu verschieben hält sich jedoch in Grenzen, weswegen wir uns für diese Variante entschieden haben.</p>
<p>Verwendete Versionen:<br />
<a href="http://framework.zend.com">Zend Framework</a> 1.10.8<br />
<a href="http://www.doctrine-project.org">Doctrine</a> 1.2</p>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/code/doctrine-2-sql-profiler-in-debugleiste/" rel="bookmark">Doctrine 2 SQL Profiler in Debugleiste</a></li>
		<li><a href="http://www.loremipsum.at/blog/einstieg-in-php-frameworks/" rel="bookmark">Einstieg in PHP Frameworks</a></li>
		<li><a href="http://www.loremipsum.at/blog/rechteverwaltung-alle-benutzer-sind-gleich-manche-sind-gleicher/" rel="bookmark">Rechteverwaltung &#8211; Alle Benutzer sind gleich, manche sind gleicher</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/code/integration-von-doctrine-in-eine-modul-basierte-zend-anwendung/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IP-Telefonie und der G.711-Codec</title>
		<link>http://www.loremipsum.at/blog/technik/ip-telefonie-und-der-g-711-codec/</link>
		<comments>http://www.loremipsum.at/blog/technik/ip-telefonie-und-der-g-711-codec/#comments</comments>
		<pubDate>Tue, 28 Sep 2010 09:33:47 +0000</pubDate>
		<dc:creator>Daniel Leeb</dc:creator>
				<category><![CDATA[Technik]]></category>
		<category><![CDATA[Codec]]></category>
		<category><![CDATA[G.711]]></category>
		<category><![CDATA[Internettelefonie]]></category>
		<category><![CDATA[VoIP]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=942</guid>
		<description><![CDATA[In der Internet-Telefonie werden Codecs (Coder und Decoder) verwendet um analoge Audiosignale für die Übertragung über das Internet zu digitalisieren. Der ITU-Standard (Internationale Fernmeldeunion) G.711 ist ein Sprachcodec, welcher in der klassischen Festnetz-Telefonie und IP-Telefonie eingesetzt wird. Die Sprachqualität des &#8230; <a href="http://www.loremipsum.at/blog/technik/ip-telefonie-und-der-g-711-codec/">weiterlesen <span class="meta-nav">&#187;</span></a><div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/das-sip-protokoll/" rel="bookmark">Das SIP-Protokoll</a></li>
		<li><a href="http://www.loremipsum.at/blog/technik/der-weg-zum-eigenen-sip-client/" rel="bookmark">Der Weg zum eigenen SIP-Client</a></li>
		<li><a href="http://www.loremipsum.at/blog/technik/der-eigene-voip-server/" rel="bookmark">Der eigene VoIP-Server</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>In der Internet-Telefonie werden Codecs (Coder und Decoder) verwendet um analoge Audiosignale für die Übertragung über das Internet zu digitalisieren. Der ITU-Standard (Internationale Fernmeldeunion) G.711 ist ein Sprachcodec, welcher in der klassischen Festnetz-Telefonie und IP-Telefonie eingesetzt wird.<br />
Die Sprachqualität des G.711 Codec entspricht derjenigen von ISDN. Hierbei erfolgt eine sogenannte PCM-Kodierung (Pulse Code Modulation) ohne Komprimierung mit einer Netto-Bitrate von 64 kbps. Durch die sehr gute Sprachqualität gilt er auch als Maßstab für Voice over IP.</p>
<h3>Der Codec im Test</h3>
<p>Um die benötigte Bandbreite zu ermitteln, haben wir ein simples Softphone basierend auf der <a href="http://www.pjsip.org/">pjsip</a>-Bibliothek entwickelt. In unseren Tests, bei denen ein Gespräch mit offenen Kanälen in beide Richtungen aufgebaut wurde, ergab sich eine Datenübertragung von 89 kbps sowohl ausgehend (Upload) als auch eingehend (Download). Die erhöhte Bitrate ergibt sich durch die bei VoIP verwendeten Protokolle RTP (Real-Time Transport Protocol) und UDP (User Datagram Protocol) zur Übertragung der IP-Pakete. Es empfiehlt sich jedoch im Praxiseinsatz einen Puffer von 10% (etwa für das optionale RTCP-Protokoll) einzurechnen, also etwa <strong>100 kbps für ein laufendes Gespräch</strong> zu kalkulieren. Sinkt die Leistung unter 89 kbps zeigt der Test, dass sofort eine spürbare Verzögerung eintritt, da die angestauten Pakete in diesem Fall in einer Warteschlange abgearbeitet werden.<br />
Vorteil von G.711: Sehr gute Sprachqualität.<br />
Nachteil: Benötigt durch die fehlende Komprimierung eine höhere Datenübertragungsrate im Vergleich zu anderen Codecs.</p>
<h3>Alternativen</h3>
<p><em>GSM</em>: Für Mobiltelefonie – es stehen verschiedene GSM-Sprachcodecs zur Verfügung, welche sich alle im Bereich von 20 kbps bewegen.<br />
<em>G.726</em>: Von der ITU beschriebener Codec zur Komprimierung von Sprache in digitale Signale. Verwendet Bitraten von 16 bis 40 kbps.<br />
<em>Speex</em>: Freier Audiocodec, optimiert auf Komprimierung von Audiodaten, die menschliche Sprache enthalten.</p>
<h3>Die Wahl des richtigen Codec</h3>
<p>Benötigt man eine gute Sprachqualität, die sich nicht vom Festnetz unterscheidet, oder steht eine ausreichende Bandbreite zur Verfügung empfiehlt sich der Einsatz des G.711 Codecs für die IP-Telefonie. Eine Übersicht der Sprachqualität von Codecs bietet der Mean Opinion Score (MOS) &#8211; von 1 (mangelhaft) bis 5 (ausgezeichnet):</p>
<table>
<tr>
<th>Codec (Datenrate)</th>
<th>MOS-Wert</th>
</tr>
<tr>
<td>G.711 (64 kbps)</td>
<td>4,1</td>
</tr>
<tr>
<td>G.722 (64 kbps)</td>
<td>4,5</td>
</tr>
<tr>
<td>G.726 (32 kbps)</td>
<td>3,85</td>
</tr>
<tr>
<td>G.723.1 (5,3 kbps)</td>
<td>3,65</td>
</tr>
<tr>
<td>G.723.1 (6,3 kbps)</td>
<td>3,9</td>
</tr>
<tr>
<td>G.729 (8 kbps)</td>
<td>3,92</td>
</tr>
<tr>
<td>G.729a (8 kbps)</td>
<td>3,7</td>
</tr>
</table>
<p>Quelle: Wikipedia</p>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/das-sip-protokoll/" rel="bookmark">Das SIP-Protokoll</a></li>
		<li><a href="http://www.loremipsum.at/blog/technik/der-weg-zum-eigenen-sip-client/" rel="bookmark">Der Weg zum eigenen SIP-Client</a></li>
		<li><a href="http://www.loremipsum.at/blog/technik/der-eigene-voip-server/" rel="bookmark">Der eigene VoIP-Server</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/technik/ip-telefonie-und-der-g-711-codec/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rechteverwaltung &#8211; Alle Benutzer sind gleich, manche sind gleicher</title>
		<link>http://www.loremipsum.at/blog/rechteverwaltung-alle-benutzer-sind-gleich-manche-sind-gleicher/</link>
		<comments>http://www.loremipsum.at/blog/rechteverwaltung-alle-benutzer-sind-gleich-manche-sind-gleicher/#comments</comments>
		<pubDate>Mon, 06 Sep 2010 10:32:17 +0000</pubDate>
		<dc:creator>Daniel Leeb</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[ACL]]></category>
		<category><![CDATA[Assert]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Rechteverwaltung]]></category>
		<category><![CDATA[Zend_Acl]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=791</guid>
		<description><![CDATA[Jede Seite mit mehreren Benutzern benötigt eine mehr oder weniger umfangreiche Rechteverwaltung. Ein simples Blog unterscheidet bereits zwischen Autoren, registrierten Benutzern und einfachen Gästen. ACL – Access Control List – ist eine Technik mit der sich ein flexibles Rechtesystem aufbauen &#8230; <a href="http://www.loremipsum.at/blog/rechteverwaltung-alle-benutzer-sind-gleich-manche-sind-gleicher/">weiterlesen <span class="meta-nav">&#187;</span></a><div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/passwoerter-richtig-speichern/" rel="bookmark">Passwörter richtig speichern</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/wordpress-adminbar-fur-usergruppen-global-deaktivieren/" rel="bookmark">WordPress Adminbar für Usergruppen global deaktivieren</a></li>
		<li><a href="http://www.loremipsum.at/wissen/webacademy/maile-ohye-site-performance-speed-optimieren/" rel="bookmark">Maile Ohye – Site Performance &#038; Speed optimieren</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Jede Seite mit mehreren Benutzern benötigt eine mehr oder weniger umfangreiche Rechteverwaltung. Ein simples Blog unterscheidet bereits zwischen Autoren, registrierten Benutzern und einfachen Gästen. ACL – Access Control List – ist eine Technik mit der sich ein flexibles Rechtesystem aufbauen lässt, indem festgelegt wird, welcher Benutzer welche Aktionen ausführen darf. Die hier vorgestellte Variante ist nur eine von vielen Möglichkeiten ein ACL-System aufzubauen.</p>
<h3>ACL Aufbau</h3>
<p>Das System besteht aus Benutzern, Rollen, Regeln sowie speziellen Bedingungen (Assertions). Einem Benutzer sollen mehrere Rollen aber auch einzelne Regeln zugewiesen werden können. Rollen bestehen aus einer Sammlung von Regeln. Eine Regel bestimmt, welche Aktion erlaubt oder nicht erlaubt ist oder ob eine bestimmte Bedingung erfüllt werden muss. Eine Bedingung kann in diesem Zusammenhang etwa die Einschränkung auf eine bestimmte IP oder ein eingeschränkter Zeitraum sein.</p>
<h3>ACL in der Datenbank</h3>
<p>Folgende Tabellen werden in der Datenbank benötigt:</p>
<ul>
<li><strong>user</strong></li>
<li><strong>role</strong>
<ul>
<li>name: z.B. “Admin”, “Guest”, …</li>
<li>parent_id: Falls die Rolle die Regeln einer anderen Rolle erben soll.</li>
<li>order: Werden einem Benutzer mehrere Rollen zugewiesen, bestimmt diese Rangordnung die Reihenfolge und damit Priorität der jeweiligen Rolle.</li>
</ul>
</li>
<li><strong>rule</strong>
<ul>
<li>resource: Entspricht einem Controller; z.B.: „site“.</li>
<li>pivilege: Entspricht einer Action eines Controllers; z.B.: „index“.</li>
<li>assert_id: Falls die Regeln an eine Bedingung gebunden ist.</li>
<li>permission: Wird die jeweilige Aktion erlaubt oder verweigert; z.B.: „Allow“/“Deny“.</li>
</ul>
</li>
<li>Tabellen zur Zuweisung von Regeln: <strong>user_roles</strong>, <strong>user_rules</strong> und <strong>role_rules</strong>.</li>
<li><strong>assert</strong>
<ul>
<li>Classname: Der Name der Klasse, in der die Bedingung geprüft wird; z.B.: „IPAssertion“</li>
</ul>
</li>
</ul>
<h3>ACL und das Zend Framework</h3>
<p>Das Zend PHP Framework bietet mit der Zend_Acl Klasse bereits eine Implementierung eines ACL-Systems. Im Folgenden möchte ich die wichtigsten Funktionen vorstellen:</p>
<div style="font-family:Courier New">
// Instanz von Zend_Acl mit welcher die Rechteverwaltung realisiert wird.<br />
$acl = new Zend_Acl();</p>
<p>// Hinzufügen einer Rolle ‚guest‘.<br />
$acl-&gt;addRole(new Zend_Acl_Role(&#8216;guest&#8217;));</p>
<p>// Der Benutzer (hier repräsentiert als Rolle) ‚myUser‘ erbt die Rolle ‚guest‘.<br />
//  Auf dieselbe Weise können auch Rollen Eigenschaften anderer Rollen erben.<br />
$acl-&gt;addRole(new Zend_Acl_Role(&#8216;myUser&#8217;), &#8216;guest&#8217;);</p>
<p>// Hinzufügen einer Ressource (Controller)<br />
$acl-&gt;add(new Zend_Acl_Resource(&#8216;site&#8217;));</p>
<p>// Deny All<br />
$acl-&gt;deny(null);<br />
// Setzen der Zugriffsrechte von Rollen auf Ressourcen/Privilegien mit Bedingung:<br />
//  *Assertion sind Klassen, welche Zend_Acl_Assert_Interface implementieren.<br />
$acl-&gt;allow(&#8216;guest&#8217;, &#8216;site&#8217;, &#8216;index&#8217;);<br />
$acl-&gt;deny(&#8216;guest&#8217;, &#8216;site&#8217;, null, IPAssertion);<br />
$acl-&gt;allow(&#8216;myUser&#8217;, &#8216;site&#8217;, &#8216;index&#8217;, TimeAssertion);<br />
$acl-&gt;allow(&#8216;myUser&#8217;, &#8216;site&#8217;);</p>
<p>// Abfrage eines Zugriffsrechts<br />
$acl-&gt;isAllowed(&#8216;myUser&#8217;, &#8216;site&#8217;, &#8216;index&#8217;);
</p></div>
<h3>ACL im Einsatz</h3>
<p>Um das oben beschriebene System zu implementieren muss also zunächst eine Zend_Acl Instanz erstellt werden. Dieser werden alle Rollen aus der Datenbank übergeben. Der Benutzer wird ebenfalls angelegt und mit seinen zugewiesenen Rollen übergeben (als zusätzlicher Parameter von addRole(), sodass deren Eigenschaften dem Benutzer vererbt werden). Anschließend werden die Ressourcen erstellt und übergeben. Mittels deny(null) können alle Zugriffe verhindert werden. Nun folgen die Regel-Zuweisungen via allow() und deny() Aufrufe, wodurch den Rollen die jeweiligen Ressourcen, Privilegien und Bedingungen zugewiesen werden. Beim Aufruf eines Controllers und dessen Action kann nun das Zugriffsrecht mittels der Methode isAllowed() überprüft werden.</p>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/passwoerter-richtig-speichern/" rel="bookmark">Passwörter richtig speichern</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/wordpress-adminbar-fur-usergruppen-global-deaktivieren/" rel="bookmark">WordPress Adminbar für Usergruppen global deaktivieren</a></li>
		<li><a href="http://www.loremipsum.at/wissen/webacademy/maile-ohye-site-performance-speed-optimieren/" rel="bookmark">Maile Ohye – Site Performance &#038; Speed optimieren</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/rechteverwaltung-alle-benutzer-sind-gleich-manche-sind-gleicher/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Passwörter richtig speichern</title>
		<link>http://www.loremipsum.at/blog/passwoerter-richtig-speichern/</link>
		<comments>http://www.loremipsum.at/blog/passwoerter-richtig-speichern/#comments</comments>
		<pubDate>Fri, 03 Sep 2010 10:46:15 +0000</pubDate>
		<dc:creator>Daniel Leeb</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Codeschnippsel]]></category>
		<category><![CDATA[Hash]]></category>
		<category><![CDATA[MD5]]></category>
		<category><![CDATA[Passwort]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Salt]]></category>
		<category><![CDATA[SHA]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=742</guid>
		<description><![CDATA[Bei der Benutzerverwaltung sollte man von Anfang an Wert auf eine sichere Verwahrung der Passwörter legen. Natürlich ist zu beachten, Passwörter im Klartext weder in die Datenbank oder in ein Log zu speichern noch per Email zu senden. Bevor das &#8230; <a href="http://www.loremipsum.at/blog/passwoerter-richtig-speichern/">weiterlesen <span class="meta-nav">&#187;</span></a><div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/rechteverwaltung-alle-benutzer-sind-gleich-manche-sind-gleicher/" rel="bookmark">Rechteverwaltung &#8211; Alle Benutzer sind gleich, manche sind gleicher</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/wordpress-adminbar-fur-usergruppen-global-deaktivieren/" rel="bookmark">WordPress Adminbar für Usergruppen global deaktivieren</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/permanenter-zugriff-fur-die-facebook-app/" rel="bookmark">Permanenter Zugriff für die Facebook-App</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Bei der Benutzerverwaltung sollte man von Anfang an Wert auf eine sichere Verwahrung der Passwörter legen. Natürlich ist zu beachten, Passwörter im Klartext weder in die Datenbank oder in ein Log zu speichern noch per Email zu senden. Bevor das Benutzerpasswort gespeichert wird, kann es etwa mit einem Hash-Algorithmus verschlüsselt werden. Im Gegensatz zum Encodieren können aus Hashwerten die originalen Nachrichten bzw. Passwörter nicht wiederhergestellt werden. Bei der Benutzerauthentifizierung muss also zunächst der Hashwert des übergebenen Passworts erzeugt und dann mit dem Hashwert des Passworts aus der Datenbank verglichen werden. Es stehen verschiedene Hash-Algorithmen zur Verfügung, welche sich z.B. in Hinsicht auf Größe und Sicherheit unterscheiden. Die bekannte Funktion MD5 gilt mittlerweile als unsicher, da es zwei verschiedene Nachrichten m1 und m2 geben kann, für die gilt md5(m1)=md5(m2). Auch wenn dies hinsichtlich Passwörter nicht bedeutet, dass die Hashwerte der Passwörter unsicher sind, kann man auf Alternativen zurückgreifen: etwa SHA256 oder SHA512 (256 Bit bzw. 512 Bit großer Hashwert, im Gegensatz zum 128 Bit großen MD5-Hash).</p>
<p>Beispiel einer PHP-Funktion, welche einen SHA256-Hashwert zurückgibt:</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">hash_hmac('sha256', $salt . ':' . $password, $appSalt);</div></td></tr></tbody></table></div>
<h3>Sicher versalzen</h3>
<p>Um die gespeicherten Passwörter noch sicherer zu verwahren, empfiehlt sich das &#8220;beimischen&#8221; eines zufallsgenerierten Wertes, genannt Salt. Dieser wird dem Passwort angehängt und dann der Hashfunktion übergeben. Für jeden Benutzer sollte ein eigener Salt generiert und neben dem Hashcode des Passworts in der Datenbank gespeichert werden. Das hat den Vorteil, dass vorberechnete Hashtabellen eines Angreifers nutzlos sind, da jedes Passwort mit einem eigenen Salt versehen wurde. Zusätzlich kann noch ein globaler Anwendungs-Schlüssel (Application Salt) beigestreut werden.</p>
<p>Beispielfunktion zum Generieren eines Salts (PHP-Code):</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">function genSalt($saltLen) {<br />
&nbsp; &nbsp; $chars64 = &quot;./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&quot;;<br />
&nbsp; &nbsp; $salt = &quot;&quot;;<br />
&nbsp; &nbsp; for ($i=0;$i &amp;lt; $saltLen;$i++) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; $salt .= substr($chars64, rand()%64, 1);<br />
&nbsp; &nbsp; }<br />
&nbsp; &nbsp; return $salt;<br />
}</div></td></tr></tbody></table></div>
<h3>Starke Passwörter</h3>
<p>Alle hier aufgeführten Maßnahmen betreffen jedoch nur die Speicherung von Passwörtern. Sicher sind Passwörter nur, wenn der Benutzer selbst ein starkes Passwort eingibt. Um dies zu erreichen können bei der Passworteingabe folgende Regeln definiert werden: Eine Kombination aus Buchstaben, Zahlen und Sonderzeichen sowie eine Mindestlänge des Passworts. Eine Anzeige der Passwortstärke während der Eingabe (etwa mittels Auswertung via Javascript) kann dem Benutzer darüber hinaus helfen, ein sicheres Passwort zu wählen.</p>
<p>Links:<br />
<a href="http://en.wikipedia.org/wiki/Cryptographic_hash_function#Cryptographic_hash_algorithms">Hashfunktionen</a></p>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/rechteverwaltung-alle-benutzer-sind-gleich-manche-sind-gleicher/" rel="bookmark">Rechteverwaltung &#8211; Alle Benutzer sind gleich, manche sind gleicher</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/wordpress-adminbar-fur-usergruppen-global-deaktivieren/" rel="bookmark">WordPress Adminbar für Usergruppen global deaktivieren</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/permanenter-zugriff-fur-die-facebook-app/" rel="bookmark">Permanenter Zugriff für die Facebook-App</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/passwoerter-richtig-speichern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Der Projekt-Werkzeugkasten</title>
		<link>http://www.loremipsum.at/blog/der-projekt-werkzeugkasten/</link>
		<comments>http://www.loremipsum.at/blog/der-projekt-werkzeugkasten/#comments</comments>
		<pubDate>Fri, 20 Aug 2010 11:19:18 +0000</pubDate>
		<dc:creator>Daniel Leeb</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Technik]]></category>
		<category><![CDATA[Dokumentation]]></category>
		<category><![CDATA[Entwicklung]]></category>
		<category><![CDATA[Projektmanagement]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Werkzeuge]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=591</guid>
		<description><![CDATA[Möchte man heutzutage ein Projekt realisieren, kann man auf eine Vielzahl von Planungs-, Projekt-, Dokumentations- und Entwicklungstools zurückgreifen. Obwohl Bleistift und Papier nach wie vor ihre Daseinsberechtigung besitzen, erleichtern diverse Werkzeuge die tägliche Projektarbeit ungemein. Am Anfang war die Planung &#8230; <a href="http://www.loremipsum.at/blog/der-projekt-werkzeugkasten/">weiterlesen <span class="meta-nav">&#187;</span></a><div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/code/wordpress-3-1-pluginbugfixing-bei-kategorielinks/" rel="bookmark">WordPress 3.1 Pluginbugfixing bei Kategorielinks</a></li>
		<li><a href="http://www.loremipsum.at/blog/einstieg-in-php-frameworks/" rel="bookmark">Einstieg in PHP Frameworks</a></li>
		<li><a href="http://www.loremipsum.at/blog/technik/der-eigene-voip-server/" rel="bookmark">Der eigene VoIP-Server</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Möchte man heutzutage ein Projekt realisieren, kann man auf eine Vielzahl von Planungs-, Projekt-, Dokumentations- und Entwicklungstools zurückgreifen. Obwohl Bleistift und Papier nach wie vor ihre Daseinsberechtigung besitzen, erleichtern diverse Werkzeuge die tägliche Projektarbeit ungemein.</p>
<h3>Am Anfang war die Planung</h3>
<p>Neben Office-Lösungen (<a href="http://office.microsoft.com">MS Office</a>, <a href="http://de.openoffice.org/">OpenOffice</a>) empfiehlt sich anfangs der Einsatz einer Mind-Mapping-Software (<a href="http://freemind.sourceforge.net/">FreeMind</a> <a href="http://www.mindmeister.com">MindMeister.com</a>) um eine erste Projektübersicht zu erstellen und Brain-Stormings festzuhalten.</p>
<p>Verwendet man MySQL und möchte seine Datenbank importieren oder ein erstelltes Design exportieren, bietet sich <a href="http://www.mysql.de/products/workbench/">MySQL Workbench</a> (Nachfolger des DB Designers) an.</p>
<p>Diagramm-/UML-Modeller eignen sich gut um etwa die Struktur einer Anwendung oder Use-Cases grafisch darzustellen. <a href="http://office.microsoft.com/de-de/visio/">MS Visio</a> ist ein bekannter Vertreter dieser Werkzeuge; mit <a href="http://www.yworks.com/en/products_yed_about.html">yEd</a> wartet hingegen ein sehr simples und vor allem freies Tool. Eine kostenpflichtige, dafür sehr umfangreiche Software in diesem Bereich wäre <a href="http://www.visual-paradigm.com/">Visual Paradigm</a>.</p>
<h3>Projekte managen</h3>
<p>Besonders für die Entwicklung von Projekten in einem Team sollte eine Projektmanagement-Software verwendet werden. Hier können Vorgänge zeitlich koordiniert und Ressourcen (Mitarbeiter, Kosten, etc.) zugeteilt werden. <a href="http://www.microsoft.com/Project/">MS Project</a> oder <a href="http://www.openworkbench.org/">OpenWorkbench</a> verwenden die Darstellung mittels Gantt-Diagramm (weitere Ansätze: Netzplan, Projektstrukturplan). Sehr umfangreiche Open-Source-Lösungen im Bereich Projektmanagement sind <a href="http://endeavour-mgmt.sourceforge.net/">Endeavour Software Project Management</a> oder <a href="http://www.project-open.com/">Project Open</a>.</p>
<h3>Schöner coden</h3>
<p>Um effizient im Team arbeiten zu können, besonders wenn Programmierarbeit koordiniert werden muss, hilft der Einsatz einer Versionsverwaltungssoftware. Zwei vielversprechende Kandidaten in diesem Bereich sind <a href="http://git-scm.com/">GIT</a> und <a href="http://subversion.apache.org/">SVN</a>. Wobei es hier eine große Auswahl an robusten Open-Source-Lösungen gibt.</p>
<p>Auch der Einsatz einer Code-Dokumentationssoftware ist empfehlenswert, um auch die technischen Aspekte des Projektes strukturiert festzuhalten. Die freie Software <a href="http://www.stack.nl/~dimitri/doxygen/">DoxyGen</a> bietet eine Vielzahl an Funktionen und unterstützt die meisten Programmiersprachen.</p>
<p>Bug-Tracking-Tools helfen hingegen, wie der Name es bereits verrät, Fehler zu protokollieren und gezielt auszubessern. <a href="http://www.mantisbt.org/">Mantis</a> ist ein populäres Web-basiertes System, welches auch als Projektmanagementsoftware eingesetzt werden kann. Ebenfalls empfehlenswert in diesem Bereich: <a href="http://www.bugzilla.org/">Bugzilla</a>. Beide Bug Tracker sind frei erhältlich.</p>
<p>Ein zentrales Entwicklerwerkzeug, möchte man sich nicht mit Notepad &amp; Co begnügen, ist die integrierte Entwicklungsumgebung (IDE): Mein persönlicher Favorit für C++ Programmierer unter Windows: <a href="http://www.microsoft.com/germany/express/">MS Visual Studio</a> (in der Express Version gratis erhältlich). Weitere freie IDEs für verschiedene Programmiersprachen: <a href="http://www.eclipse.org/">Eclipse</a>, <a href="http://netbeans.org/">NetBeans</a>, <a href="http://www.codeblocks.org/">Code::Blocks</a> (C/C++).</p>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/code/wordpress-3-1-pluginbugfixing-bei-kategorielinks/" rel="bookmark">WordPress 3.1 Pluginbugfixing bei Kategorielinks</a></li>
		<li><a href="http://www.loremipsum.at/blog/einstieg-in-php-frameworks/" rel="bookmark">Einstieg in PHP Frameworks</a></li>
		<li><a href="http://www.loremipsum.at/blog/technik/der-eigene-voip-server/" rel="bookmark">Der eigene VoIP-Server</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/der-projekt-werkzeugkasten/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Einstieg in PHP Frameworks</title>
		<link>http://www.loremipsum.at/blog/einstieg-in-php-frameworks/</link>
		<comments>http://www.loremipsum.at/blog/einstieg-in-php-frameworks/#comments</comments>
		<pubDate>Mon, 16 Aug 2010 07:40:33 +0000</pubDate>
		<dc:creator>Daniel Leeb</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Technik]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Framework]]></category>
		<category><![CDATA[Open-Source]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Yii]]></category>
		<category><![CDATA[Zend]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=571</guid>
		<description><![CDATA[Will man nicht wertvolle Entwicklungszeit in ein eigenes PHP Framework stecken, hat man eine Reihe von freien Frameworks zur Auswahl. In diesem Artikel möchte ich keinen direkten Vergleich der Frameworks anstellen. Diese gibt es im Überfluss im Web zu finden &#8230; <a href="http://www.loremipsum.at/blog/einstieg-in-php-frameworks/">weiterlesen <span class="meta-nav">&#187;</span></a><div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/die-suche-nach-der-passenden-sip-api/" rel="bookmark">Die Suche nach der passenden SIP-API</a></li>
		<li><a href="http://www.loremipsum.at/blog/qt-ein-machtiges-gui-framework/" rel="bookmark">Qt &#8211; Ein mächtiges GUI-Framework</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/doctrine-2-sql-profiler-in-debugleiste/" rel="bookmark">Doctrine 2 SQL Profiler in Debugleiste</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Will man nicht wertvolle Entwicklungszeit in ein eigenes PHP Framework stecken, hat man eine Reihe von freien Frameworks zur Auswahl. In diesem Artikel möchte ich keinen direkten Vergleich der Frameworks anstellen. Diese gibt es im Überfluss im Web zu finden – einige davon habe ich in den Links am Ende des Artikels aufgelistet. Statt dessen möchte ich den Einstieg in die drei beliebten Frameworks Zend, Yii und CodeIgniter beschreiben, sowie anschließend einen kurzen Blick darauf werfen wie gut sich große Webanwendungen im jeweiligen PHP Framework umsetzen lassen.</p>
<h3>Erste Schritte</h3>
<p>Zunächst versucht man sich naturgemäß einen ersten Überblick über die verschiedenen freien PHP Frameworks mittels Vergleich-Listen und subjektiven, sich oft auch widersprechenden Artikeln im Netz zu machen. Nachdem man nun festgestellt hat, dass sich die beliebteren PHP Frameworks offensichtlich in ihren Features kaum unterscheiden bzw. die Vergleiche einem bei der Entscheidung nicht viel weiterhelfen, sucht man deren Webseiten auf. Hier bekommt man einen ersten Überblick über Dokumentation, Community sowie Aufbau einer einfachen Webanwendung.</p>
<h3>Yii PHP Framework</h3>
<p>URL: <a href="http://www.yiiframework.com">http://www.yiiframework.com/</a><br />
Yii bietet meines Erachtens eine umfangreiche und übersichtliche Dokumentation, eine einfache Einführung mittels des beliebten Blog-Tutorials sowie eine Sammlung von User-Tutorials die unterschiedlichste Themengebiete abdeckt. Da es sich um ein junges Framework handelt, steht im Vergleich eine relativ kleine, aber schnell wachsende Community dahinter.</p>
<p>Nach dem Downloaden und Entpacken des Frameworks kann sofort via &#8216;yiic&#8217; Tool (Konsolenbefehl) ein neues Projekt erstellt werden:</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">yiic webapp path/to/webroot</div></td></tr></tbody></table></div>
<p>Im gewählten Verzeichnis wird eine bereits relativ umfangreiche Webanwendung erstellt, auf deren Basis man sofort mit der eigenen Implementierung beginnen kann. Sogar eine einfache Benutzeranmeldung, welche leicht erweiterbar ist, findet sich im eben erstellten Projekt. Aktiviert man das Modul <em>Gii</em> in der Applikations-Konfiguration steht einem ein praktisches Tool zur automatischen Code-Erstellung von Model, Controller, CRUD-Operationen (Create, read, update und delete) und Modulen zur Verfügung.</p>
<h3>Zend Framework</h3>
<p>URL: <a href="http://framework.zend.com/">http://framework.zend.com/</a><br />
Das am weitesten verbreitete Framework hat zwar eine sehr umfangreiche Dokumentation, ist aber was den Einstieg betrifft etwas unübersichtlich. Im Gegensatz zum sehr strikt Objekt-orientiert aufgebauten Yii Framework bei dem die Struktur eines Projektes schnell erkannt werden kann. Dafür bietet es eine enorme Flexibilität und hat eine sehr aktive Community.</p>
<p>Auch hier kann ein neues Projekt mittels eines Konsolenbefehls erstellt werden:</p>
<div class="codecolorer-container text geshi" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">zf create project path/to/webroot</div></td></tr></tbody></table></div>
<p>Das dabei erstellte Projekt kümmert sich jedoch &#8216;nur&#8217; um die notwendigsten Vorgänge und ist daher um einiges schlanker im Vergleich zur Yii &#8211; Webanwendung. Mittels des zf – Befehls können weitere Aktionen im aktuellen Projekt ausgeführt werden: Layouts aktivieren, Datenbank-Adapter einrichten, Model erstellen, usw. Durch den flexiblen Aufbau von Zend muss man mit einer etwas längeren Einarbeitungszeit in das Framework rechnen.</p>
<h3>CodeIgniter</h3>
<p>URL: <a href="http://www.codeigniter.com/">http://www.codeigniter.com/</a><br />
CodeIgniter wird im Gegensatz zu den anderen Projekten einfach in ein Verzeichnis entpackt ohne explizit ein eigenes Projekt zu erstellen. Unter dem Ordner <em>application</em> befinden sich die wichtigsten Elemente (Models, Views, Controllers). Durch den simplen Aufbau des Frameworks lassen sich schnell einfache Webanwendungen auch ohne viel Erfahrung in PHP realisieren. Jedoch ist der Umfang von CodeIgniter etwas bescheidener als bei den anderen Frameworks. Auf der Webseite findet man eine gute Dokumentation sowie einige von der Community erstellte Tutorials.</p>
<h3>Large-scale Applications</h3>
<p>Alle Frameworks bieten eine <abbr title="Hierarchical-Model-View-Controller">HMVC</abbr>-Architektur, wodurch eine klare und einfache Trennung ermöglicht wird – etwa in Frontend und Backend-Bereich. Die bekannte e-Commerce Software Magento (basiert auf dem Zend Framework) setzt zum Beispiel sehr stark auf einen modul-basierten Aufbau. Was die Performance betrifft haben das Yii Framework sowie CodeIgniter wiederrum die Nase vorne, vertraut man den diversen im Web veröffentlichten Benchmarks. Aufgrund des größeren Funktionsumfangs würde ich mich hier entweder für Yii oder Zend entscheiden.</p>
<h3>Fazit</h3>
<p>Der Einstieg in das Yii PHP Framework ist mir persönlich leichter gefallen, da die Struktur klarer ist und die Webanwendung durch das überlegte Objekt-orientierte Design sehr leicht erweiterbar ist. Das Zend Framework hat jedoch den Vorteil, dass es flexibler und trotz des enormen Umfangs sehr gut dokumentiert ist. Dafür sorgt allein die weite Verbreitung und große Community des Projektes. CodeIgniter bietet sich für die schnelle Entwicklung von kleineren Webanwendungen an.</p>
<p><a href="http://www.phpframeworks.com/">http://www.phpframeworks.com/</a><br />
<a href="http://www.bestwebframeworks.com/php/">http://www.bestwebframeworks.com/php/</a><br />
<a href="http://en.wikipedia.org/wiki/Comparison_of_web_application_frameworks#PHP_2">http://en.wikipedia.org/wiki/Comparison_of_web_application_frameworks#PHP_2</a></p>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/die-suche-nach-der-passenden-sip-api/" rel="bookmark">Die Suche nach der passenden SIP-API</a></li>
		<li><a href="http://www.loremipsum.at/blog/qt-ein-machtiges-gui-framework/" rel="bookmark">Qt &#8211; Ein mächtiges GUI-Framework</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/doctrine-2-sql-profiler-in-debugleiste/" rel="bookmark">Doctrine 2 SQL Profiler in Debugleiste</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/einstieg-in-php-frameworks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Der eigene VoIP-Server</title>
		<link>http://www.loremipsum.at/blog/technik/der-eigene-voip-server/</link>
		<comments>http://www.loremipsum.at/blog/technik/der-eigene-voip-server/#comments</comments>
		<pubDate>Fri, 06 Aug 2010 09:45:35 +0000</pubDate>
		<dc:creator>Daniel Leeb</dc:creator>
				<category><![CDATA[Technik]]></category>
		<category><![CDATA[Asterisk]]></category>
		<category><![CDATA[SIP]]></category>
		<category><![CDATA[Telefonanlage]]></category>
		<category><![CDATA[VoIP]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=482</guid>
		<description><![CDATA[Beschäftigt man sich mit Voice over IP (VoIP) fällt schnell der Name Asterisk. Die Open-Source-Software ist gerade hinsichtlich Flexibilität und Kosten erste Anlaufstelle für die eigene VoIP Umgebung. Flexibilität bietet Asterisk hinsichtlich Skalierbarkeit sowie Einsatzmöglichkeiten – etwa als eigenständiger PBX &#8230; <a href="http://www.loremipsum.at/blog/technik/der-eigene-voip-server/">weiterlesen <span class="meta-nav">&#187;</span></a><div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/der-richtige-voip-client/" rel="bookmark">Der richtige VoIP-Client</a></li>
		<li><a href="http://www.loremipsum.at/blog/git-as-a-server/" rel="bookmark">Git as a Server</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/der-eigene-javascript-event-handler/" rel="bookmark">Der eigene Javascript Event Handler</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Beschäftigt man sich mit Voice over IP (VoIP) fällt schnell der Name Asterisk. Die Open-Source-Software ist gerade hinsichtlich Flexibilität und Kosten erste Anlaufstelle für die eigene VoIP Umgebung. Flexibilität bietet Asterisk hinsichtlich Skalierbarkeit sowie Einsatzmöglichkeiten – etwa als eigenständiger PBX (Telefonanlage), als VoIP Gateway oder Anrufbeantworter.</p>
<h2>Der Server als Telefonanlage oder Gateway</h2>
<p>Die Kostenfrage stellt sich jedoch zunächst bei der Server- und Client-Hardware. Hier können größere Investitionen anstehen, möchte man seine eigene Telefonanlage mit PSTN-Anschluss (Festnetz) realisieren, die über eine Heimlösung hinausgeht. Stattdessen eignet sich eine Anbindung an einen VoIP- bzw. <abbr title="Session Initiation Protocol">SIP</abbr>-Provider (oft im Angebot eines <abbr title="Internet Service Provider">ISP</abbr>). Der eigene Asterisk-Server dient nur mehr als Gateway zwischen diesem und den internen Endgeräten, wodurch auch die Hardwareanforderungen an den Server rapide sinken. Die benötigte Bandbreite richtet sich nach der Anzahl an gleichzeitig geführten Gesprächen (bei guter Gesprächsqualität beginnend bei 100Kbps (up und down); bei 20 parallelen Gesprächen etwa 2Mbps).</p>
<h2>Die Wahl der Endgeräte</h2>
<p>Bei den Endgeräten muss man Kosten entweder für IP-Telefone, herkömmliche analoge Telefone oder aber PC + Headset einrechnen. Zusätzlich benötigt man für die PC-Lösung ein Softphone, also eine Client-Software, welche als Telefon fungiert. Dafür bietet diese Variante die höchste Flexibilität und lässt sich auch auf die eigenen Bedürfnisse anpassen.</p>
<h2>Fazit</h2>
<p>Investitionskosten für die VoIP Lösung hängen also stark von den eigenen Anforderungen ab. Und schlussendlich muss man bedenken, dass ein wesentlicher Bestandteil im System, nämlich die VoIP Server Software, mit Asterisk in einer freien Open-Source-Lösung existiert.<br />
Ist das System einmal im Einsatz bietet es je nach VoIP-Provider günstige Tarife ins Festnetz sowie gratis Telefonie über das Internet.</p>
<p>Links:<br />
<a href="http://www.asterisk.org/">Asterisk</a><br />
<a href="http://www.asteriskguru.com/tools/bandwidth_calculator.php">Bandbreiten-Rechner</a></p>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/der-richtige-voip-client/" rel="bookmark">Der richtige VoIP-Client</a></li>
		<li><a href="http://www.loremipsum.at/blog/git-as-a-server/" rel="bookmark">Git as a Server</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/der-eigene-javascript-event-handler/" rel="bookmark">Der eigene Javascript Event Handler</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/technik/der-eigene-voip-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

