<?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; Code</title>
	<atom:link href="http://www.loremipsum.at/kategorie/blog/code/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>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>Magento: Verschiedene Preise in StoreViews</title>
		<link>http://www.loremipsum.at/blog/code/magento-verschiedene-preise-in-storeviews/</link>
		<comments>http://www.loremipsum.at/blog/code/magento-verschiedene-preise-in-storeviews/#comments</comments>
		<pubDate>Fri, 26 Aug 2011 09:55:51 +0000</pubDate>
		<dc:creator>Peter Hasitschka</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Plugin]]></category>
		<category><![CDATA[price]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=2730</guid>
		<description><![CDATA[Magentos Shop-Hierarchie ist in 3 Ebenen aufgebaut: Website &#8211; Store &#8211; StoreView. Letztere wird im Allgemeinen dazu verwendet, um mehrere Sprachen auf einen Shop anzuwenden. Je nach Einstellung können Felder global oder StoreView-spezifisch gesetzt werden. Außerdem kann man ohne Probleme &#8230; <a href="http://www.loremipsum.at/blog/code/magento-verschiedene-preise-in-storeviews/">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/rundungsfehler-in-magento-beheben/" rel="bookmark">Rundungsfehler in Magento beheben</a></li>
		<li><a href="http://www.loremipsum.at/blog/datenschutz/facebook-connect-in-magento-shops/" rel="bookmark">Facebook-Connect in Magento-Shops</a></li>
		<li><a href="http://www.loremipsum.at/blog/technik/magento-suche-mit-kurzer-zeichenlange/" rel="bookmark">Magento: Suche mit kurzer Zeichenlänge</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Magentos Shop-Hierarchie ist in 3 Ebenen aufgebaut: Website &#8211; Store &#8211; StoreView. Letztere wird im Allgemeinen dazu verwendet, um mehrere Sprachen auf einen Shop anzuwenden. Je nach Einstellung können Felder global oder StoreView-spezifisch gesetzt werden. Außerdem kann man ohne Probleme verschiedene Währungen angeben.</p>
<p>Unser Kunde hatte jedoch den Wunsch, für ein spezielles Land eigene Preise festsetzen zu können. Leider bietet Magento out-of-the-box keine Möglichkeit das Preisattribut auf StoreView Ebene zu setzen, sondern nur global.</p>
<p>Abhilfe bietet das Modul <strong>Store Price</strong>[1] von <strong>ZenPrint</strong>. Es wandelt den Preis, der in der Datenbank als Decimal-Attribut gespeichert ist, von einem fixen globalen Attribut in ein frei wählbares um. Es lässt sich über Magento Connect Version 1.0 installieren, bzw. in neueren Magento Versionen problemlos manuell einspielen.</p>
<p>Nach der Installation muss das Attribut unter <strong>System->Configuration->Catalog->Catalog</strong> noch auf die StoreView Ebene gesetzt werden (Siehe Screenshot).</p>
<div id="attachment_2732" class="wp-caption alignright" style="width: 180px"><a href="http://www.loremipsum.at/wp-content/uploads/2011/08/Magento-Config-Store-Price.png"><img class="size-thumbnail wp-image-2732" title="Aktivieren des Store Price Moduls" src="http://www.loremipsum.at/wp-content/uploads/2011/08/Magento-Config-Store-Price-170x89.png" alt="Aktivieren des Store Price Moduls" width="170" height="89" /></a><p class="wp-caption-text">Aktivieren des Store Price Moduls</p></div>
<p>Nun können beim Wechsel des Store Views in der Backend-Produktansicht verschiedene Preise eingegeben werden.</p>
<div class="mceTemp" style="text-align: right;">
<dl id="attachment_2737" class="wp-caption alignright" style="width: 310px;">
<dt class="wp-caption-dt"><a href="http://www.loremipsum.at/wp-content/uploads/2011/08/Magento-be-Store-Price.png"><img class="size-medium wp-image-2737 " title="Store View spezifischer Preis" src="http://www.loremipsum.at/wp-content/uploads/2011/08/Magento-be-Store-Price-300x39.png" alt="Store View spezifischer Preis" width="300" height="39" /></a></dt>
<dd class="wp-caption-dd">Store View spezifischer Preis</dd>
</dl>
</div>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><strong>BugFix</strong>: Falls im Frontend die Preise in der Kategorieansicht plötzlich als SpecialPrices erscheinen muss noch schnell ins Template eingegriffen werden:<br />
Unter <strong>app\design\frontend\[path_to_templates]\template\catalog\product\price.phtml</strong> findet man etwa in <strong>Zeile 43</strong> folgenden Code:</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"><span style="color: #000088;">$_product</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getProduct</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Diesen erweitert man um eine weitere Zeile, die das Produkt vollständig lädt:</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;">$_product</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;;</span>getProduct<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$_product</span> <span style="color: #339933;">=</span> Mage<span style="color: #339933;">::</span><span style="color: #004000;">getModel</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'catalog/product'</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #339933;">-&gt;</span><span style="color: #004000;">load</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_product</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<p>Schlussendlich sind im Frontend für jeden StoreView respektive Sprache verschiedene Preise verfügbar.</p>
<div style="float: left; width: 100%;">
<div style='float:left; width:100%'>
<div id="attachment_2739" class="wp-caption alignleft" style="width: 180px"><a href="http://www.loremipsum.at/wp-content/uploads/2011/08/magento-prod1-storeprice.png"><img class="size-thumbnail wp-image-2739" title="Preis im StoreView 1" src="http://www.loremipsum.at/wp-content/uploads/2011/08/magento-prod1-storeprice-170x91.png" alt="Preis im StoreView 1" width="170" height="91" /></a><p class="wp-caption-text">Preis im StoreView 1</p></div> <div id="attachment_2740" class="wp-caption alignright" style="width: 180px"><a href="http://www.loremipsum.at/wp-content/uploads/2011/08/magento-prod2-storeprice.png"><img class="size-thumbnail wp-image-2740" title="Preis im StoreView 2" src="http://www.loremipsum.at/wp-content/uploads/2011/08/magento-prod2-storeprice-170x92.png" alt="Preis im StoreView 2" width="170" height="92" /></a><p class="wp-caption-text">Preis im StoreView 2</p></div></div>
<p>&nbsp;</p>
<h2>Links:</h2>
<p>[1] <a href="http://www.magentocommerce.com/magento-connect/bott/extension/976/zenprint-store-price">http://www.magentocommerce.com/magento-connect/bott/extension/976/zenprint-store-price</a></p>
</div>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/code/rundungsfehler-in-magento-beheben/" rel="bookmark">Rundungsfehler in Magento beheben</a></li>
		<li><a href="http://www.loremipsum.at/blog/datenschutz/facebook-connect-in-magento-shops/" rel="bookmark">Facebook-Connect in Magento-Shops</a></li>
		<li><a href="http://www.loremipsum.at/blog/technik/magento-suche-mit-kurzer-zeichenlange/" rel="bookmark">Magento: Suche mit kurzer Zeichenlänge</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/code/magento-verschiedene-preise-in-storeviews/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress 3.1 Pluginbugfixing bei Kategorielinks</title>
		<link>http://www.loremipsum.at/blog/code/wordpress-3-1-pluginbugfixing-bei-kategorielinks/</link>
		<comments>http://www.loremipsum.at/blog/code/wordpress-3-1-pluginbugfixing-bei-kategorielinks/#comments</comments>
		<pubDate>Thu, 24 Feb 2011 21:43:58 +0000</pubDate>
		<dc:creator>Ing. Karl Kowald</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Bugfix]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Plugins]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=2627</guid>
		<description><![CDATA[Seit gestern wird WordPress 3.1 als stable ausgeliefert, jedoch scheinen einige Plugin-Anbieter ihre Software nicht damit vorabgetestet zu haben, denn bei einigen treten seltsame Fehler auf, betreffend der mod_rewrite-Funktion für sprechende URL&#8217;s und Kategorielinks Kategorielinks verweisen auf Artikel oder 404-Fehlerseite &#8230; <a href="http://www.loremipsum.at/blog/code/wordpress-3-1-pluginbugfixing-bei-kategorielinks/">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/wordpress-plugins/" rel="bookmark">WordPress Plugins</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/wordpress-3-0-upgrade-sinnvoll/" rel="bookmark">WordPress 3.0 &#8211; Upgrade sinnvoll?</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Seit gestern wird WordPress 3.1 als stable ausgeliefert, jedoch scheinen einige Plugin-Anbieter ihre Software nicht damit vorabgetestet zu haben, denn bei einigen treten seltsame Fehler auf, betreffend der mod_rewrite-Funktion für sprechende URL&#8217;s und Kategorielinks<span id="more-2627"></span></p>
<h2>Kategorielinks verweisen auf Artikel oder 404-Fehlerseite</h2>
<p>Ob man ein Plugin mit solch einen Fehler hat bemerkt man eigentlich sehr einfach. Klickt man auf einen Kategorielink und wird automatisch auf einen Artikel der Kategorie oder eine 404 Fehlerseite weitergeleitet, anstatt in der schönen Kategorieübersicht zu landen hat man ein nicht kompatibles Plugin dabei.</p>
<h2>1 Zeile auskommentieren als Sofortmaßnahme</h2>
<p>Erstaunlicherweise lässt sich das in den meisten Fällen jedoch recht einfach lösen. Einfach nach folgender Zeile suchen:</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"><span style="color: #000088;">$wp_rewrite</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">flush_rules</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p><strong>Diese Zeile</strong> einfach <strong>auskommentieren oder löschen</strong> und schon funktionieren die Kategorielinks wieder korrekt. <strong>Trotz</strong> dieses <strong>Eingriffs funktionieren</strong> die <strong>Plugins</strong> alle noch <strong>korrekt</strong> (bisher 3 Plugins auf diese Art bearbeitet). Dies ist zwar keine sinnvolle Dauerlösung, jedoch werden in den nächsten Tagen und Wochen die meisten Pluginentwickler adequate, getestete Lösungen via Updates nachreichen.</p>
<h2>Betroffene Plugins via Linux-Shell finden</h2>
<p>Betreiber von Blogs mit sehr vielen Plugins können mit diesem Aufruf in der Linuxshell rasch und effizient herausfinden in welche Plugins von diesem Problem betroffen sind.</p>
<div class="codecolorer-container c 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="c codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">grep <span style="color: #339933;">-</span>rl <span style="color: #ff0000;">'flush_rules'</span> <span style="color: #339933;">/</span>pathtowordpress<span style="color: #339933;">/</span>wp<span style="color: #339933;">-</span>content<span style="color: #339933;">/</span>plugins<span style="color: #339933;">/</span></div></td></tr></tbody></table></div>
<p>Mit diesem Aufruf erhält man eine Liste betroffener Dateien zurück, dort muss nur noch der entsprechende Eintrag auskommentiert werden.</p>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/produkte/wordpress-plugins/" rel="bookmark">WordPress Plugins</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/wordpress-3-0-upgrade-sinnvoll/" rel="bookmark">WordPress 3.0 &#8211; Upgrade sinnvoll?</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/code/wordpress-3-1-pluginbugfixing-bei-kategorielinks/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>WordPress Adminbar für Usergruppen global deaktivieren</title>
		<link>http://www.loremipsum.at/blog/code/wordpress-adminbar-fur-usergruppen-global-deaktivieren/</link>
		<comments>http://www.loremipsum.at/blog/code/wordpress-adminbar-fur-usergruppen-global-deaktivieren/#comments</comments>
		<pubDate>Wed, 23 Feb 2011 19:30:25 +0000</pubDate>
		<dc:creator>Ing. Karl Kowald</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Technik]]></category>
		<category><![CDATA[AdminBar]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=2618</guid>
		<description><![CDATA[Seit heute ist WordPress in der Version 3.1 veröffentlicht. Mit diesem Release kam unter anderem ein Feature namens Adminbar, für Benutzer von wordpress.com bereits eine bekannte Kopfleiste im Frontend von WordPress um schneller Backendfunktionen auch im Frontend nutzen zu können. &#8230; <a href="http://www.loremipsum.at/blog/code/wordpress-adminbar-fur-usergruppen-global-deaktivieren/">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/wordpress-plugins/" rel="bookmark">WordPress Plugins</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/wordpress-3-0-upgrade-sinnvoll/" rel="bookmark">WordPress 3.0 &#8211; Upgrade sinnvoll?</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Seit heute ist WordPress in der Version 3.1 veröffentlicht. Mit diesem Release kam unter anderem ein Feature namens Adminbar, für Benutzer von wordpress.com bereits eine bekannte Kopfleiste im Frontend von WordPress um schneller Backendfunktionen auch im Frontend nutzen zu können.</p>
<h2>Adminbar für registrierte Benutzer global deaktivieren</h2>
<p>Grundsätzlich eine sinnvolle Sache für Admins und Redakteure, jedoch für registrierte Leser meist unnötig und nicht ins Designkonzept passend. Mit einem kleinen aber feinen Eintrag in der functions.php des aktivierten Designs kann man dem aber Abhilfe schaffen &#8211; alternativ kann man das natürlich auch via Plugin aktivieren:</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: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>current_user_can<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'edit_posts'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
add_filter<span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'show_admin_bar'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'__return_false'</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>Mit diesen Zweizeiler kann man auf einfachste Weise die Adminbar für gewisse Usergruppen deaktivieren. In diesem Beispiel gilt das nur für registrierte Benutzer, da diese die einzige Gruppe ist, die keine Artikel editieren kann.</p>
<div id="_mcePaste" class="mcePaste" style="position: absolute; left: -10000px; top: 0px; width: 1px; height: 1px; overflow: hidden;">edit_posts</div>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/produkte/wordpress-plugins/" rel="bookmark">WordPress Plugins</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/wordpress-3-0-upgrade-sinnvoll/" rel="bookmark">WordPress 3.0 &#8211; Upgrade sinnvoll?</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/code/wordpress-adminbar-fur-usergruppen-global-deaktivieren/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Neues WordPress Plugin: Affiliando Vergleichsrechner 1.0</title>
		<link>http://www.loremipsum.at/blog/sem/neues-wordpress-plugin-affiliando-vergleichsrechner-1-0/</link>
		<comments>http://www.loremipsum.at/blog/sem/neues-wordpress-plugin-affiliando-vergleichsrechner-1-0/#comments</comments>
		<pubDate>Mon, 17 Jan 2011 19:55:47 +0000</pubDate>
		<dc:creator>Ing. Karl Kowald</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[SEM]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=2250</guid>
		<description><![CDATA[Seit heute ist unser neues WordPress-Plugin, der Affiliando Vergleichsrechner für WP auch direkt unter wordpress.org verfügbar. Damit können auch Updates der Software nun für einfachen Klick übernommen werden. Wozu das Plugin? Das Plugin integriert die PHP-Include-Version des Affiliando Vergleichsrechners mittels &#8230; <a href="http://www.loremipsum.at/blog/sem/neues-wordpress-plugin-affiliando-vergleichsrechner-1-0/">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/wordpress-plugins/affiliando-vergleichsrechner/" rel="bookmark">Affiliando Vergleichsrechner</a></li>
		<li><a href="http://www.loremipsum.at/produkte/wordpress-plugins/" rel="bookmark">WordPress Plugins</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/anti-spam-plugin-fur-wp-kommentare/" rel="bookmark">Anti-Spam Plugin für WP Kommentare</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Seit heute ist unser neues WordPress-Plugin, der <a href="http://www.loremipsum.at/produkte/wordpress-plugins/affiliando-vergleichsrechner/">Affiliando Vergleichsrechner für WP</a> auch direkt unter wordpress.org verfügbar. Damit können auch Updates der Software nun für einfachen Klick übernommen werden.</p>
<h3>Wozu das Plugin?</h3>
<p>Das Plugin integriert die PHP-Include-Version des Affiliando Vergleichsrechners mittels Shortcode auf jede beliebige WordPress-Seite. Zusätzlich cached das Plugin alle Dateien und Bilder lokal, sodass sowohl die Besucher als auch Suchmaschinen keine Daten mehr von einer fremden Domain nachladen müssen (Ladezeitverbesserung und SEO-Verbesserung).</p>
<h3>Das Plugin ist Gratis?</h3>
<p>Natürlich stellen wir das Plugin kostenlos zur Verfügung. Der Vergleich selbst stammt weiterhin aus der Feder des Affiliandobetreibers Zieltraffic, nur die spezielle WordPress-Integration ist von uns hinzugefügt worden. Updates von Zieltraffic für den Rechner werden wir natürlich zeitnah integrieren damit das Plugin jederzeit ready2use ist. Wenn euch das Plugin gefällt freuen wir uns natürlich über Danksagungen und Verlinkungen zu uns <img src='http://www.loremipsum.at/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/produkte/wordpress-plugins/affiliando-vergleichsrechner/" rel="bookmark">Affiliando Vergleichsrechner</a></li>
		<li><a href="http://www.loremipsum.at/produkte/wordpress-plugins/" rel="bookmark">WordPress Plugins</a></li>
		<li><a href="http://www.loremipsum.at/blog/code/anti-spam-plugin-fur-wp-kommentare/" rel="bookmark">Anti-Spam Plugin für WP Kommentare</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/sem/neues-wordpress-plugin-affiliando-vergleichsrechner-1-0/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>Rundungsfehler in Magento beheben</title>
		<link>http://www.loremipsum.at/blog/code/rundungsfehler-in-magento-beheben/</link>
		<comments>http://www.loremipsum.at/blog/code/rundungsfehler-in-magento-beheben/#comments</comments>
		<pubDate>Fri, 26 Nov 2010 12:37:47 +0000</pubDate>
		<dc:creator>Peter Hasitschka</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[Bugfix]]></category>
		<category><![CDATA[Magento]]></category>
		<category><![CDATA[Shop]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=1613</guid>
		<description><![CDATA[In Magento (1.4 oder älter), das als mächtiges Online-Shop-System bekannt ist, kann in verschiedenen Fällen ein unangenehmer Rundungsfehler aufscheinen, der sich aber leicht beheben lässt: Anmerkung: Um den Core unberührt zu lassen, empfiehlt es sich, die geänderten Files in der &#8230; <a href="http://www.loremipsum.at/blog/code/rundungsfehler-in-magento-beheben/">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/magento-verschiedene-preise-in-storeviews/" rel="bookmark">Magento: Verschiedene Preise in StoreViews</a></li>
		<li><a href="http://www.loremipsum.at/blog/technik/magento-suche-mit-kurzer-zeichenlange/" rel="bookmark">Magento: Suche mit kurzer Zeichenlänge</a></li>
		<li><a href="http://www.loremipsum.at/blog/datenschutz/facebook-connect-in-magento-shops/" rel="bookmark">Facebook-Connect in Magento-Shops</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>In Magento (1.4 oder älter), das als mächtiges Online-Shop-System bekannt ist, kann in verschiedenen Fällen ein unangenehmer Rundungsfehler aufscheinen, der sich aber leicht beheben lässt:</p>
<p><a href="http://loremipsum.at/wp-content/uploads/2010/11/magento_chicklets_02.png"><img class="alignright size-full wp-image-1623" title="Magento Logo" src="http://loremipsum.at/wp-content/uploads/2010/11/magento_chicklets_02.png" alt="" width="101" height="89" /></a>Anmerkung: Um den Core unberührt zu lassen, empfiehlt es sich, die geänderten Files in der gleichen Struktur in Ordner Local abzuspeichern.</p>
<p>Die beiden Änderungen bewirken eine genauere Rundung von Zahlen. Bei der bisherigen Rundung kann es bei der Aufsummierung von Zahlen zu einem Ungenauigkeitsfehler kommen, da sich die Rundung auf zwei Nachkommastellen beschränkt.<br />
Mit den Änderungen rundet Magento auf vier Stellen genau &#8211; Dadurch werden obige Fehler vermieden.</p>
<p>Folgende Änderungen sind durchzuführen:</p>
<p>Erstellen Sie Duplikat  der Datei:<br />
<strong>/app/code/core/Mage/Core/Model/Store.php</strong><br />
und fügen Sie das Duplikat in folgendem Pfad ein:<br />
<strong>/app/code/local/Mage/Core/Model/Store.php</strong></p>
<p>Die Änderung betrifft die Zeile 715 der Datei:</p>
<p><code class="codecolorer php geshi"><span class="php"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> roundPrice<span style="color: #009900;">&#40;</span><span style="color: #000088;">$price</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
<span style="color: #b1b100;">return</span> <span style="color: #990000;">round</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$price</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></span></code></p>
<p>Erstellen Sie Duplikat  der Datei:<br />
<strong>/app/code/core/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/Price.php</strong><br />
und fügen Sie das Duplikat in folgendem Pfad ein:<br />
<strong>/app/code/local/Mage/Adminhtml/Block/Catalog/Product/Helper/Form/Price.php</strong></p>
<p>Die Änderungen beginnen bei  Zeile: 78</p>
<p><code class="codecolorer php geshi"><span class="php"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getEscapedValue<span style="color: #009900;">&#40;</span><span style="color: #000088;">$index</span><span style="color: #339933;">=</span><span style="color: #009900; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
<span style="color: #000088;">$value</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getValue</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #990000;">is_numeric</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
<span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #b1b100;">return</span> <span style="color: #990000;">number_format</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">4</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">null</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></span></code></p>
<p>Beachten Sie, dass Sie niemals ein File bearbeiten sollten dass direkt in der Core-Struktur von Magento liegt. Die Core Files werden bei jedem Update von Magento überschrieben, sodass Änderungen nicht persistent sind. </p>
<p>Weiters sollten Sie speziell bei Systemen wie Magentocommerce eine genaue Dokumentation über geänderte / angelegte Files führen, um den Überblick zu behalten. Bei Magento &#8211; Versionssprüngen wie etwa von 1.3 auf 1.4 sind derartige Dokumentationen ein relevanter Zeitfaktor.</p>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/blog/code/magento-verschiedene-preise-in-storeviews/" rel="bookmark">Magento: Verschiedene Preise in StoreViews</a></li>
		<li><a href="http://www.loremipsum.at/blog/technik/magento-suche-mit-kurzer-zeichenlange/" rel="bookmark">Magento: Suche mit kurzer Zeichenlänge</a></li>
		<li><a href="http://www.loremipsum.at/blog/datenschutz/facebook-connect-in-magento-shops/" rel="bookmark">Facebook-Connect in Magento-Shops</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/code/rundungsfehler-in-magento-beheben/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>3 Schritte zur Keyword SERP-Position mit Google Analytics</title>
		<link>http://www.loremipsum.at/blog/sem/seo/3-schritte-zur-keyword-serp-position-mit-google-analytics/</link>
		<comments>http://www.loremipsum.at/blog/sem/seo/3-schritte-zur-keyword-serp-position-mit-google-analytics/#comments</comments>
		<pubDate>Thu, 30 Sep 2010 11:51:17 +0000</pubDate>
		<dc:creator>Ing. Karl Kowald</dc:creator>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[SEO]]></category>
		<category><![CDATA[Codeschnippsel]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Google Analytics]]></category>
		<category><![CDATA[Ranking]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.loremipsum.at/?p=953</guid>
		<description><![CDATA[Die Suchbegriffe mit welchen Besucher auf unsere Seite gelangen kann man problemlos mit Google Analytics auswerten. Will man jedoch auch die eigene Position auf der Suchmaschinenergebnisseite (SERP) wissen, welche zum Klick des Besuchers geführt hat, muss man schon selbst nach &#8230; <a href="http://www.loremipsum.at/blog/sem/seo/3-schritte-zur-keyword-serp-position-mit-google-analytics/">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/consulting/google-analytics-consulting/" rel="bookmark">Google Analytics Consulting</a></li>
		<li><a href="http://www.loremipsum.at/blog/sem/seo/google-bombing-der-weg-vom-spitzenkanditat-zum-vollkoffer/" rel="bookmark">Google-Bombing: Der Weg vom Spitzenkandidat zum Vollkoffer</a></li>
		<li><a href="http://www.loremipsum.at/blog/sem/seo/besserer-content-bessere-serp-platzierung/" rel="bookmark">Besserer Content = bessere SERP-Platzierung?</a></li>
	</ul></div>
]]></description>
			<content:encoded><![CDATA[<p>Die Suchbegriffe mit welchen Besucher auf unsere Seite gelangen kann man problemlos mit Google Analytics auswerten. Will man jedoch auch die eigene Position auf der Suchmaschinenergebnisseite (SERP) wissen, welche zum Klick des Besuchers geführt hat, muss man schon selbst nach dem Begriff googlen oder via Google WebmasterTools danach suchen. Leider gibt bei beiden Methoden Abweichungen die kein genaues Resultat ergeben, doch mit einer kleinen Änderung am Google Analytics Code kann dem abhilfe geschaffen werden.<span id="more-953"></span></p>
<h2>Schritt 1: Referer Auswerten</h2>
<p>Zuerst liest man einfach beim Seitenaufruf den Referer aus:</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 /></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;">&lt;?php</span> <span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/cd\=(\d+)/&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_REFERER'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$str</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
<span style="color: #990000;">preg_match</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/(\d+)/&quot;</span><span style="color: #339933;">,</span><span style="color: #000088;">$str</span><span style="color: #339933;">,</span><span style="color: #000088;">$matches</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$rank</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$matches</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></div></td></tr></tbody></table></div>
<p>Dadurch erhalten wir die Position auf der Google Suchergebnisseite von welcher der aktuelle Besucher kommt. Sollte die eigene Seite eventuell mit der $_GET Variable cd arbeiten wäre es Ratsam noch einen allgemeinen Filter über die Refererdomain laufen zu lassen um falsche Werte auszuschließen.</p>
<h2>Schritt 2: Wert an Google Analytics übergeben</h2>
<p>Hierfür nutzen wir die Möglichkeit via Javascript eigens definierte Variablen ans Google Analytics zu übergeben. Inmitten des Google-Codes fügen wir nun die Position mit einem eigenes kreierten Variablennamen &#8220;Google_Platz&#8221; ein, allerdings nur dann wenn auch tatsächlich ein Wert dafür vorhanden ist:</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 /></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;">&lt;?php</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$rank</span> <span style="color: #339933;">!=</span> <span style="color: #0000ff;">''</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #000000; font-weight: bold;">?&gt;</span>    _gaq.push(['_setCustomVar',1,'Google_Platz','<span style="color: #000000; font-weight: bold;">&lt;?=</span><span style="color: #000088;">$rank</span><span style="color: #339933;">;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>',2]);<br />
<span style="color: #000000; font-weight: bold;">&lt;?php</span><br />
<span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span></div></td></tr></tbody></table></div>
<p>Als Ergebnis sollte dann soetwas im Quellcode stehen:</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 /></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> _gaq <span style="color: #339933;">=</span> _gaq <span style="color: #339933;">||</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span><br />
_gaq.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'_setAccount'</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">'UA-xxxxxxxx-x'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
_gaq.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'_setCustomVar'</span><span style="color: #339933;">,</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span><span style="color: #3366CC;">'Google_Platz'</span><span style="color: #339933;">,</span><span style="color: #3366CC;">'3'</span><span style="color: #339933;">,</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
_gaq.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'_trackPageview'</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#40;</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 />
<span style="color: #003366; font-weight: bold;">var</span> ga <span style="color: #339933;">=</span> document.<span style="color: #660066;">createElement</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'script'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> ga.<span style="color: #660066;">type</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'text/javascript'</span><span style="color: #339933;">;</span> ga.<span style="color: #660066;">async</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
ga.<span style="color: #660066;">src</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'https:'</span> <span style="color: #339933;">==</span> document.<span style="color: #660066;">location</span>.<span style="color: #660066;">protocol</span> <span style="color: #339933;">?</span> <span style="color: #3366CC;">'https://ssl'</span> <span style="color: #339933;">:</span> <span style="color: #3366CC;">'http://www'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">'.google-analytics.com/ga.js'</span><span style="color: #339933;">;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> s <span style="color: #339933;">=</span> document.<span style="color: #660066;">getElementsByTagName</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'script'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span> s.<span style="color: #660066;">parentNode</span>.<span style="color: #660066;">insertBefore</span><span style="color: #009900;">&#40;</span>ga<span style="color: #339933;">,</span> s<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>In diesem Beispiel kam der Klick von der 3. Position.</p>
<h2>Schritt 3: Auswerten nach Platzierung</h2>
<div id="attachment_954" class="wp-caption alignright" style="width: 253px"><a href="http://loremipsum.at/wp-content/uploads/2010/09/google-positionszahl.jpg"><img class="size-medium wp-image-954" title="google-positionszahl" src="http://loremipsum.at/wp-content/uploads/2010/09/google-positionszahl-243x300.jpg" alt="Die Positionszahl die das Script übergibt" width="243" height="300" /></a><p class="wp-caption-text">Die Positionszahl die das Script übergibt</p></div>
<p>Nach einigen Tagen sollte man die ersten Ergebnisse bereits sehen und man kann mit der Auswertung beginnen. Leider werden eigene Variablen nicht standardmäßig von Google Analytics ausgewertet, weshalb man sich in die Benutzerdefierten Berichte wagen muss. Jedoch lohnt es sich, da man ab diesem Zeitpunkt wichtige Kennzahlen wie die Bounce-Rate oder Umsatzziele auch nach dem Ranking auswerten. Auch durchschnittliche Platzierungen von wichtigen Keywords kann man über einen langen Zeithorizont auswerten, wobei natürlich nur die Platzierungen bewertet werden, welche auch tatsächlich zu einem Besuch auf der Homepage geführt haben.</p>
<h2>WordPress Plugin mit dieser Funktion</h2>
<p>Wir arbeiten bereits seit einigen Tagen an einer kleinen Funktions- &amp; Effektsammlung für WordPress welches wir an dieser Stelle veröffentlichen möchten. Diese Auswertungsoption wird darin von ebenfalls integriert werden. Für alle die somit noch einige Tage darauf warten können ein Hinweis damit Sie es nicht selbst in ihrem Code einfügen müssen.</p>
<h2>Update: Auswertung nur mit Javascript</h2>
<p>Alternativ kann man auch eine reine Javascriptauswertung machen, dadurch erspart man sich den Eingriff in PHP-Files.</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 /></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: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>document.<span style="color: #660066;">referrer</span>.<span style="color: #660066;">search</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/[\?|&amp;]cd=/</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">1</span><br />
<span style="color: #339933;">&amp;&amp;</span> document.<span style="color: #660066;">referrer</span>.<span style="color: #660066;">search</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/google\./</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
<span style="color: #003366; font-weight: bold;">var</span> rank<span style="color: #339933;">=</span>document.<span style="color: #660066;">referrer</span>.<span style="color: #660066;">match</span><span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/[&amp;|\?]cd=([\d]+)/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
_gaq.<span style="color: #660066;">push</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #3366CC;">'_setCustomVar'</span><span style="color: #339933;">,</span><span style="color: #CC0000;">1</span><span style="color: #339933;">,</span><span style="color: #3366CC;">'Google_Platz'</span><span style="color: #339933;">,</span>rank<span style="color: #009900;">&#91;</span><span style="color: #CC0000;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><span style="color: #CC0000;">2</span><span style="color: #009900;">&#93;</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>
<div class="related"> 						<span class="hash">Verwandte Themen und Beitr&auml;ge</span>  						<ul>
		<li><a href="http://www.loremipsum.at/consulting/google-analytics-consulting/" rel="bookmark">Google Analytics Consulting</a></li>
		<li><a href="http://www.loremipsum.at/blog/sem/seo/google-bombing-der-weg-vom-spitzenkanditat-zum-vollkoffer/" rel="bookmark">Google-Bombing: Der Weg vom Spitzenkandidat zum Vollkoffer</a></li>
		<li><a href="http://www.loremipsum.at/blog/sem/seo/besserer-content-bessere-serp-platzierung/" rel="bookmark">Besserer Content = bessere SERP-Platzierung?</a></li>
	</ul></div>
]]></content:encoded>
			<wfw:commentRss>http://www.loremipsum.at/blog/sem/seo/3-schritte-zur-keyword-serp-position-mit-google-analytics/feed/</wfw:commentRss>
		<slash:comments>4</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>
	</channel>
</rss>

