<?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>kj187</title>
	<atom:link href="http://blog.kj187.de/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.kj187.de</link>
	<description>Blog von Julian Kleinhans</description>
	<lastBuildDate>Mon, 28 Jun 2010 09:42:21 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>TYPO3 Agentur &#8211; Bergisch Media</title>
		<link>http://blog.kj187.de/2010/06/28/typo3-agentur-bergisch-media/</link>
		<comments>http://blog.kj187.de/2010/06/28/typo3-agentur-bergisch-media/#comments</comments>
		<pubDate>Mon, 28 Jun 2010 09:40:41 +0000</pubDate>
		<dc:creator>Julian Kleinhans</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[Privat]]></category>
		<category><![CDATA[TYPO3]]></category>

		<guid isPermaLink="false">http://blog.kj187.de/?p=251</guid>
		<description><![CDATA[Vor guten 2 Monaten hat es mich arbeitstechnisch zur TYPO3 Agentur Bergisch Media, die seit 2005 besteht und in Heiligenhaus ansässig ist, gezogen. Heute wird es Zeit mal einen ersten Eindruck dazu zu schreiben.
In den 2 Monaten habe ich mich relativ schnell eingelebt und fühle mich hier rundum pudelwohl! Nicht nur die Kollegen sind der [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.kj187.de/wp-content/uploads/2010/06/bmMediaLogo.gif"><img class="size-full wp-image-252 alignright colorbox-251" title="bmMediaLogo" src="http://blog.kj187.de/wp-content/uploads/2010/06/bmMediaLogo.gif" alt="" width="238" height="68" /></a>Vor guten 2 Monaten hat es mich arbeitstechnisch zur <a title="TYPO3 Agentur" href="http://www.bergisch-media.de" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.bergisch-media.de?referer=');">TYPO3 Agentur Bergisch Media</a>, die seit 2005 besteht und in Heiligenhaus ansässig ist, gezogen. Heute wird es Zeit mal einen ersten Eindruck dazu zu schreiben.</p>
<p>In den 2 Monaten habe ich mich relativ schnell eingelebt und fühle mich hier rundum pudelwohl! Nicht nur die Kollegen sind der hammer, auch die Projekte die mir anvertraut wurden sind äußerst interessant und bieten jede menge Herausforderungen. Auf Qualität wird hier umheimlich geachtet was die starke Kundenzufriedenheit denke ich auch ausmacht. Ich selbst bin ja seit knapp einem halben Jahr auf einem Qualitätstrip, daher ist mir dieser Aspekt hier ziemlich schnell und positiv aufgefallen.</p>
<p>Als TYPO3 Association Silver Member ist die Bergisch Media dieses Jahr mit 3 Mitarbeitern auf den TYPO3 Developer Days vertreten. Ich freue mich dann dort das erste mal für Bergisch Media unterwegs zu sein!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.kj187.de/2010/06/28/typo3-agentur-bergisch-media/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>t3n Gewinnspiel</title>
		<link>http://blog.kj187.de/2010/06/06/t3n-gewinnspiel/</link>
		<comments>http://blog.kj187.de/2010/06/06/t3n-gewinnspiel/#comments</comments>
		<pubDate>Sun, 06 Jun 2010 15:19:11 +0000</pubDate>
		<dc:creator>Julian Kleinhans</dc:creator>
				<category><![CDATA[Privat]]></category>

		<guid isPermaLink="false">http://blog.kj187.de/?p=239</guid>
		<description><![CDATA[Anlässlich des 20ten Jubiläums von t3n gibt es hier eine Verlosungsaktion! Kurz zu den Fakten: Zu gewinnen gibt es

1. Platz - Aktuelle Ausgabe des Magazins „Zukunft – leckere Webtrends“ + ein Open-Source T-Shirt. 2 + 3 Platz - Aktuelle Ausgabe des Magazins „Zukunft – leckere Webtrends“
]]></description>
			<content:encoded><![CDATA[<p>Anlässlich des 20ten Jubiläums von <a href="http://t3n.de" target="_blank" onclick="pageTracker._trackPageview('/outgoing/t3n.de?referer=');">t3n</a> gibt es hier eine Verlosungsaktion!<a href="http://blog.kj187.de/wp-content/uploads/2010/06/t3n-Cover_Nr20.jpg"><img class="alignright size-full wp-image-240 colorbox-239" title="t3n-Cover_Nr20" src="http://blog.kj187.de/wp-content/uploads/2010/06/t3n-Cover_Nr20.jpg" alt="" width="176" height="249" /></a><br />
Kurz zu den Fakten: Zu gewinnen gibt es</p>
<p><strong>1. Platz</strong><br />
Aktuelle Ausgabe des Magazins „Zukunft – leckere Webtrends“ + ein Open-Source T-Shirt</p>
<p><strong>2 + 3 Platz</strong><br />
Aktuelle Ausgabe des Magazins „Zukunft – leckere Webtrends“</p>
<p>Einen Einblick in die aktuelle Ausgabe gibt es <a href="http://t3n.de/app/to/db2e8032d8" target="_blank" onclick="pageTracker._trackPageview('/outgoing/t3n.de/app/to/db2e8032d8?referer=');">hier</a>!</p>
<p>Ok, wie könnt Ihr teilnehmen ? Das ist relativ einfach, hinerlasst hier einen Kommentar oder ein Track-/Pingback auf dieses Seite. Ich werde dann nach dem Zufallsprinzip die jeweiligen Gewinner bestimmen.<br />
Die Gewinne werden dann direkt von t3n versendet. Damit ich Kontakt zu den Gewinnern aufnehmen kann ist es wichtig das Ihr eine gültige E-Mail Adresse hinterlasst!</p>
<p>Den Gewinner des Platz 1. wird am 11.06 bestimmt und kontaktiert.<br />
Die Gewinner von Platz 2 und 3 werden am 18.06 bestimmt und kontaktiert.</p>
<p>Viel spass und glück :-)</p>
<p>PS: Wenn Ihr das Magazin dann habt, schenkt den Seiten 122/123 besonders Aufmerksamkeit&#8230; der Artikel ist von mir :-) &#8220;<strong>TYPO3 und AJAX</strong>&#8221;</p>
<p><strong>EDIT: Alle Gewinner wurden informiert! Damit ist das Gewinnspiel offiziell vorbei :-) Aber schon bald wird es ein neues geben!</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.kj187.de/2010/06/06/t3n-gewinnspiel/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>TYPO3 Developer Days 2010</title>
		<link>http://blog.kj187.de/2010/04/06/typo3-developer-days-2010/</link>
		<comments>http://blog.kj187.de/2010/04/06/typo3-developer-days-2010/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 20:07:11 +0000</pubDate>
		<dc:creator>Julian Kleinhans</dc:creator>
				<category><![CDATA[TYPO3]]></category>
		<category><![CDATA[T3DD10]]></category>

		<guid isPermaLink="false">http://blog.kj187.de/?p=226</guid>
		<description><![CDATA[Vor knapp 6 Tagen wurde die offizielle Anmeldung zu den TYPO3 Developer Days 2010 &#8211; T3DD10 &#8211; unter dem Motto &#8220;Getting things done&#8221; eröffnet. Es stehen rund 200 Tickets zur Verfügung wovon nach 1.5 Tagen schon knapp 50% weg waren. Der Ansturm ist also auch in diesem Jahr wieder enorm. Wie auch im letzten Jahr [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://t3dd10.typo3.org" onclick="pageTracker._trackPageview('/outgoing/t3dd10.typo3.org?referer=');"><img class="alignleft size-full wp-image-227 colorbox-226" title="T3DD10_AD_T3O" src="http://blog.kj187.de/wp-content/uploads/2010/04/T3DD10_AD_T3O.gif" alt="" width="180" height="120" /></a>Vor knapp 6 Tagen wurde die offizielle Anmeldung zu den TYPO3 Developer Days 2010 &#8211; T3DD10 &#8211; unter dem Motto &#8220;<strong>Getting things done</strong>&#8221; eröffnet. Es stehen rund 200 Tickets zur Verfügung wovon <a href="http://twitter.com/t3dd/statuses/11438890669" target="_blank" onclick="pageTracker._trackPageview('/outgoing/twitter.com/t3dd/statuses/11438890669?referer=');">nach 1.5 Tagen schon knapp 50% weg waren</a>. Der Ansturm ist also auch in diesem Jahr wieder enorm. Wie auch im letzten Jahr findet das Event im kleinen und netten <a href="http://de.wikipedia.org/wiki/Elmshorn" target="_blank" onclick="pageTracker._trackPageview('/outgoing/de.wikipedia.org/wiki/Elmshorn?referer=');">Elmshorn</a> vom 01 &#8211; 04 Juli in der nähe von Hamburg statt. Wer teilnehmen möchte sollte nicht lange überlegen und sich ein Ticket besorgen. Das ganze könnt Ihr Online auf der <a href="http://t3dd10.typo3.org" target="_blank" onclick="pageTracker._trackPageview('/outgoing/t3dd10.typo3.org?referer=');">offiziellen Event Seite</a> machen. Zu beachten ist, das es einen early bird gibt, der nur zum Vorteil für Association Mitglieder und und Studenten ist. Dieser geht bis zum 30.4. Danach senkt sich der reguläre Preis um knapp 100 €. Wer kein Association Member und kein Student ist und bedenken hat er bekommt kein Ticket mehr, sollte die 100 € investieren oder noch besser, <a href="http://association.typo3.org/membership/membership-registration/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/association.typo3.org/membership/membership-registration/?referer=');">Association Mitglied werden</a> :-) Achtet darauf das Ihr euch zusätzlich noch um eine Bleibe kümmern müsst, auch dazu findet Ihr Informationen auf der <a href="http://t3dd10.typo3.org/travel-hotel/hotel/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/t3dd10.typo3.org/travel-hotel/hotel/?referer=');">Event Seite</a>.</p>
<p>In diesem Jahr läuft alles unter dem Motto &#8220;Getting things done&#8221; was bedeuten wird, das es keine gewohnten Vorträge mehr gibt, sondern  eher Workshops. Jeder Workshop soll dabei auf maximal 20 Teilnehmer begrenzt werden und knapp 4 Stunden gehen. Es soll jeweils 3 verschiedene Worksphops parallel ablaufen.</p>
<p>Ich werde da sein und bestimmt den ein und anderen Blog Eintrag live aus Elmshorn posten!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.kj187.de/2010/04/06/typo3-developer-days-2010/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Exception Handling</title>
		<link>http://blog.kj187.de/2010/03/22/exception-handling/</link>
		<comments>http://blog.kj187.de/2010/03/22/exception-handling/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 07:36:39 +0000</pubDate>
		<dc:creator>Julian Kleinhans</dc:creator>
				<category><![CDATA[OOP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Ausnahmezustand]]></category>
		<category><![CDATA[Error]]></category>
		<category><![CDATA[Exception Handling]]></category>

		<guid isPermaLink="false">http://blog.kj187.de/?p=199</guid>
		<description><![CDATA[Exceptions sind Ausnahmezustände die eine Möglichkeit bieten auf verschiedene kritische Bedingungen bzw. Fehler während des Programmablaufs zu reagieren. Mit diesem Artikel möchte ich euch eine kleine Einführung in die Welt des Exception Handlings geben. Speziell gewidmet für meinen Arbeitskollegen David, der sich dieses Thema als Blogartikel von mir gewünscht hat.]]></description>
			<content:encoded><![CDATA[<p>Diesen Artikel über Exception Handling widme ich meinem Arbeitskollegen David der sich dieses Thema von mir gewünscht hat :-)</p>
<p>Wollen wir auch sofort zum Thema kommen! Um es in einem Satz zu sagen: Exceptions sind Ausnahmezustände die eine Möglichkeit bieten auf verschiedene kritische Bedingungen bzw. Fehler während des Programmablaufs zu reagieren. BAM!</p>
<p>Geschnallt ? :-)  Wenn nicht, nicht schlimm! Der Artikel fängt ja jetzt erst richtig an!</p>
<p>Um bei meiner lieblings Sprache zu bleiben, das Exception Handling gibt es in PHP erst seit der Version 5. Dort ist Sie standardmäßig dabei! Es muss also nix installiert, konfiguriert oder aktiviert werden! Wenn Ihr also noch mit PHP 4 arbeitet, leuteee, geht mit der Zeit :-)</p>
<p>Ok, das Exception Handling bietet uns also eine Möglichkeit! Wie sieht diese Möglichkeit aus? In PHP und auch in andere Sprachen gibt es das try und catch Konstrukt. Mit throw werfen wir einen Fehler und mit catch fangen wir diesen Fehler und können entsprechend auf diesen reagieren! Um das Fangen von Exceptions zu ermöglichen, muss der jeweilige Code in dem wir einen Fehler vermuten würden in einem try Block umschlossen werden. Dabei muss jeder try Block mindestens einen catch Block besitzen! Mehrere catch Blöcke sind dabei natürlich zu genaueren Filterung von Fehlern möglich.</p>
<p>Damit wir uns das ein bischen besser vorstellen können gibts dazu auch direkt ein Beispiel</p>
<pre class="brush: php;">class TestClass {
    public function sayHello($name) {
        if (!$name) {
            throw new Exception('Der Name fehlt!');
        } else {
            echo 'Hello ' . $name;
        }
    }
}

$object = new TestClass;

try {
    $object-&gt;sayHello('Julian');
    $object-&gt;sayHello('');
    $object-&gt;sayHello('David');
} catch (Exception $error) {
    echo 'Exception abgefangen: ' . $error-&gt;getMessage();
}

echo 'Schönen Tag wünsche ich!';</pre>
<p>Wir haben also eine Klasse TestClass. Diese besitzt eine Methode sayHello die uns freundlicherweise begrüßt wenn wir Ihr als Parameter einen Namen mit übergeben. Nette Methode oder ? Doch wenn wir Ihr unseren Namen nicht veraten ist das recht unfreundlich, daher wird Sie uns auch nicht Hallo sagen sondern wird mit einem Fehler schmeißen und uns darauf aufmerksam machen wollen!</p>
<p>Wir instanzieren also ein Objekt der Klasse TestClass. Dann kommt der try Block in dem wir unseren Code schreiben in dem wir evtl einen Fehler vermuten würden. Wir rufen die Methode sayHello auf und übergeben Ihr einen Namen &#8220;Julian&#8221;. &#8220;Julian&#8221;, in dem Fall ich, wird begrüßt! Dann rufen wir die Methode auf vergessen Ihr aber unseren Namen zu sagen! Oh Oh&#8230; Was macht die Methode, Sie wirft per throw eine Exception! Unser try catch Block bekommt davon sofort Wind und fängt diesen Fehler per catch ab!</p>
<p>Wie sieht unsere Ausgabe eigentlich aus ?</p>
<p>Hello Julian<br />
Exception abgefangen: Der Name fehlt!<br />
Schönen Tag wünsche ich!</p>
<p>Aber hey, ich habe nachdem ich bemerkt habe das ich meinen Namen vergessen hab doch direkt einen weiteren Aufruf hingeknallt! Warum wird David also nicht begrüßt ? Das ist ganz einfach! Nachdem in einem try Block eine Exception geworfen wurde wird innerherhalb des try Blocks nichts mehr ausgeführt! Der try Block wird also sofort verlassen und der rest des Scripts wird ausgeführt, daher wird uns also noch ein schöner Tag gewünscht!</p>
<p>Gut das Beispiel ist etwas blöd um den Sinn hinter dem Exception Handling zu demonstieren weil in diesem Beispiel hätten wir ja auch alles einfach über eine if else Bedingung steuern können. Exception Handling ist eigentlich auch nichts anderes wenn man es man grob betrachtet. Aber es bringt doch etliche Vorteile mit! Man braucht sich nicht mehr um Rückgabewerte kümmern, man schmeisst per throw einfach den Fehler! In etwas komplexeren Szenen kommt dort der Sinn und Zweck schon deutlich zum Vorschein! Würdet Ihr mit dem if Konstrukt arbeiten würdet Ihr sehr schnell in einem tiefen verschachtelten Dschungel landen :-)</p>
<p>Wollt Ihr verschiedene Arten von Fehlern behandeln, empfiehlt es sich, mit unterschiedlichen Fehlerklassen zu arbeiten. Höö?<br />
Ja Ihr werdet staunen, aber wir können sehr einfach eigene Exception Klassen erstellen. Beispiel:</p>
<pre class="brush: php;">class unfreundlicherUser extends Exception {
    public function __construct($message) {
        parent::__construct($message);
    }
}</pre>
<p>Wichtig dabei ist das a) unsere Klasse von der Basisklasse Exception erbt und b) das wir einen Konstruktor definieren damit die Fehlermeldung aufgenommen werden kann!<br />
Unseren obigen Code könnten wir also wie folgt ändern, Ausgangsbasis ist, das uns der User verarschen will und einfach ein &#8220;x&#8221; eingibt weil er weiss das er was übergeben muss! Aber unser Programm soll auf eine Eingabe von einem &#8220;x&#8221; mit einem Fehler um sich schmeißen :-)</p>
<pre class="brush: php;">class TestClass {

    public function sayHello($name) {
        if (!$name) {
            throw new Exception('Der Name fehlt!');
        } elseif ('x' === $name) {
            throw new unfreundlicherUser('Ah Mr. X will uns seinen Namen nicht veraten!');
        } else {
            echo 'Hello ' . $name;
        }
    }

}

$object = new TestClass;

try {
    $object-&gt;sayHello('Julian');
    $object-&gt;sayHello('x');
} catch (Exception $error) {
    echo 'Exception abgefangen: ' . $error-&gt;getMessage();
} catch (unfreundlicherUser $error) {
    echo 'Exception abgefangen: ' . $error-&gt;getMessage();
}

$object-&gt;sayHello('David');</pre>
<p>Wie wir sehen hat sich der Code erweitert. In der Methode sayHello wurde die Abfrage eingebaut wo der Name mit dem &#8220;x&#8221; verglichen wird. Hat der User also nur ein &#8220;x&#8221; eingegeben wird eine Exception vom Typ unfreundlichenUser geschmissen die wir vorher selbst definiert haben. An unseren ersten catch Block haben wir einen weiteren gehangen in dem die Fehler vom Typ unfreundlichenUser gefangen werden.</p>
<p>Ist doch super! Wir können also auf alle verschiedenen Fehler verschiedenen reagieren!</p>
<p>In unserem catch Block haben wir nebem getMessage noch mehrere Methoden die uns zur Verfügung stehen.<br />
Darunter zählen</p>
<p>- getCode() zur Ausgabe eines Fehlercodes<br />
- getFile() zur Ausgabe des Dateinamens in dem der Fehler geschmissen wurde<br />
- getLine() die Zeile in dem der Fehler geschmissen wurde<br />
- getTrace() liefert ein Array mit dem Stacktrace<br />
- getTraceAsString() liefert den Stacktrace nicht als Array sondern als String</p>
<p>Wir sehen, es stehen uns reichlich Mittel zur Verfügung um auf jeden Fehler zu reagieren!</p>
<p>Ich hoffe mein Kollege David konnte sich mit dem Thema Exceptions jetzt ein wenig anfreunden und wird es in Zukunft in allen Projekten einsetzen :-)<br />
Ich bin gespannt hehe&#8230; und euch hat es hoffentlich auch gefallen! Ein Kommentar und eine Bewertung hier unten würde mich wie immer freuen!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.kj187.de/2010/03/22/exception-handling/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>MySQL Optimierung</title>
		<link>http://blog.kj187.de/2010/03/16/mysql-optimierung/</link>
		<comments>http://blog.kj187.de/2010/03/16/mysql-optimierung/#comments</comments>
		<pubDate>Tue, 16 Mar 2010 20:30:49 +0000</pubDate>
		<dc:creator>Julian Kleinhans</dc:creator>
				<category><![CDATA[Best practices]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Datenbank]]></category>
		<category><![CDATA[MySQL Optimierung]]></category>

		<guid isPermaLink="false">http://blog.kj187.de/?p=167</guid>
		<description><![CDATA[MySQL, es gehört zum Alltag eines jeden Webprogrammierers!
 Doch viele wissen nicht, bzw. achten nicht darauf, das man mit falschen Querys starke Perfomanceeinbußen fahren kann.
 Daher will ich euch ein paar Best Practices mit auf den Weg geben, die grundsätzlich für eine bessere Performance sorgen!]]></description>
			<content:encoded><![CDATA[<p><strong>MySQL</strong>, es gehört zum Alltag eines jeden Webprogrammierers!<br />
Doch viele wissen nicht, bzw. achten nicht darauf, das man mit falschen Querys starke Perfomanceeinbußen fahren kann.<br />
Daher will ich euch ein paar Best Practices mit auf den Weg geben, die grundsätzlich für eine bessere Performance sorgen!</p>
<p><strong>1) Vermeide SELECT * (sternchen)</strong></p>
<p>Über SELECT * werden <em>ALLE</em> Spalten einer Tabelle eingelesen! Aber nicht immer benötigt man wirklich alle Spalten aus einer Tabelle! Meißt benötigt man nur 2-3 Spalten wie den &#8220;title&#8221; oder die &#8220;id&#8221; und trotzem ist man zu faul die Spaltennamen auszuschreiben. Also knallen wir einfach mal das * (sternchen) hin, ist ja einfacher nicht wahr?! Jaha&#8230; nur bei einem * (sternchen) werden wie gesagt <em>ALLE</em> Spalten einer Tabelle eingelesen und das kostet Performance.<span id="more-167"></span></p>
<p>Benötigen wir also zum Beispiel aus einer Tabelle nur die Spalte &#8220;id&#8221; und &#8220;title&#8221; sollten wir unbedingt darauf achten auch nur diese beiden Spalten einzulesen:</p>
<pre class="brush: php;">// Nicht empfehlenswert
$result = mysql_query('SELECT * FROM tabelle WHERE id = 1');</pre>
<pre class="brush: php;">// Empfehlenswert
$result = mysql_query('SELECT id, title FROM tabelle WHERE id = 1');</pre>
<p><strong>2) Vermeide ORDER BY RAND()</strong></p>
<p>Ein sehr beliebtes Feature! Sie möchten auf Ihrer Webseite per Zufall &#8220;einen&#8221; Artikel aus Ihrer Tabelle darstellen!<br />
Was schreiben wir also, ganz easy:</p>
<pre class="brush: php;">$result = mysql_query('SELECT title FROM tabelle ORDER BY RAND() LIMIT 1');</pre>
<p>Sehr cool! Wir bekommen also per Zufall immer nur einen Artikel (eine Row), ganz wie wir es uns vorgestellt haben!<br />
Jedoch muss ich euch sagen, ORDER BY RANDOM() ernährt sich unheimlich gerne von unserer köstlichen und wertvollen Zutat namens Performance.  Wie also können wir unsere Abfrage so optimieren dass wir das gleiche Ergebnis bekommen ?</p>
<p>Ganz einfach, wir besorgen uns erstmal die Anzahl aller verfügbaren Zeilen, generieren uns dann eine Zufallszahl zwischen 0 und der Gesamtanzahl und nutzen LIMIT :-)</p>
<p>Moment, *taschenrechner.. klick klick*&#8230; hum, das sind ja jetzt mehr Zeilen als mein schöner Einzeiler da! Ja richtig, aber er frist garantiert nicht so viel Performance! Also, hier der Code:</p>
<pre class="brush: php;">$result = mysql_query('SELECT COUNT(*) FROM tabelle);
$row = mysql_fetch_row($result);
$randomizeNumber = mt_rand(0, $row[0]-1);
$result = mysql_query('SELECT title FROM tabelle LIMIT ' . $randomizeNumber . ', 1');</pre>
<p>Diese 4 Zeilen führen zum gleichen Ergebnis und sind nicht so Performancelastig.<br />
Hier wird gezielt per LIMIT nur eine Row gelesen. Bei ORDER BY RAND() werden erst ALLE Rows gelesen und dann erst per LIMIT begrenzt.</p>
<p><strong>3) Benutze LIMIT 1 bei eindeutigen Abfragen</strong></p>
<p>Es kommt sehr oft vor das wir genau wissen welche Zeile wir brauchen. Also schreibt man folgende Query</p>
<pre class="brush: php;">$result = mysql_query('SELECT title FROM tabelle WHERE title = &quot;Hello World&quot;');</pre>
<p>1 row in set (0.36 sec)</p>
<p>Wir wissen also daß wir nur eine Zeile zurückbekommen!<br />
Auch hier können wir ein minimale Performacesteigerung erzwingen, und wie ? Naja, wir wissen das es nur eine Zeile gibt, lasst uns also ein LIMIT 1 dran hängen:</p>
<pre class="brush: php;">$result = mysql_query('SELECT id, title, crdate FROM tabelle WHERE title = &quot;Hello World&quot; LIMIT 1');</pre>
<p>1 row in set (0.17 sec)</p>
<p>Auch wenn nicht wirklich spürbar, aber der Query ist schneller!<br />
Wenn wir nach einer Spalte suchen die einen Index hat, wie zB die Spalte id, diese ist ja unique, macht es keinen Sinn da über den Index das Ergebnis schon rasend schnell geliefert wird.</p>
<p><strong>4) Query Cache nutzen</strong></p>
<p>Seit MySQL Version 4 steht uns der MySQL Query Cache zur Verfügung der in den meisten Fällen unsere Abfragen beschleunigt. Vorausgesetzt ist natürlich das dieser aktiviert und konfiguriert ist! Die Betonung im ersten Satz liegt übrigens auf &#8220;in den meisten Fällen&#8221; ;-)</p>
<p>Was macht dieser Query Cache genau ?<br />
Hier werden Querys und deren Ergebnismengen abgespeichert. Wenn die gleiche Abfrage mehrmals benutzt wird und sich die betroffenen Datensätze nicht geändert haben, wird das Ergebnis aus diesem Cache geliefert anstatt eine neue Abfrage zu generieren.</p>
<p>Jetzt ist es so das wir als Programmierer eigentlich nichts spezielles beachten müssen. Unsere Querys landen eigentlich automatisch im Cache. Stop! Nicht immer! Nutzen wir in unserer Abfrage eine nichtdeterministische Funktion wird der Cache nicht benutzt!</p>
<p>Ok, halten wir mal kurz an! Ihr fragt euch jetzt bestimmt: &#8220;Was für eine Funktion ? nichtdeterwas ?&#8221; :-) hehe! Hier ein kleines Zitat aus der MySQL Doku:</p>
<blockquote><p>Eine Prozedur oder Funktion gilt als &#8220;deterministisch&#8221;, wenn sie für gleiche Eingabeparameter immer gleiche Resultate erzeugt; ansonsten ist sie &#8220;nichtdeterministisch&#8221;. Wenn in der Definition der Routine weder DETERMINISTIC noch NOT DETERMINISTIC steht, ist die Voreinstellung NOT DETERMINISTIC.</p></blockquote>
<p>Soweit klar ? Super&#8230; dann können wir ja weiter machen.<br />
Also, sobald wir eine solche Funktion in unserer Abfrage nutzen wird nicht mehr mit dem Cache gearbeitet! Soweit klar, hier ein Beispiel:</p>
<pre class="brush: php;">$result = mysql_query('SELECT title FROM tabelle WHERE myDate &lt;= CURDATE()');</pre>
<p>Mit diesem Query holen wir uns alle Zeilen wo die Spalte &#8220;myDate&#8221; kleiner gleich dem aktuellen Datum ist! CURDATE ist in diesem Fall eine nichtdeterministische Funktion! NOW() oder RAND() wären andere Beispiele!</p>
<p>Diesen Query können wir natürlich optimieren. Und zwar so das auch der Cache benutzt wird. Wir verzichten einfach auf diese komische nichtdeterministische Funktion und nutzen ein wenig PHP</p>
<pre class="brush: php;">$curdate = date('Y-m-d');
$result = mysql_query('SELECT title FROM tabelle WHERE date &lt;= ' . $curdate);</pre>
<p><strong>5) Nutze das Werkzeug EXPLAIN</strong></p>
<blockquote><p>Wenn man einer SELECT Anweisung das Schlüsselwort EXPLAIN voranstellt, zeigt MySQL Informationen des Optimierers zum Ausführungsplan der Abfrage an. MySQL erläutert also, wie es die SELECT-Anweisung verarbeiten würde, und gibt zudem an, wie und in welcher Reihenfolge Tabellen miteinander verknüpft werden.</p></blockquote>
<p>Zitat aus der MySQL Doku : <a href="http://dev.mysql.com/doc/refman/5.1/de/explain.html" onclick="pageTracker._trackPageview('/outgoing/dev.mysql.com/doc/refman/5.1/de/explain.html?referer=');">http://dev.mysql.com/doc/refman/5.1/de/explain.html</a></p>
<p>Super, bedeutet wir haben ein Werkzeug mit dessen Hilfe wir Step by Step einen SELECT Query optimieren können!</p>
<p>Wir können jetzt also beim entwickeln unserer Applikation jedes mal wenn wir einen SELECT bauen direkt schauen ob dieser performant ist! Da wir die Applikation ja gerade erst bauen, die Datenbank nur ein paar Testeinträge besitzt, geht alles in allem recht flot und wir stempeln unseren Query als Performant ab!</p>
<p>1 Jahr später, die Applikation ist gut besucht, die Datenbank ist fett mit wunderbaren Informationen gefüllt, fragen wir uns, warum ist meine Webseite so langsam. Als ich die gebaut hab war doch alles so schnell. Mit der Zeit hat sich viel verändert, als wir beim entwickeln getestet haben hatten wir auch noch keinen Bezug auf die Realität, keine volle Datenbank, keine X-hundert Hits am Tag!</p>
<p>Wir wollen also versuchen unsere Webseite im MySQL Bereich zu optimieren. Um jetzt nicht jede einzelne Query wieder zu suchen und von Hand zu testen nutzen wir ein wunderbares Feature! Wir können MySQL sagen ab welcher Ausführungszeit eine Abfrage als &#8220;zu langsam&#8221; gilt. Und diese lassen wir dann mitloggen! Extrem cool nicht war.. wir haben also jetzt eine Möglichkeit Querys ausfindig zu machen die langsam sind. Diese nehmen wir uns jetzt genauer unter die Lupe und zwar mit unserem Werkzeug EXPLAIN!</p>
<p>EXPLAIN analysiert unsere Abfrage und stellt dar was die Datenbank mit der Abfrage genau macht.<br />
Beispiel:</p>
<pre class="brush: php;">$result = mysql_query('EXPLAIN SELECT title FROM tabelle');</pre>
<p>Was uns das Ergebnis genau sagt können wir auf der MySQL Seite nachlesen: <a href="http://dev.mysql.com/doc/refman/5.1/de/explain.html" onclick="pageTracker._trackPageview('/outgoing/dev.mysql.com/doc/refman/5.1/de/explain.html?referer=');">http://dev.mysql.com/doc/refman/5.1/de/explain.html</a> eine ausführliche Antwort um dieses zu verstehen würde sonst diesen Beitrag sprengen :-)</p>
<p><strong>6) Suchfelder indizieren</strong></p>
<p>Oft müssen wir per MySQL nach irgendwelchen Sachen suchen. Nehmen wir an, wir haben einen selbstprogrammierten Blog. Der User möchte nach einem Artikel suchen wo er sich nur schwach an den Titel erinnern kann. Irgendwas mit &#8220;Hello&#8221; war das&#8230;.</p>
<p>Statisch umgesetzt könnte das so aussehen:</p>
<pre class="brush: php;">$result = mysql_query('SELECT COUNT(*) FROM tabelle WHERE title LIKE &quot;Hello%&quot;');</pre>
<p>Wenn wir uns die Zeit dazu mal anschauen sehen wir das das schon ziemlich lange dauert: 1 row in set (0.31 sec)</p>
<p>Also, legen wir einen INDEX auf die Spalte &#8220;title&#8221; in der gesucht werden soll:</p>
<p>[mysql]ALTER TABLE tabelle ADD INDEX (&#8220;title&#8221;);[/mysql]</p>
<p>Führen wir unseren Query erneut aus:</p>
<pre class="brush: php;">$result = mysql_query('SELECT COUNT(*) FROM tabelle WHERE title LIKE &quot;Hello%&quot;');</pre>
<p>sieht unser Ergebnis schon ganz anders aus: 1 row in set (0.07 sec)</p>
<p>Mit einem INDEX kann man also extreme Performancesteigerungen erreichen!</p>
<p>Kleiner Tip: Wo welcher Index verwendet wird können wir ganz einfach mit der Abfrage</p>
<pre class="brush: sql;">SHOW INDEX FROM tabelle;</pre>
<p>rausbekommen!</p>
<p>Es gibt bestimmt noch dutzende weitere Möglichkeiten seine Scripte zu optimieren! Ich möchte hier aber erst mal einen Cut machen. Wenn Ihr noch gute Optimierungsmöglichkeiten kennt die ich hier mit aufnehmen sollte, benutzt bitte die Kommentarfunktion!</p>
<p>Jedenfalls hoffe ich das euch der Artikel gefallen und vor allem geholfen hat! Ihr könnt diesen Artikel auch unten Bewerten oder per Twitter ein wenig pushen :-)</p>
<p>Lieben Gruß<br />
Julian</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.kj187.de/2010/03/16/mysql-optimierung/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Polymorphie</title>
		<link>http://blog.kj187.de/2010/03/12/polymorphie/</link>
		<comments>http://blog.kj187.de/2010/03/12/polymorphie/#comments</comments>
		<pubDate>Fri, 12 Mar 2010 20:23:26 +0000</pubDate>
		<dc:creator>Julian Kleinhans</dc:creator>
				<category><![CDATA[OOP]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Polymorphie]]></category>

		<guid isPermaLink="false">http://blog.kj187.de/?p=154</guid>
		<description><![CDATA[Nein, es handelt sich hier nicht um irgendeine seltene Krankheit. Unter Polymorhie versteht man in der Programmierung eine Art von Vielgestaltigkeit, bei der das dynamische Verhalten von Methoden verfolgt wird, welche von der Anzahl und des Typs der übergebenen Parameter abhängt.
Verständlich oder ? Etwa nicht ? Keine Angst ich werde gleich ein Beispiel zeigen in [...]]]></description>
			<content:encoded><![CDATA[<p>Nein, es handelt sich hier nicht um irgendeine seltene Krankheit. Unter Polymorhie versteht man in der Programmierung eine Art von Vielgestaltigkeit, bei der das dynamische Verhalten von Methoden verfolgt wird, welche von der Anzahl und des Typs der übergebenen Parameter abhängt.</p>
<p>Verständlich oder ? Etwa nicht ? Keine Angst ich werde gleich ein Beispiel zeigen in dem das ganze dann deutlich wird!<span id="more-154"></span></p>
<p>Die Polymorphie gibt es in PHP nicht wirklich, warum? Weil PHP eine dynamisch getypte Programmiersprache ist, viele sagen eine typenlose Programmiersprache. Was so viel bedeutet wie, wir müssen den Variablen nicht fest vorgeben was in Ihnen gespeichert wird, ob ein String, ein Integer oder Double oder oder oder. Wir können jederzeit von einem Typ zum anderen wechseln.</p>
<p>In anderen Programmiersprachen wie Java zum Beispiel muss man jeder Variable sagen welcher Typ in Ihr gespeichert wird und diesen kann man dann nicht mal eben ändern bzw man kann keinen String in einer als Integer definierten Variable speichern. Das nennt man dann eine statisch getypte Programmiersprache.</p>
<p>Daher gibt es in PHP keine direkte Polymorphie. Um das ganze jetzt etwas deutlicher zu machen möchte ich euch ein Beispiel aus der Java Welt zeigen.</p>
<pre class="brush: java;">class MyClassName {

 public void methodName (int variableName) {
 // Es wurde ein Integer übergeben
 }

 public void methodName (String variableName) {
 // Es wurde ein String übergeben
 }

}</pre>
<p>Würden wir die Methode &#8220;methodName&#8221; jetzt aufrufen und Ihr als Parameter einen Integer mit übergeben, würde die erste Methode auufgerufen werden. Rufen wir die gleiche Methode auf aber übergeben Ihr einen String als Parameter, wird die zweite Methode aufgerufen. Es wird also überprüft welcher Typ übergeben wurde und entsprechend mit den Typen der Methodensignatur verglichen.</p>
<p>Das gleiche können wir aber auch mit der Anzahl der Parameter machen</p>
<pre class="brush: java;">class MyClassName {

 public void methodName (int variableName, String variableName) {
 // Es wurde ein Integer und ein String übergeben
 }

 public void methodName (int variableName) {
 // Es wurde ein Integer übergeben
 }

}</pre>
<p>Rufen wir die Methode &#8220;methodName&#8221; mit nur einem Parameter, einen Integer Parameter auf, wird die zweite Methode aufgerufen. Rufen wir aber die Methode mit einem Integer UND einem String Parameter auf, ja richtig, dann wird die zweite Methode aufgerufen.</p>
<p>Das bedeutet Vielgestaltigkeit!</p>
<p>Soviel dazu, jetzt habe ich aber gesagt das PHP eine typenlose Sprache ist. Daher dann die Deklaration von mehreren Methoden des gleichen Namens nicht verwendet werden. Wie klappt das dann in PHP ?</p>
<p>Es bieten sich folgende Möglichkeiten an:<br />
Eine Methode kann einen Parameter akzeptieren der unterschiedliche Typen enthält. Über eine if Bedingungen überprüfen wir den Typen und agieren entsprechend</p>
<pre class="brush: php;">class MyClassName {

 public function methodName ($variableName) {
 if (is_string($variableName)) {
 // Die Variable ist ein String
 } elseif (is_integer($variableName)) {
 // Die Variable ist ein Integer
 } elseif (is_array($variableName)) {
 // Die Variable ist ein Array
 }
 // usw.
 }

}</pre>
<p>Wenn noch fragen offen sind könnt Ihr gerne die Kommentarfunktion benutzen!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.kj187.de/2010/03/12/polymorphie/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>TYPO3 Recycler</title>
		<link>http://blog.kj187.de/2010/03/11/typo3-recycler/</link>
		<comments>http://blog.kj187.de/2010/03/11/typo3-recycler/#comments</comments>
		<pubDate>Thu, 11 Mar 2010 11:40:26 +0000</pubDate>
		<dc:creator>Julian Kleinhans</dc:creator>
				<category><![CDATA[News]]></category>
		<category><![CDATA[TYPO3]]></category>
		<category><![CDATA[extJS]]></category>
		<category><![CDATA[Recycler]]></category>

		<guid isPermaLink="false">http://blog.kj187.de/?p=132</guid>
		<description><![CDATA[Hat TYPO3 jetzt einen grünen Punkt oder wie ?
Nein, nicht wirklich. Der TYPO3 Recycler ist ein Backend Modul der einen Papierkorb wiederspiegelt.
Wir alle kennen ja den Papierkorb von unserem Betriebssystem. Löschen wir mal eine Datei bzw. einen Ordner ist dieser nicht wirklich gelöscht.
Er wird in den Papierkorb verschoben. Wir müssten um diese Dateien entgültig zu [...]]]></description>
			<content:encoded><![CDATA[<p><em><strong>Hat TYPO3 jetzt einen grünen Punkt oder wie ?</strong></em></p>
<p><a href="http://blog.kj187.de/wp-content/uploads/2010/03/TYPO3_4.3_Recycler.png"><img class="alignright size-medium wp-image-133 colorbox-132" title="TYPO3 4.3 Recycler" src="http://blog.kj187.de/wp-content/uploads/2010/03/TYPO3_4.3_Recycler-300x196.png" alt="" width="300" height="196" /></a>Nein, nicht wirklich. Der TYPO3 Recycler ist ein Backend Modul der einen Papierkorb wiederspiegelt.<br />
Wir alle kennen ja den Papierkorb von unserem Betriebssystem. Löschen wir mal eine Datei bzw. einen Ordner ist dieser nicht wirklich gelöscht.<br />
Er wird in den Papierkorb verschoben. Wir müssten um diese Dateien entgültig zu löschen also den Papierkorb leeren. Haben wir mal eine Datei ausversehen gelöscht, können wir in den Papierkorb gehen und die Datei wiederherstellen. Genauso arbeitet der TYPO3 Recycler. In TYPO3 werden Seiten  &#8230;<span id="more-132"></span>und Seiteninhaltselemente nicht wirklich gelöscht. Sie werden in der Datenbank nur als deleted=1 markiert und sind somit in der Backend Oberfäche und im Frontend nicht mehr sichtbar. Existieren tuen Sie allerdings noch. Und genau diese Dateien zeigt der Recycler an. Wie auch auf dem Betriebssystem könnt ihr also in diesem Recycler Daten wiederherstellen bzw entgültig und unwiederruflich vom System löschen.</p>
<p>Das spannende am TYPO3 Recylcer ist das man rekursive wiederherstellen kann. Hat ein Redakteur oder gar ein Admin die Rechte im System rekursive zu löschen und nutzt diese evtl unwissentlich aus, kann es sein das mal eben der komplette Seitenbaum gelöscht wird. Viele stehen jetzt vor einem Problem. Nicht nur, das die Daten weg sind, Sie müssen es erstmal Ihrem Chef beibringen ;-)</p>
<p>Aber, alles kein Problem. Ein Sysadmin der weiss das die Daten noch in der Datenbank stehen, würde jetzt auf Datenbankebene hingehen und alle gelöschten Daten wiederherstellen. Aber, woher weiss er eigentlich welche er wiederherstellen soll und welche nicht, welche gehörten zum Seitenbaum und welche nicht. Und muss ich jetzt alles einzeln durchgehen, es gibt ja mehrere Tabellen&#8230; da kommt die große Frage auf: Wann habe ich endlich feierabend :-)</p>
<p>Diese Problem können wir mit wenigen Klicks umgehen. Recycler installieren, in den Recycler gehen, Weltkugel bzw die Mutterseite auswählen in der euer gelöschter Seitenbaum war. Die Seite auswählen, Wiederherstellen und ein Hacken bei Rekursive setzen, neuen Kaffee holen und warten bis Feierabend ist :-)</p>
<p>Natürlich könnt ihr auch einzelne Dateien wiederherstellen bzw entgültig löschen. Neben diesen Grundfunktionalitäten könnt ihr nach Dateien suchen und filtern.<br />
Das ganze basiert auf dem Javascript Framework extJS.</p>
<p>Der TYPO3 Recycler ist seit der Version 4.3 bestandteil des Cores. Also eine Core Extension. Diese ist Standardmäßig nicht installiert. Ihr müsst also in den Extension Manager gehen und Sie kurz aktivieren. Danach könnt ihr den Recycler benutzen.</p>
<p>Aber noch ein paar Worte zur Entstehung des ganzen.<br />
2005 habe ich mit TYPO3 angefangen. Damals suchte ich nach einem Projekt bei dem ich was lernen konnte und es gleichzeitig mit der Community teilen konnte.<br />
Damals löschte ich ausversehen einen Seitenbaum und merkte schnell das es keine brauchbare Lösung gab. Also hatte ich mein Projekt gefunden. Ich gründete die TER Extension &#8220;kj_recycler&#8221;. Diese Extension ist mittlerweile recht veraltet und als Obsolete im TER noch zu finden. Schaut lieber nicht rein :-) Der Code stammt von meinen blutjungen Ersterfahrungen :-)</p>
<p>Jedenfalls fiel auf den TYPO3 Developer Days 2008, bei einer Featurewunschliste für TYPO3 4.3, der Satz &#8220;Improve record recycling concept&#8221;. Natürlich meldete ich mich direkt und übernahm diese Aufgabe. Eine Codeübernahme des kj_recyclers kam für mich nicht in frage da dieser total veraltet war. In der Zeit wurde bekannt das das Javascript Framework extJS fester bestandteil des Cores werden sollte. Das war für mich die perfekte Lösung. der Recylcer muss auf extJS basieren. Schwup die bub fing ich auch damit an. Mit Hilfe von Erik Frister, Steffen Kamper und Oliver Hader wurde aus dem Recycler das was er heute ist. Eine, nein, DIE erste auf extJS basierende TYPO3 Core Extension.</p>
<p>Ich freue mich mit dieser Idee und Umsetzung der Community zu helfen. Schon viele Mails habe ich bekommen in denen sich Leute einfach dafür bedanken das es diese Extension gibt und diese Ihnen in wahrsten Sinne den Arsch gerettet hat :-)</p>
<p>Wo ihr den Recyler finden könnt ?<br />
Ihr benötigt mindestens die TYPO3 Version 4.3, damit habt ihr auch schon den Recycler, dieser muss nur über den Extension Manager aktiviert werden.</p>
<p>Die trunk Version findet Ihr im <a href="http://forge.typo3.org/projects/show/extension-recycler" target="_blank" onclick="pageTracker._trackPageview('/outgoing/forge.typo3.org/projects/show/extension-recycler?referer=');">Forge</a></p>
<p>Vielleicht hilft diese Extension auch euch irgendwann mal :-)<br />
Für eine kleines Dankeschön hier im Kommentarbereich würde ich mich sehr freuen!</p>
<p>Cheers<br />
Julian</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.kj187.de/2010/03/11/typo3-recycler/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>TYPO3 und AJAX &#8211; Wie geht das?</title>
		<link>http://blog.kj187.de/2010/03/09/typo3-und-ajax-wie-geht-das/</link>
		<comments>http://blog.kj187.de/2010/03/09/typo3-und-ajax-wie-geht-das/#comments</comments>
		<pubDate>Tue, 09 Mar 2010 21:53:05 +0000</pubDate>
		<dc:creator>Julian Kleinhans</dc:creator>
				<category><![CDATA[TYPO3]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[eID]]></category>
		<category><![CDATA[typeNum]]></category>

		<guid isPermaLink="false">http://blog.kj187.de/?p=89</guid>
		<description><![CDATA[Dieses Tutorial soll euch eine kleine Einführung geben, wie man AJAX zusammen mit TYPO3 am besten nutzen kann!
Dazu werden wir das Javascript Framework jQuery verwenden. Selbstverständlich kann man auch jedes andere Framework verwenden was eine AJAX API anbietet.
Grundlegend gibt es bei TYPO3 zwei verschiedene Wege im Frontend und einen im Backend über die man einen [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.kj187.de/wp-content/uploads/2010/03/logo-typo3.gif"><img class="alignright size-full wp-image-101 colorbox-89" title="logo-typo3" src="http://blog.kj187.de/wp-content/uploads/2010/03/logo-typo3.gif" alt="" width="123" height="34" /></a>Dieses Tutorial soll euch eine kleine Einführung geben, wie man <em>AJAX</em> zusammen mit <em>TYPO3</em> am besten nutzen kann!<br />
Dazu werden wir das Javascript Framework <a href="http://jquery.com/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/jquery.com/?referer=');">jQuery</a> verwenden. Selbstverständlich kann man auch jedes andere Framework verwenden was eine AJAX API anbietet.</p>
<p>Grundlegend gibt es bei TYPO3 zwei verschiedene Wege im Frontend und einen im Backend über die man einen AJAX Request absetzen kann.<br />
Da wäre im Frontend einmal der so genannte typeNum, wo man per GET Parameter den entsprechenen type mit übermittelt, und zum anderen gibt es den sogenannten eID Mechanismus. Ich werde zu beiden Wegen ein kleines Beispiel zeigen. Im Backend gibt es den Weg über die ajaxID. Dazu werde ich ganz zum Schluß noch ein paar Worte sagen!</p>
<p>Beginnen wir aber erst mit dem Frontend und mit den Grundlagen die beide Wege die ich genannt hatte benötigen.<br />
Bedeutet, wir müssen erst einmal das jQuery Framework einbinden um eine entsprechende AJAX API nutzen zu können. Hierzu verwende ich immer folgendes Script:</p>
<p><span id="more-89"></span></p>
<pre class="brush: jscript;">jQuerySrc = 'fileadmin/js/jquery-min.js';

// only load jQuery if not present
if (typeof jQuery == 'undefined')  {
    document.write(&quot;&lt;script type=\&quot;text/javascript\&quot; src=\&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js\&quot;&gt;&lt;/&quot;+&quot;script&gt;&quot;);
}

// if Google is down
if (typeof jQuery == 'undefined') {
    document.write(&quot;&lt;script type=\&quot;text/javascript\&quot; src=\&quot;&quot; + jQuerySrc + &quot;\&quot;&gt;&lt;/&quot;+&quot;script&gt;&quot;);
}</pre>
<p>Was passiert hier:  <br />
Es wird überprüft ob jQuery schon eingebunden wurde. Es kann ja sein das per TypoScript oder einer anderen Extension das jQuery Framework schon in die Seite eingebunden ist und doppelt wollen wir es ja nicht haben. Wenn jQuery also noch nicht eingebunden wurde wird es von der Google API geholt. Sollte die Google API einmal down sein, was zu 99,99% nie der fall sein sollte,  überprüft eine weitere Bedingung erneut ob jQuery eingebunden wurde. Ist die Google API also mal down, lachen wir google erstmal kurz aus und lehnen uns wieder entspannt zurück, den es wird dann unsere lokale Version eingebunden. Ihr müsst dazu natürlich die jQuerySrc Variable entsprechend anpassen.</p>
<p>Soweit so gut, Grundstein ist gelegt, für Kaffee ist gesorgt, oder ? :-) Weiter gehts&#8230;</p>
<p>In unserem Beispiel gehen wir davon aus das ein Klick auf einen Button, der die id &#8220;triggerButton&#8221; als Attribut hat, den AJAX Request auslöst (der sogenannte Trigger &#8211; Auslöser).</p>
<p>In jQuery kann das so aussehen:</p>
<pre class="brush: jscript;">$('#triggerButton').bind('click', function() {
    // mache was
});</pre>
<p>Sehr gut, Putzlappen raus, jetzt kommt AJAX zum Einsatz :-)<br />
Innerhalb des click Events kommt jetzt unser AJAX Request rein der wie folgt aussehen kann</p>
<pre class="brush: jscript;">$.ajax({
    url: '',
    success: function(data) {

    },
    error: function(XMLHttpRequest, textStatus, errorThrown) {

    }
});</pre>
<p>Das ist ein Aufruf mit grundlegenden Einstellungen, hier gibt es natürlich noch weitere Einstellungen um den Rückgabetyp zu definieren und und und, hier einfach mal in die <a href="http://api.jquery.com/jQuery.ajax/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/api.jquery.com/jQuery.ajax/?referer=');">AJAX API </a>von jQuery schauen.</p>
<p>Die &#8220;url&#8221; erkläre ich gleich da hier die zwei unterschiedlichen Wege zum Einsatz kommen.<br />
&#8220;success&#8221; wird aufgerufen wenn der Call erfolgreich war und &#8220;error&#8221; sofern ein Fehler aufgetreten ist! Beides sind funktionen in denen man dann entsprechende Aktionen auslösen kann!</p>
<p>Ok, fangen wir mit dem ersten Weg an:</p>
<p><strong>Der typeNum!</strong></p>
<p>Der typeNum sollte uns schon etwas sagen, den unsere Webseite basiert auf dem typeNum 0. 0 Ist dabei der default typeNum.<br />
Gibt der user also die Domain euerer Webseite ein und gibt keinen &#8220;type&#8221; als GET Parameter ein, wird der default typeNum 0 genommen.<br />
Das TypoScript sieht in den meisten Fällen so aus</p>
<pre class="brush: typoscript;">page = PAGE
page.typeNum = 0
page.bodyTag = &lt;body&gt;

page.10 = TEMPLATE
page.10.template = FILE
page.10.template.file = fileadmin/index.html
page.10.workOnSubpart = DOCUMENT

page.10 {
 subparts {
   CONTENT &lt; styles.content.get
 }

 # usw
} </pre>
<p>Ok, also, wir können also beliebig viele weitere typeNums definieren, diese müssen halt nur einmalig sein, da der letzte sonst immer gewinnen würde. Ihr kennt das Prinzip, TypoScript wird von oben nach unten eingelesen und wenn ihr Definitionen doppelt drin habt gewinnt immer der letzte!</p>
<p>Wunderbar, wir wollen also einen typNum definieren den wir für unsere AJAX Anfrage nutzen. Also, tragen wir folgendes im TypoScript Setup ein:</p>
<pre class="brush: typoscript;">ajaxCall = PAGE
ajaxCall {
  typeNum = 5000
  10 &lt; plugin.tx_unsereextension_pi1

  config {
    disableAllHeaderCode = 1
    xhtml_cleaning = 0
    admPanel = 0
    debug = 0
    no_cache = 1
  }
}</pre>
<p>[Setzt voraus wir haben eine Extension "unsereextension" die installiert ist. Das kann eine recht einfache über den Kickstarter erstellte Extension sein die mindestens eine pi1 enthält]</p>
<p>Das TypoScript bewirkt das, wenn wir eine URL mit dem type=5000 aufrufen, das sofort an das Plugin tx_unsereextension_pi1 weitergeleitet wird und das was dort als return zurück kommt ausgegeben wird. Im Bereich config stellen wir noch ein paar Feinheiten ein, wie zB disableAllHeaderCode = 1 was bewirkt das wir unser Ergebnis als reinen Plaintext wieder bekommen ohne das der von TYPO3 generierte HTML Header etc. mit ausgegeben wird. Da wir auch keine anderen Ausgaben haben wollen deaktivieren wir auch das adminPanel und die debug Ausgabe und deaktivieren das Caching.</p>
<p>In unserer Extension steht aktuell folgendes in der main Methode<br />
typo3conf/ext/unsereextension/pi1/class.tx_unsereextension_pi1.php</p>
<pre class="brush: php;">// ...

public function main($content, $conf) {
    return 'Das ist ein Test!';
} 

// ...
</pre>
<p>Um vorab einmal zu testen ob unser neu angelegter typeNum funktioniert rufen wir das ganze manuell auf. Gebt also euere Domain + den neuen type als GET Parameter an: http://www.domain.de/?type=5000</p>
<p>Als Ausgabe müssten wir jetzt sehen &#8220;Das ist ein Test!&#8221; und wenn wir in den Quellcode der Seite gucken dürfte dort auch KEIN HTML Tag etc. stehen sondern nur der reine Plaintext. </p>
<p>Sollte das nicht funktieren stellt bitte sicher ob ihr den Frontend Cache geleert habt :-) Ein häufiger Fehler wenn man nicht mit dem Template Modul arbeitet. Im Template Modul passiert das nämlich automatisch.</p>
<p>Aber wir gehen davon aus das alles geklappt hat und kümmern uns jetzt um das AJAX<br />
Im AJAX Call tragen wir also in der &#8220;url&#8221; folgendes ein</p>
<pre class="brush: jscript;">$.ajax({
    url: '/?type=5000',
    success: function(result) {
        alert(result);
    },
});</pre>
<p>Wenn jetzt auf den Button geklickt wird den wir als Trigger nutzen, müsste ein Alert erscheinen in dem steht: Das ist ein Test!<br />
Ich würde sagen, glückwunsch! Ihr habt es geschafft!<br />
Jetzt könnt Ihr mit jQuery das Ergebnis entsprechend verarbeiten.</p>
<p>Dem AJAX Call kann man natürlich auch noch Daten mit übergeben damit, anhand dieser Daten kann man im AJAX Script bestimmte Aktionen durchgeführen lassen!<br />
Nehmen wir also an ihr wollt die FE User ID eines eingeloggten Users mit übergeben</p>
<pre class="brush: jscript;">var useruid = 1; // müsste dann dynamisch gefüllt werden

$.ajax({
    url: '/?type=5000',
    data: 'useruid=' + useruid,
    success: function(result) {
        alert(result);
    },
});</pre>
<p>Der Aufruf sieht jetzt aber wie folgt aus: http://www.domain.de/?type=5000&#038;useruid=X<br />
Dementsprechend könnt ihr in euerem AJAX Script auf den GET Parameter zugreifen!</p>
<p>Möchte man die Extension mit mehreren verschiedenen typNums nutzen kann man in der Extension einfach folgendes machen</p>
<pre class="brush: php;">
switch ($GLOBALS['TSFE']-&gt;type) {
  case 5000: // fuer typeNum 5000
    break;
  case 5001: // fuer typeNum 5001
    break;
  // usw
}
</pre>
<p>Der Vorteil bei dem Weg über typeNum ist das uns alle globalen Variablen wie das komplette TSFE mit cObj etc. zur Verfügung stehen. Bei dem Weg per eID musste man vor der TYPO3 Version 4.3 noch ein eigenes TSFE Objekt erzeugen. Seit der 4.3 bietet das das eID Script aber an womit wir direkt zum zweiten Weg kommen!</p>
<p><strong>eID steht für Extension ID</strong></p>
<p>Der eID Mechanismus ist  seit der Version 4.0 dabei!</p>
<p>Angesprochen wird er über einen GET oder POST Parameter. Sobald also eID als Parameter in der URL vorhanden ist, zB. www.domain.de/?eID=schuesselwort, wird der normale Prozess sehr früh abgebrochen und auf ein Script weitergeleitet was von uns vorher registriert wurde. Da der normale Prozess so früh abgebrochen wird kommt es auch noch zu keiner Ausgabe. Es wird nichts gecachet und kein HeaderCode etc. generiert. Wir bekommen also ein blankes Ergebnis unserer main Methode ausgegeben.</p>
<p>Wollen wir uns einmal die index_ts.php (typo3/sysext/cms/tslib/) Zeile 174 bis 185 ansehen.</p>
<pre class="brush: php;">// *********************
// Look for extension ID which will launch alternative output engine
// *********************
if ($temp_extId = t3lib_div::_GP('eID')) {
    if ($classPath = t3lib_div::getFileAbsFileName($TYPO3_CONF_VARS['FE']['eID_include'][$temp_extId])) {
        // Remove any output produced until now
        ob_clean();
        require($classPath);
    }
    exit;
}</pre>
<p>Hier wird überprüft ob es einen GET bzw POST Parameter mit dem Namen eID gibt, sofern vorhanden wird geguckt ob dieser Key registriert wurde und der Pfad zu unserem Script wird in $classPath gespeichert und per require eingebunden. Danach folgt ein exit damit der restliche Prozess von TYPO3 nicht mehr ausgeführt wird.</p>
<p>Wie genau können wir unser Script registrieren ?</p>
<p>Das sagen wir dem System über $TYPO3_CONF_VARS['FE']['eID_include'][$temp_extId]<br />
Wir müssten entweder in die localconf.php oder in eine ext_localconf.php einer Extension folgendes Eintragen</p>
<pre class="brush: php;">$TYPO3_CONF_VARS['FE']['eID_include']['helloworld'] = 'EXT:meinExtKey/meinScript.php';</pre>
<p>Steht jetzt also in der Adresse www.domain.de/?eID=helloworld geht er in die erste if Abfrage und sieht das<br />
$TYPO3_CONF_VARS['FE']['eID_include'][$temp_extId] vorhanden ist und speichert &#8216;EXT:meinExtKey/meinScript.php&#8217; in die Variable $classPath und includiert unser Script.</p>
<p>Da unser Script noch leer ist bekommen wir eine weiße Seite angezeigt in der auch der komplette Quelltext leer ist.</p>
<p>Damit wir auch ein FE User Objekt, das TSFE Objekt und eine Datenbank Verbindung zur Verfügung haben, geben wir folgendes ein</p>
<pre class="brush: php;">$feUserObject = tslib_eidtools::initFeUser();
$TSFEObject = tslib_eidtools::getTSFE();</pre>
<p>Die erste Zeile initialisert den Frontent User und gibt uns diesen als Objekt zurück. Dabei wird auch eine Verbindung zur Datenbank hergestellt.<br />
Um jetzt noch das komplette TSFE zur Verfügung zu haben rufen wir in der zweiten Zeile die getTSFE Methode auf.<br />
Im Weiteren können wir ganz normal auch TYPO3 Funktionalitäten benutzen und eine entsprechende Rückgabe an unseren AJAX Request geben.</p>
<p>Möchten wir zB explizit JSON als Format zurückgeben können wir im AJAX Call einen dataType definieren und im PHP einfach json_encode($content); zurück geben. Damit kann man in der success Funktion dann auf das JSON Objekt zugreifen. Beispiel:</p>
<pre class="brush: jscript;">$.ajax({
    url: '/?eID=helloworld',
    dataType: 'json',
    success: function(result) {
        alert('Hello ' + result.myResult);
    },
});</pre>
<pre class="brush: php;">class unsereKlasse {

    public function main() {
        $feUserObject = tslib_eidtools::initFeUser();
        $TSFEObject = tslib_eidtools::getTSFE();
        return json_encode(array('myResult' =&gt; 'World'));
    }

}

$output = t3lib_div::makeInstance('unsereKlasse');
echo $output-&gt;main();</pre>
<p>Das war es soweit zum Frontend. Kommen wir noch zum Backend, hier hatte ich ja gesagt das es einen Weg per ajaxID gibt.<br />
Machen wir es kurz und schmerzlos :-)</p>
<p>Ihr habt eine Extension in der wir in die ext_localconf.php folgendes eintragen</p>
<pre class="brush: php;">$TYPO3_CONF_VARS['BE']['AJAX']['tx_extkey::helloworld'] = t3lib_extMgm::extPath($_EXTKEY) . 'classes/class.tx_extkey_helloworld_ajax.php:tx_extkey_helloworld_ajax-&gt;sayHello';</pre>
<p>OHA, was ist das ;-) Gang einfach, ich schreibe es nochmal so </p>
<pre class="brush: php;">$TYPO3_CONF_VARS['BE']['AJAX']['tx_extkey::key'] = 'pfad/datei.php:klassenname-&gt;methodenname';</pre>
<p>Ich denke jetzt ist es verständlicher und bedarf keiner weiteren Worte :-) oder doch ? Ok!<br />
In unserer Datei class.tx_extkey_helloworld_ajax.php die im Ordner classes liegt gibt es also eine Klasse mit dem Namen tx_extkey_helloworld_ajax in der eine<br />
Methode sayHello ist. </p>
<p>Mit dieser Zeile haben wir unser AJAX Script erstmal registriert!<br />
Ein Aufruf aus einem Modul etc. ist jetzt relativ einfach</p>
<pre class="brush: php;">$url = $this-&gt;doc-&gt;backPath . 'ajax.php?ajaxID=tx_extkey::helloworld';</pre>
<p>Diese Url ruft Ihr jetzt per AJAX API über jQuery oder extJS (seit 4.3 fest im Core) auf. Dabei wird dann die oben gannten Klasse->Methode aufgerufen und liefert das Ergebnis der Methode zurück.</p>
<p>So, der Kaffee ist leer und somit auch das Tutorial zu ende! Ich hoffe ich konnte euch einen kleinen grundlegenden Einstieg verschaffen. Wenn Ihr noch Fragen, Anregungen, Lob oder Kritik habt, nutzt bitte die Kommentarfunktion!</p>
<p>Cheers und bis zum nächsten mal,<br />
Julian</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.kj187.de/2010/03/09/typo3-und-ajax-wie-geht-das/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>TYPO3 &#8211; The new Extension Manager</title>
		<link>http://blog.kj187.de/2010/03/08/typo3-the-new-extension-manager/</link>
		<comments>http://blog.kj187.de/2010/03/08/typo3-the-new-extension-manager/#comments</comments>
		<pubDate>Mon, 08 Mar 2010 19:36:29 +0000</pubDate>
		<dc:creator>Julian Kleinhans</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[TYPO3]]></category>
		<category><![CDATA[extJS]]></category>
		<category><![CDATA[Extension Manager]]></category>
		<category><![CDATA[Recyler]]></category>
		<category><![CDATA[Steffen Kamper]]></category>

		<guid isPermaLink="false">http://blog.kj187.de/?p=73</guid>
		<description><![CDATA[Seitdem in der TYPO3 Version 4.3 das extJS Framework eingebunden ist werden immer mehr Backend Bereiche auf dieses Framework umgestellt. Neben dem Recycler hat sich nun auch Steffen Kamper den Extension Manager vorgeknüpft. Dieser basiert in seiner trunk Version komplett auf extJS. Noch ist dieser kein Bestandteil des Core trunks. Jedoch ist er recht zuversichtlich [...]]]></description>
			<content:encoded><![CDATA[<p>Seitdem in der TYPO3 Version 4.3 das <a href="http://www.extjs.com/" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.extjs.com/?referer=');">extJS Framework</a> eingebunden ist werden immer mehr Backend Bereiche auf dieses Framework umgestellt. Neben dem Recycler hat sich nun auch Steffen Kamper den Extension Manager vorgeknüpft. Dieser basiert in seiner <a href="http://forge.typo3.org/repositories/show/typo3v4-em" target="_blank" onclick="pageTracker._trackPageview('/outgoing/forge.typo3.org/repositories/show/typo3v4-em?referer=');">trunk Version</a> komplett auf extJS. Noch ist dieser kein Bestandteil des Core trunks. Jedoch ist er recht zuversichtlich das dieser in die nächste Version 4.4 einfließen wird.</p>
<p><a href="http://blog.kj187.de/2010/03/08/typo3-the-new-extension-manager/"><em>Click here to view the embedded video.</em></a></p>
<p>Um sich weitere Eindrücke zu verschaffen gibt es im <a href="http://forge.typo3.org/wiki/typo3v4-em/EM_Screenshots" target="_blank" onclick="pageTracker._trackPageview('/outgoing/forge.typo3.org/wiki/typo3v4-em/EM_Screenshots?referer=');">Forge</a> weitere Screenshots</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.kj187.de/2010/03/08/typo3-the-new-extension-manager/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The passionate programmer</title>
		<link>http://blog.kj187.de/2010/03/06/the-passionate-programmer/</link>
		<comments>http://blog.kj187.de/2010/03/06/the-passionate-programmer/#comments</comments>
		<pubDate>Sat, 06 Mar 2010 17:46:47 +0000</pubDate>
		<dc:creator>Julian Kleinhans</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Buch]]></category>
		<category><![CDATA[Leidenschaft]]></category>
		<category><![CDATA[programmer]]></category>

		<guid isPermaLink="false">http://blog.kj187.de/?p=40</guid>
		<description><![CDATA[Der Leidenschaftliche Programmierer ist ein Buch von Chad Fowler das als inspirierender Wegweiser für Programmierer und Softwareentwickler dient. Chad Fowler zeigt wie man sich nachaltig persönlich weiterentwickeln kann, um eine eigene berufliche Laufbahn erfolgreich zu gestalten und Schritt für Schritt seine eigenen Ziele erreicht. Ich persönlich bin sehr begeistert von diesem Buch. Es ist in [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.kj187.de/wp-content/uploads/2010/03/cfcar2.jpg"><img class="size-full wp-image-42 alignright colorbox-40" title="The passionate programmer" src="http://blog.kj187.de/wp-content/uploads/2010/03/cfcar2.jpg" alt="" width="152" height="228" /></a>Der Leidenschaftliche Programmierer ist ein Buch von Chad Fowler das als inspirierender Wegweiser für Programmierer und Softwareentwickler dient. Chad Fowler zeigt wie man sich nachaltig persönlich weiterentwickeln kann, um eine eigene berufliche Laufbahn erfolgreich zu gestalten und Schritt für Schritt seine eigenen Ziele erreicht. Ich persönlich bin sehr begeistert von diesem Buch. Es ist in einem recht lockeren Stil geschrieben so das eigenlich nie wirklich langweile aufkommt!</p>
<blockquote><p>This book is about creating a remarkable career in software development. In most cases, remarkable careers don’t come by chance. They require thought, intention, action, and a willingness to change course when you’ve made mistakes. Most of us have been stumbling around letting our careers take us where they may. It’s time to take control. This revised and updated second edition lays out a strategy for planning and creating a radically successful life in software development (the first edition was released as My Job Went to India: 52 Ways To Save Your Job).</p></blockquote>
<p><span id="more-40"></span><br />
<a href="http://blog.kj187.de/wp-content/uploads/2010/03/978-3-8266-5885-3.gif"><img class="alignleft size-full wp-image-51 colorbox-40" title="978-3-8266-5885-3" src="http://blog.kj187.de/wp-content/uploads/2010/03/978-3-8266-5885-3.gif" alt="" width="130" height="182" /></a>Das Buch gibt es als Paper und als eBook, für die die nicht so gerne englische Bücher lesen gibt es  eine deutsche Übersetzung vom &#8220;mitp&#8221; Verlag. Für alle Programmierer die eine Karriere anstreben und nicht auf einer Linie bleiben wollen ist das Buch ein Muss!</p>
<p>Das englische Original gibt es bei &#8220;The pragmatic bookshelf&#8221; (<a href="http://www.pragprog.com/titles/cfcar2/the-passionate-programmer" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.pragprog.com/titles/cfcar2/the-passionate-programmer?referer=');">klick hier</a>)</p>
<p>Die deutsche Übersetzung von Reinhard Engel gibt es beim &#8220;mitp&#8221; Verlag. (<a href="http://www.it-fachportal.de/de/shop/buch/The%20Passionate%20Programmer%20-%20Der%20leidenschaftliche%20Programmierer/detail.html,b168778" target="_blank" onclick="pageTracker._trackPageview('/outgoing/www.it-fachportal.de/de/shop/buch/The_20Passionate_20Programmer_20-_20Der_20leidenschaftliche_20Programmierer/detail.html_b168778?referer=');">klick hier</a>)</p>
<p>Über euere Meinung zu diesem Buch würde ich mich freuen, schreibt mir oder hinterlasst mir hier einen Kommentar!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.kj187.de/2010/03/06/the-passionate-programmer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
