<?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>Kau-Boys blog &#187; PHP</title>
	<atom:link href="http://kau-boys.de/tag/php/feed" rel="self" type="application/rss+xml" />
	<link>http://kau-boys.de</link>
	<description>Webdevelopment and more</description>
	<lastBuildDate>Thu, 29 Jul 2010 22:09:53 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Assoziatives Array als HTML Tabelle ausgeben</title>
		<link>http://kau-boys.de/webentwicklung/assoziatives-array-als-html-tabelle-ausgeben?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=assoziatives-array-als-html-tabelle-ausgeben</link>
		<comments>http://kau-boys.de/webentwicklung/assoziatives-array-als-html-tabelle-ausgeben#comments</comments>
		<pubDate>Tue, 09 Mar 2010 21:39:06 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Webentwicklung]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Snippet]]></category>

		<guid isPermaLink="false">http://kau-boys.de/?p=803</guid>
		<description><![CDATA[Sehr h&#228;ufig wird gefordert ein assoziatives Array als HTML Tabelle auszugeben. Ich nutze hier sehr oft die implode() Funktion, um dabei mit m&#246;glichst wenig Quellcode zu dem Gew&#252;nschten Ergebnis zu kommen. Da ich meine L&#246;sung wirklich sehr sch&#246;n und genial einfach finde, wollte ich euch kurz die Funktion pr&#228;sentieren. Als auszugebendes Array nehmen wir das [...]]]></description>
			<content:encoded><![CDATA[<p>Sehr h&#228;ufig wird gefordert ein assoziatives Array als HTML Tabelle auszugeben. Ich nutze hier sehr oft die <a href="http://de.php.net/manual/en/function.implode.php">implode() Funktion</a>, um dabei mit m&#246;glichst wenig Quellcode zu dem Gew&#252;nschten Ergebnis zu kommen. Da ich meine L&#246;sung wirklich sehr sch&#246;n und genial einfach finde, wollte ich euch kurz die Funktion pr&#228;sentieren. Als auszugebendes Array nehmen wir das MySQL-Debugging Array aus meinem vorherigen Artikel <a href="http://kau-boys.de/webentwicklung/mysql-unter-php-debuggen-mit-einer-eigenen-mysql-klasse">MySQL unter PHP debuggen mit einer eigenen MySQL Klasse</a>.</p>
<pre class="brush: php;">
function array_to_table($a){
	$t='&lt;table&gt;';
	$t.='&lt;tr&gt;&lt;th&gt;'.implode('&lt;/th&gt;&lt;th&gt;', array_keys($a[0])).'&lt;/th&gt;&lt;/tr&gt;';
	foreach($a as $row){
		$t.= '&lt;tr&gt;&lt;td&gt;'.implode('&lt;/td&gt;&lt;td&gt;', $row).'&lt;/td&gt;&lt;/tr&gt;';
	}
	return $t.='&lt;/table&gt;';
}

// Ausgabe der Tabelle
echo array_to_table($mysqli-&gt;queries);
</pre>
<p><span id="more-803"></span></p>
<p>In Zeile 3 werden die Schl&#252;ssel des assoziativen Array f&#252;r die &#220;berschriften der Spalten genutzt. Wir &#246;ffnen hier eine Zeile und eine Spalte und f&#252;gen dann mit Hilfe der implode() Funktion alle Schl&#252;ssel in diese Zeile ein. Die &#8220;Glue&#8221; f&#252;r die implode() Funktion ist hierbei ein schlie&#223;endes Tag f&#252;r die Spalte und ein weiteres &#246;ffnendes. Am Ende der Zeile schlie&#223;en wir noch die letzte Spalte und die Zeile. Die gleiche elegante Anwendung der implode() Funktion verwenden wir auch bei den einzelnen Spalten mit den Werten. Hier in einer foreach Schleife.</p>
<p>Mit dieser Funktion kann jedes assoziative Array sehr elegant ausgegeben werden. Dabei l&#228;sst sich die Funktion trefflich erweitern. So k&#246;nnte z.B. in einem Parameter ein Array mit Schl&#252;sselnamen &#252;bergeben werden, wenn die Schl&#252;ssel des Assoziativen Arrays nicht passend f&#252;r die Tabelle sind. Oder es k&#246;nnte jeder Zeile eine alternierende &#8220;gerade&#8221; und &#8220;ungerade&#8221; Klasse mitgegeben werden. Oder aber man vergibt Klassen um eine der vielen JavaScript Sortierungen auf die Tabelle anwenden zu k&#246;nnen.</p>
<p>Wir ihr also sehen k&#246;nnt ihr eure Fantasie bei der Erweiterbarkeit freien Lauf lassen. Ich vergebe meistens die Klassen f&#252;r Sortierung einer Tabelle mit der <a href="http://www.millstream.com.au/view/code/tablekit/">Tablekit Sortierung</a>.</p>
<p>Ich hoffe, dass euch die Funktion bei eurer t&#228;glichen Arbeit helfen kann. Ich liebe die implode() Funktion, da man mit ihr sehr elegant PHP Arrays in Strings umwandeln kann. Ich verwende sie auch h&#228;ufig beim Erstellen von SQL Statements in Verbindung mit dem <a href="http://dev.mysql.com/doc/refman/5.1/de/comparison-operators.html#id2785292">IN() Operator</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://kau-boys.de/webentwicklung/assoziatives-array-als-html-tabelle-ausgeben/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL unter PHP debuggen mit einer eigenen MySQL Klasse</title>
		<link>http://kau-boys.de/webentwicklung/mysql-unter-php-debuggen-mit-einer-eigenen-mysql-klasse?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=mysql-unter-php-debuggen-mit-einer-eigenen-mysql-klasse</link>
		<comments>http://kau-boys.de/webentwicklung/mysql-unter-php-debuggen-mit-einer-eigenen-mysql-klasse#comments</comments>
		<pubDate>Thu, 04 Mar 2010 22:41:07 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Webentwicklung]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://kau-boys.de/?p=794</guid>
		<description><![CDATA[Bei einem meiner Projekte kam es zu ungew&#246;hnlich langen Ladezeiten eines Formulars. Da hier allerdings auch sehr viele Datenbankabfragen ausgef&#252;hrt werden m&#252;ssen und dabei auch noch die Werte per COUNT() gez&#228;hlt werden wunderten mich die Zeiten nicht wirklich. Nun wollte ich nat&#252;rlich wissen, welche Abfrage dabei besonders viel Zeit in Anspruch nimmt um dann gezielt [...]]]></description>
			<content:encoded><![CDATA[<p>Bei einem meiner Projekte kam es zu ungew&#246;hnlich langen Ladezeiten eines Formulars. Da hier allerdings auch sehr viele Datenbankabfragen ausgef&#252;hrt werden m&#252;ssen und dabei auch noch die Werte per <a href="http://dev.mysql.com/doc/refman/5.1/en/group-by-functions.html#function_count">COUNT()</a> gez&#228;hlt werden wunderten mich die Zeiten nicht wirklich.</p>
<p>Nun wollte ich nat&#252;rlich wissen, welche Abfrage dabei besonders viel Zeit in Anspruch nimmt um dann gezielt optimieren zu k&#246;nnen. Ich setze in dem Projekt auf die <a href="http://de.php.net/manual/en/book.mysqli.php">MySQLi Klasse</a> von PHP. Da ich hierbei die Klasse objektorientiert nutze, war es sehr einfach m&#246;glich diese zu erweiterten. Eine M&#246;glichkeit w&#228;re es nat&#252;rlich gewesen eine eigene Funktion zu schreiben, aber in diesem Fall h&#228;tte ich auch alle Skript anpassen m&#252;ssen, in denen ich eine Query ausf&#252;hre. Daher habe ich mich dazu entschlossen einfach die <a href="http://de.php.net/manual/en/mysqli.query.php">query() Funktion</a> von MySQLi zu &#252;berschreiben. Hier ein stark vereinfachtes Beispiel, wie so etwas aussehen k&#246;nnte:</p>
<p><span id="more-794"></span></p>
<pre class="brush: php;">
&lt;?php

class mysqliDebugger extends mysqli {

	public $queries = array();
	public $queries_time = 0;

	function __construct($host, $user, $pass, $name, $port, $sock){
		parent::__construct($host, $user, $pass, $name, $port, $sock);
	}

	function __destruct(){
		parent::__destruct();
	}

	function query($query){
		$start = microtime(true);

		if(!$result = parent::query($query)){
				$error_message = $this-&gt;error;
		}

		$end = microtime(true);

		$this-&gt;queries[] = array(
			'number' =&gt; count($this-&gt;queries),
			'query' =&gt; $query,
			'error' =&gt; $error_message,
			'time' =&gt; $end - $start
		);

		$this-&gt;queries_time += $end - $start;

		return $result;
	}
}

$mysqli = new mysqliDebugger('host', 'user', 'pass', 'name');
if($result = $mysqli-&gt;query('SELECT * FROM tablename')){
	while($row = $result-&gt;fetch_assoc()){
		// Verarbeiten der Ergebniszeilen
	}
}

if($result = $mysqli-&gt;query('SELECT * FROM tablename2')){
	while($row = $result-&gt;fetch_assoc()){
		// Verarbeiten der Ergebniszeilen
	}
}

?&gt;
</pre>
<p>Sehen wir uns die wichtigsten Zeilen des Quellcodes an. Die Zeilen 8-10 zeigen den Konstruktor unserer neuen Klasse, die den Konstruktor der geerbten Klasse MySQLi aufruft. In den Zeilen 16-36 &#252;berschreiben wir die query() Funktion der MySQLi Klasse mit unserer Debugging-Klasse. Dort wird zuerst einmal zur Protokollierung der Ausf&#252;hrungszeit der Startzeitpunkt mit Hilfe der <a href="http://de.php.net/manual/en/function.microtime.php">microtime() Funktion</a> ermittelt. Anschlie&#223;end wird der Query mit dem Aufruf <code>parent::query($query)</code> an die query() Funktion der MySQLi Klasse &#252;bergeben. Einen eventuell auftretenden Fehler speichern wir dabei in einer Variablen ab.</p>
<p>In Zeile 23 speichern wir die Endzeit des Query. Anschlie&#223;end speichern wir alle Werte, die wir zur sp&#228;teren Auswertung ben&#246;tigen in einem Array gespeichert. Zus&#228;tzlich summieren wir noch alle Zeiten auf, um sp&#228;ter die Gesamtdauer aller Statements bestimmen zu k&#246;nnen. Die ab Zeile 38 wird eine einfache Instanziierung und Nutzung der Klasse aufgezeigt, wie man sie auch von MySQLi kennt. Wer also in seinen Skripten schon MySQLi verwendet kann einfach beim Instanziieren der Klasse die neue Debugging-Klasse verwenden und muss keine weiteren Zeilen im Quellcode &#228;ndern. Ich empfehle eine kleine Bedingung zu verwenden, die feststellt, ob der Debugging-Modus aktiv ist und nur dann die Debugging-Klasse zu verwenden, wenn sie auch ben&#246;tigt wird. Das spart im produktiven Einsatz etwas Rechenzeit. Eine m&#246;gliche Bedingung k&#246;nnte wie folgt aussehen:</p>
<pre class="brush: php; gutter: false;">
if($debug){
	$mysqli = new mysqliDebugger('host', 'user', 'pass', 'name');
} else {
	$mysqli = new mysqli('host', 'user', 'pass', 'name');
}
</pre>
<p>Anstelle der <code>$debug</code> Variablen k&#246;nntet ihr auch einen GET Parameter oder einen Session Parameter verwenden. Ich rate aber dringend davon ab einen einfach zu erratenden GET Parameter zu verwenden, da in solchen F&#228;llen eure SQL-Statements f&#252;r Unbefugte sichtbar werden k&#246;nnten, was unter Umst&#228;nden die Sicherheit eueres Systems gef&#228;hrden k&#246;nnte.</p>
<p>Nachdem wir die Daten gesammelt haben m&#246;chten wir sie nat&#252;rlich auch ausgeben. Das solltet ihr auch wieder die vorherige Bedingung verwenden. Dazu erstellen wir einfach eine Tabelle, die die gesammelten Daten enth&#228;lt:</p>
<pre class="brush: xml;">
&lt;table style=&quot;border: 1px solid #000;&quot; rules=&quot;all&quot;&gt;
	&lt;caption&gt;Gesamtdauer: &lt;?= $mysqli-&gt;queries_time ?&gt;&lt;/caption&gt;
	&lt;tr&gt;
		&lt;th&gt;Anzahl&lt;/th&gt;
		&lt;th&gt;Query&lt;/th&gt;
		&lt;th&gt;Fehler&lt;/th&gt;
		&lt;th&gt;Zeit&lt;/th&gt;
	&lt;/tr&gt;
&lt;? foreach($mysqli-&gt;queries as $query) : ?&gt;
	&lt;tr&gt;
		&lt;td&gt;&lt;?= $query['number'] ?&gt;&lt;/td&gt;
		&lt;td&gt;&lt;?= $query['query'] ?&gt;&lt;/td&gt;
		&lt;td&gt;&lt;?= $query['error'] ?&gt;&lt;/td&gt;
		&lt;td&gt;&lt;?= $query['time'] ?&gt;&lt;/td&gt;
	&lt;/tr&gt;
&lt;? endforeach ?&gt;
&lt;/table&gt;
</pre>
<p>Nehmen wir an, wir die Tabelle aus dem ersten Statement ist in der Datenbank nicht vorhanden. In diesem Fall w&#252;rden wir einen SQL-Fehler erhalten. In der Tabelle k&#246;nnen wir dann direkt den Fehler ermitteln und entsprechend das Statement korrigieren. Auch hier wird das Statement gespeichert und die Zeit gemessen.</p>
<table style="color: rgb(185, 189, 182); background-color: rgb(27, 36, 38); width: 100%; padding: 5px; border: 1px solid #000;" rules="all">
<caption style="background-color: rgb(27, 36, 38);">Gesamtdauer: 0.0025820732116699</caption>
<tr>
<th>Anzahl</th>
<th>Query</th>
<th>Fehler</th>
<th>Zeit</th>
</tr>
<tr>
<td>0</td>
<td>SELECT * FROM tablename</td>
<td>Table &#8216;name.tablename&#8217; doesn&#8217;t exist</td>
<td>0.00076198577880859</td>
</tr>
<tr>
<td>1</td>
<td>SELECT * FROM tablename2</td>
<td></td>
<td>0.0018200874328613</td>
</tr>
</table>
<p>Ihr habt mit dieser kleinen Beispiel-Klasse einen sehr einfachen Debugger zur Hand, mit dem ihr sehr schnell die langsamen Statements in eurem System finden k&#246;nnt. Ihr k&#246;nnt die Klasse nat&#252;rlich auch noch nach euren W&#252;nschen erweitern und auch andere Funktionen von MySQLi &#252;berschreiben. Wenn ihr, so wie ich, zentral an einer Stelle die Datenbankverbindung erzeugt k&#246;nnt ihr durch die Bedingung aus dem zweiten Quellcode eure gesamte Applikation debuggen.</p>
<p>Ich habe damit in meinem Projekt schon zwei &#252;berfl&#252;ssige Statements finden k&#246;nnen und einige andere Statements noch weiter optimieren k&#246;nnen. Ich hoffe, dass euch der Debugger auch bei eurer t&#228;glichen Arbeit unterst&#252;tzen kann. &#220;ber Anregungen und Kommentare Wrede ich mich wie immer freuen.</p>
]]></content:encoded>
			<wfw:commentRss>http://kau-boys.de/webentwicklung/mysql-unter-php-debuggen-mit-einer-eigenen-mysql-klasse/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Das Bermudadreieck des Internet Explorer &#8211; Oder: Wo zum Teufel ist mein Ordner hin?</title>
		<link>http://kau-boys.de/webentwicklung/das-bermudadreieck-des-internet-explorer-oder-wo-zum-teufel-ist-mein-ordner-hin?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=das-bermudadreieck-des-internet-explorer-oder-wo-zum-teufel-ist-mein-ordner-hin</link>
		<comments>http://kau-boys.de/webentwicklung/das-bermudadreieck-des-internet-explorer-oder-wo-zum-teufel-ist-mein-ordner-hin#comments</comments>
		<pubDate>Wed, 03 Mar 2010 17:10:12 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Webentwicklung]]></category>
		<category><![CDATA[Internet Explorer]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://kau-boys.de/?p=790</guid>
		<description><![CDATA[Heute bin ich mal wieder auf ein sehr faszinierendes Problem mit dem Internet Explorer gesto&#223;en. Meine erste Vermutung war mal wieder ein Programmierfehler im vielgeliebten IE6, aber der Fehler trat auch im Internet Explorer 7 auf. Ich nutze in einem Projekt absolute Pfade in allen Dateinamen, Links und Formularen. Nun hatte ich aber im einem [...]]]></description>
			<content:encoded><![CDATA[<p>Heute bin ich mal wieder auf ein sehr faszinierendes Problem mit dem Internet Explorer gesto&#223;en. Meine erste Vermutung war mal wieder ein Programmierfehler im vielgeliebten IE6, aber der Fehler trat auch im Internet Explorer 7 auf.</p>
<p>Ich nutze in einem Projekt absolute Pfade in allen Dateinamen, Links und Formularen. Nun hatte ich aber im einem Formular dummerweise das Gleichheitszeichen nach dem Short Open Tag in PHP vergessen. Mein Formular sah also in verk&#252;rzter Form wie folgt aus: </p>
<pre class="brush: xml;">
&lt;form action=&quot;&lt;? ABSOLUTER_PFAD ?&gt;form.php&quot;&gt;
...
&lt;/form&gt;
</pre>
<p><span id="more-790"></span></p>
<p>Soweit so gut, aber im Grund durfte hierdurch kein Problem entstanden sein. Der absolute Pfad enthielt eine Angabe in der Form <code>http:/www.beispiel.de/formularordner</code>. Da nun dieser Pfad nicht zur Verf&#252;gung stand enthielt das <code>action</code> Attribut des Formulars nur den Wert <code>form.php</code>.</p>
<p>Das Formular wurde &#252;ber einen Link aufgerufen und somit befand sich der Nutzer innerhalb des &#8220;formularordner&#8221;. Wenn nun also der Pfad relativ angegeben wird, m&#252;sste das Formular in genau diesem Ordner gesucht werden. Einige Nutzer bekamen aber eine sch&#246;ne 404 Fehlermeldung. Da mir einer dieser Nutzer einen Screenshot des Dilemmas geschickt hat konnte ich feststellen, dass der Browser versuchte den Pfad <code>http./www.beispiel.de/form.php</code> zu &#246;ffnen. Hier war aber nat&#252;rlich kein Formular zu finden.</p>
<p>Ich konnte den Fehler dann beheben, indem ich das Gleichheitszeichen wieder an seine korrekte Stelle eingef&#252;gt habe. Dadurch kam es nicht mehr zu den falschen Aufrufen. Der Vollst&#228;ndigkeit halber hier noch der korrekte Quellcode:</p>
<pre class="brush: xml;">
&lt;form action=&quot;&lt;?= ABSOLUTER_PFAD ?&gt;form.php&quot;&gt;
...
&lt;/form&gt;
</pre>
<p>Was aber genau beim Internet Explorer dazu gef&#252;hrt hat, dass er den Ordner einfach &#8220;verschluckt&#8221; hat konnte ich bisher noch nicht feststellen. Mir ist es auch bisher nicht gelungen den Fehler auf einem meiner Rechner zu reproduzieren. Es liegt auch nicht an einem grunds&#228;tzlichen Problem bei einem der Nutzer, denn nachdem sie den Browser neu ge&#246;ffnet hatten funktionierte pl&#246;tzlich alles wieder wie gewohnt.</p>
<p>Das erstaunlichste ist aber, dass dieser Fehler schon vor 13 Monaten im Skript vorhanden ist und erst jetzt von drei Nutzern entdeckt wurde, obwohl das betreffende Formular wohl hunderte Male am Tag genutzt wird.</p>
<p>Sollte jemand von euch schon einmal dieses Problem selbst erlebt haben und vielleicht sogar eine Erkl&#228;rung oder L&#246;sung daf&#252;r kennen w&#252;rde es mich wirklich brennend interessieren. Mit dem absoluten Link funktioniert es aber soweit wieder und ich hoffe, dass der Internet Explorer nun den Ordner beibeh&#228;lt.</p>
]]></content:encoded>
			<wfw:commentRss>http://kau-boys.de/webentwicklung/das-bermudadreieck-des-internet-explorer-oder-wo-zum-teufel-ist-mein-ordner-hin/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zeilen-Duplizierer mit AutoComplete Felder nutzen</title>
		<link>http://kau-boys.de/webentwicklung/zeilen-duplizierer-mit-autocomplete-felder-nutzen?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=zeilen-duplizierer-mit-autocomplete-felder-nutzen</link>
		<comments>http://kau-boys.de/webentwicklung/zeilen-duplizierer-mit-autocomplete-felder-nutzen#comments</comments>
		<pubDate>Wed, 17 Feb 2010 13:18:55 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Webentwicklung]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Prototype]]></category>
		<category><![CDATA[Scriptaculous]]></category>

		<guid isPermaLink="false">http://kau-boys.de/?p=697</guid>
		<description><![CDATA[ich bekam heute in einem Kommentar die Frage gestellt, ob mein Zeilen-Duplizierer aus dem Beitrag: Einfacher Zeilen-Duplizierer mit Prototype auch auf Feldern funktioniert, die die Scriptaculous Ajax.AutoCompleter Funktion verwenden. Ich nutze den Duplizierer selbst in einem Formular, das solche Felder enth&#228;lt. Meine erste Fassung entsprach dabei dem Einzeiler aus dem vorherigen Beitrag. Das Problem dabei [...]]]></description>
			<content:encoded><![CDATA[<p>ich bekam heute in einem Kommentar die Frage gestellt, ob mein Zeilen-Duplizierer aus dem Beitrag: <a href="http://kau-boys.de/webentwicklung/einfacher-zeilen-duplizierer-mit-prototype">Einfacher Zeilen-Duplizierer mit Prototype</a> auch auf Feldern funktioniert, die die <a href="http://wiki.github.com/madrobby/scriptaculous/ajax-autocompleter">Scriptaculous Ajax.AutoCompleter</a> Funktion verwenden.</p>
<p>Ich nutze den Duplizierer selbst in einem Formular, das solche Felder enth&#228;lt. Meine erste Fassung entsprach dabei dem Einzeiler aus dem vorherigen Beitrag. Das Problem dabei ist allerdings, dass die AutoCompleter Funktion beim Erzeugen mit dem Felder verkn&#252;pft wird, auf das sie angewendet werden soll. Wenn man nun dieses Feld kopiert wird nicht eine neue Instanz des Ajax.AutoCompleter erzeugt, sondern die Referenz auf das alte Feld mit kopiert. Ein Eintrag im neu erzeugten Feld aktiviert also die AutoCompleter Funktion des vorherigen Feldes.</p>
<p><span id="more-697"></span></p>
<p>Um dieses Problem zu l&#246;sen hatte ich die erweiterte Funktion mit den beiden Callback-Funktionen erstellt. Damit ist es m&#246;glich die Referenz zum vorherigen Feld zu l&#246;sen und eine neue Instanz des Ajax.AutoCompleter nach dem Erzeugen der Kopie zu erstellen. Hier aber zuerst noch einmal die Funktion selbst. Ich habe mittlerweile auch eine Option zum Fokussieren des ersten Feldes in der Kopie hinzugef&#252;gt:</p>
<pre class="brush: jscript;">
function addRow(selector, options){
	var lastRow = $$(selector).last();
	var newRow = lastRow.cloneNode(true);
	if (options.reset) {
		newRow.select('select', 'textarea', 'input').each(function(elm){
			elm.clear().checked = '';
		});
	}
	if(options.beforeInsert) options.beforeInsert(newRow);
	lastRow.insert({'after': newRow});
	if(options.afterInsert) options.afterInsert(newRow);

	if (options.focusFirst) {
		newRow.select('input', 'select', 'textarea').first().focus();
	}
}
</pre>
<p>Um die Ajax.Autocompleter Funktion nutzen zu k&#246;nnen ben&#246;tigt jedes Feld eine eindeutige ID. Nehmen wir also an, wir haben folgendes erstes Feld f&#252;r unser Formular (hier ein Beispiel aus dem Artikel: <a href="http://kau-boys.de/webentwicklung/google-maps-suggest-adress-autovervollstaendigung-mit-scriptaculous">Google Maps Suggest – Adress-Autovervollst&#228;ndigung mit Scriptaculous</a>):</p>
<pre class="brush: xml;">
&lt;form id=&quot;addressform&quot; action=&quot;address_save.php&quot; class=&quot;niceform&quot;&gt;
	&lt;fieldset&gt;
		&lt;legend&gt;Choose an address&lt;/legend&gt;
		&lt;dl&gt;
			&lt;dt&gt;&lt;label for=&quot;address&quot;&gt;Address:&lt;/label&gt;&lt;/dt&gt;
			&lt;dd&gt;&lt;input type=&quot;text&quot; id=&quot;address&quot; name=&quot;address[]&quot; style=&quot;width: 300px;&quot; /&gt;&lt;/dd&gt;
		&lt;/dl&gt;
	&lt;/fieldset&gt;
	&lt;fieldset&gt;
		&lt;input type=&quot;submit&quot; value=&quot;Send!&quot; /&gt;
	&lt;/fieldset&gt;
&lt;/form&gt;
&lt;div id=&quot;adresse_choices&quot; class=&quot;autocomplete&quot;&gt;&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
	new Ajax.Autocompleter('address', 'adresse_choices', 'get_addresses.php');
&lt;/script&gt;
</pre>
<p>Wichtig sind hierbei nat&#252;rlich die eckigen Klammern am Ende des Name Attributs, damit auch alle kopierten Werte mit&#252;bertragen werden. Damit wir einer Kopie dieses Feldes eine neue Instanz hinzuf&#252;gen k&#246;nnen, m&#252;ssen wir beim Kopieren auch die ID ver&#228;ndern. Dazu schreiben wir uns eine kleine Callback-Funktion, die genau das erledigt:</p>
<pre class="brush: jscript;">
function activateAutocomplete(newRow){
	var addressInput = $A(newRow.select('input')).first();
	addressInput.id += 1;
	addressInput.stopObserving();
	new Ajax.Autocompleter(addressInput.id, 'adresse_choices', 'get_addresses.php');
}
</pre>
<p>In der 2. Zeile selektieren wir das erste Element innerhalb der neuen Zeile (wir nehmen hier also an, dass es sich dabei um das AutoCompleter Feld handelt). Diesem f&#252;gen wir in der 3. Zeile zus&#228;tzlich zur ID eine 1 hinzu. Es entstehen also Felder nach dem Muster <code>"address1", "address11"</code> usw. Das reicht aus um die Felder genau zu referenzieren.<br />
In der 4. Zeile kommt die schon angesprochene Funktion zum Einsatz, die das Autocomplete f&#252;r das Feld deaktiviert. Zu guter Letzt erzeugen wir eine neue Instanz des Ajax.Autocompleter. Wir k&#246;nnen dabei als zweiten Parameter dasselbe DIV Element f&#252;r die Vorschl&#228;ge verwenden, da es ja nicht m&#246;glich ist, gleichzeitig in zwei Felder etwas einzutippen. Das DIV wird automatisch durch Scriptaculous unter das Feld positioniert, in dem es verwendet wird.</p>
<p>Damit das ganze nun auch dupliziert werden kann, f&#252;gen wir noch einen entsprechenden Link ein. Dieser muss dann die Callback-Funktion als zweiten Parameter in der Funktion erhalten. Ich verwende hier ein SPAN Element mit einem onclick Event. Es geht aber auch mit einem gew&#246;hnlichen Link:</p>
<pre class="brush: xml; gutter: false;">
&lt;span class=&quot;add&quot; onclick=&quot;addRow('#addressform dl', {reset : true, afterInsert: activateAutocomplete})&quot;&gt;Adresse hinzuf&#252;gen&lt;/span&gt;
</pre>
<p>Es wird durch den Selektor <code>"#addressform dl"</code> die gesamte Definition inklusive des Label kopiert. Ihr k&#246;nnt aber auch eine andere HTML Struktur wie z.B. eine unsortierte Liste verwenden.</p>
<p>Das war auch schon alles. Das Beispiel k&#246;nnt ihr euch hier ansehen und auch den Quellcode dazu runterladen:</p>
<p><a href="http://kau-boys.de/beispiele/google_maps_suggest/duplicate.html">Beispiel</a><br />
<a href="http://kau-boys.de/beispiele/google_maps_suggest/google_maps_suggest_duplicate.zip">Download</a></p>
<p>Ich hoffe, dass euch die erweiterte Anwendung gefallen hat und vielleicht auf neue Ideen gebracht hat. Wenn ihr eine andere Anwendung kennt, bei der Ihr nicht weiterkommt w&#252;rde ich mich wie immer &#252;ber einen Kommentar sehr freuen.</p>
]]></content:encoded>
			<wfw:commentRss>http://kau-boys.de/webentwicklung/zeilen-duplizierer-mit-autocomplete-felder-nutzen/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Backend Localization Plugin funktioniert nun auch mit PHP4</title>
		<link>http://kau-boys.de/wordpress/backend-localization-plugin-funktioniert-nun-auch-mit-php4?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=backend-localization-plugin-funktioniert-nun-auch-mit-php4</link>
		<comments>http://kau-boys.de/wordpress/backend-localization-plugin-funktioniert-nun-auch-mit-php4#comments</comments>
		<pubDate>Sun, 07 Feb 2010 14:40:31 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://kau-boys.de/?p=687</guid>
		<description><![CDATA[Anfang der Woche bekam ich einen Kommentar zu meinem Backend Localization Plugin mit dem Hinweis, dass es nicht mit PHP4 funktioniert. Da ich schon lange PHP5 nutze und auch versuche meinen Quellcode &#252;bersichtlich zu gestalten, habe ich in meinem Plugin einige Funktionen und Eigenschaften genutzt, die es f&#252;r PHP4 noch nicht gab. Der Kommentator, der [...]]]></description>
			<content:encoded><![CDATA[<p>Anfang der Woche bekam ich einen Kommentar zu meinem <a href="http://kau-boys.de/wordpress/kau-boys-backend-localization-plugin">Backend Localization Plugin</a> mit dem Hinweis, dass es nicht mit PHP4 funktioniert. Da ich schon lange PHP5 nutze und auch versuche meinen Quellcode &#252;bersichtlich zu gestalten, habe ich in meinem Plugin einige Funktionen und Eigenschaften genutzt, die es f&#252;r PHP4 noch nicht gab.</p>
<p>Der Kommentator, der den Fehler gefunden hat, konnte auch selbst am n&#228;chsten Tag schon eine L&#246;sung finden, die er <a href="http://www.est322.com/2010/02/kau-boys-backend-localization-plugin-wordpress/">auf seinem eigenen Blog</a> sowie als weiteres Kommentar hinterlassen hat. An dieser Stelle nochmals vielen Dank an David.</p>
<p>Ich versuche Fehler, die mir mitgeteilt werden immer innerhalb von wenigen Tagen zu beheben. Dazu bin ich nat&#252;rlich darauf angewiesen, dass mir diese auch mitgeteilt werden. Bei WordPress kann es sehr oft vorkommen, dass sich zwei Plugins nicht zusammen vertragen. Wenn ihr also mit einem meiner Plugins ein Problem feststellen solltet, dann scheut euch nicht mir das mitzuteilen. Ich werde gerne versuchen das Problem zu beheben.</p>
]]></content:encoded>
			<wfw:commentRss>http://kau-boys.de/wordpress/backend-localization-plugin-funktioniert-nun-auch-mit-php4/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Arrays und andere komplexe Daten mit PHP in einer MySQL-Datenbank speichern</title>
		<link>http://kau-boys.de/webentwicklung/arrays-und-andere-komplexe-daten-mit-php-in-einer-mysql-datenbank-speichern?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=arrays-und-andere-komplexe-daten-mit-php-in-einer-mysql-datenbank-speichern</link>
		<comments>http://kau-boys.de/webentwicklung/arrays-und-andere-komplexe-daten-mit-php-in-einer-mysql-datenbank-speichern#comments</comments>
		<pubDate>Sun, 24 Jan 2010 00:11:06 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Webentwicklung]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://kau-boys.de/?p=643</guid>
		<description><![CDATA[Viele von euch werden wohl schon einmal vor dem Problem gestanden haben, dass sie ein Array oder ein Objekt in der Datenbank speichern mussten. Hier m&#246;chte ich ein paar Vorschl&#228;ge unterbreiten, wie man das Problem nicht l&#246;sen sollte und wie es besser gehen kann. Der schlechte Weg Die einfachste und gleichzeitig auch schlechteste Methode w&#228;re [...]]]></description>
			<content:encoded><![CDATA[<p>Viele von euch werden wohl schon einmal vor dem Problem gestanden haben, dass sie ein Array oder ein Objekt in der Datenbank speichern mussten. Hier m&#246;chte ich ein paar Vorschl&#228;ge unterbreiten, wie man das Problem nicht l&#246;sen sollte und wie es besser gehen kann.</p>
<h2>Der schlechte Weg</h2>
<p>Die einfachste und gleichzeitig auch schlechteste Methode w&#228;re es, f&#252;r jeden Index eines Arrays oder jede Eigenschaft eines Objekts eine neue Spalte zu erzeugen. Bei diesem Ansatz werden unter Umst&#228;nden viele Zeilen erzeugt, die nicht immer einen Wert enthalten. Das ist zwar nicht so gravierend, aber durch diesen Ansatz erh&#246;ht sich auch die Anzahl der Spalten schnell auf eine un&#252;bersichtliche Anzahl. Zuletzt ist es hierbei bei jeder &#196;nderung des Arrays oder Objekts notwendig die Datenbanktabelle anzupassen.</p>
<p><span id="more-643"></span></p>
<h2>Eine bessere L&#246;sung gef&#228;llig?</h2>
<p>Etwas besser L&#246;sung, die fast immer funktioniert aber nicht f&#252;r alle F&#228;lle optimal ist, w&#228;re eine Serialisierung des Arrays oder Objekts. Hierbei werden die Daten mit der <a href="http://de.php.net/manual/en/function.serialize.php">serialize()</a> Funktion in einen String konvertiert und k&#246;nnen somit direkt in eine <a href="http://dev.mysql.com/doc/refman/5.1/en/char.html">VARCHAR</a> oder <a href="http://dev.mysql.com/doc/refman/5.1/en/blob.html">TEXT</a> Spalte speichert werden. Dabei muss der String nat&#252;rlich noch durch die Funktion <a href="http://de.php.net/manual/en/mysqli.real-escape-string.php">real_escape_string()</a> (in diesem Beispiel von der MySQLi Klasse) &#8220;escaped&#8221; werden.</p>
<h3>Speichern der Daten</h3>
<pre class="brush: php;">
// Das zu speichernde Array
$array = array('vorname' =&gt; 'Max', 'name' =&gt; 'Mustermann');
// Serialisieren der Daten
$string = serialize($array);
// Speichern der Daten
$mysqli-&gt;query('INSERT INTO table_name (array) VALUES (&quot;'.$mysqli-&gt;real_escape_string($string).'&quot;)'))
</pre>
<p>Das Beispiel setzt nat&#252;rlich voraus, dass die Variable <code>$mysqli</code> eine Instanz der MySQLi Klasse mit einer g&#252;ltige Verbindung zu einer Datenbank enth&#228;lt. Wir haben hier ein einfaches assoziatives Array, das serialisiert wird und anscheinend gespeichert wird. Die serialisierten Daten sehn in diesem Beispiel wie folgt aus:</p>
<h3>Der zu speichernde String</h3>
<pre class="brush: plain; gutter: false;">
a:2:{s:7:&quot;vorname&quot;;s:3:&quot;Max&quot;;s:4:&quot;name&quot;;s:10:&quot;Mustermann&quot;;}
</pre>
<p>Das Auslesen der Daten wird mit der Funktion <a href="http://de.php.net/manual/en/function.unserialize.php">unserialize()</a> durchgef&#252;hrt, die aus dem String wieder ein assoziatives Array erzeugt. Dazu lesen wir zuerst die Daten mit einem gew&#246;hnlichen Query aus und konvertieren anschlie&#223;end die Daten:</p>
<h3>Auslesen der Daten</h3>
<pre class="brush: php;">
// Auslesen der Daten
$result = $mysqli-&gt;query('SELECT array FROM table_name');
$row = $result-&gt;fetch_assoc();
$string = $row['array'];
// Unserialisieren der Daten
$array = unserialize($string);
</pre>
<p>Diese Methode zum Speichern von komplexen Daten funktioniert recht gut, aber der serialisierte String ben&#246;tigt dabei mehr Speicherplatz als f&#252;r ein normales assoziatives Array eigentlich n&#246;tig w&#228;re. Wie es eleganter geht zeige ich euch im n&#228;chsten Beispiel.</p>
<h2>Die elegante L&#246;sung mit JSON</h2>
<p>Das Format <a href="http://de.wikipedia.org/wiki/JSON">JSON</a> entspringt zwar der Skriptsprache JavaScript, aber es wird zu Zeiten von AJAX sehr oft auch serverseitig verwendet und erzeugt. Da die meisten serverseitigen Sprachen also auch JSON unterst&#252;tzen bietet es sich auch f&#252;r die Speicherung von komplexeren Datenstrukturen an. Die Anpassung des vorherigen Quellcodes beschr&#228;nkt sich dabei auch auf eine einzige Zeile. Wir ersetzen lediglich die serialize() durch die <a href="http://de.php.net/manual/en/function.json-encode.php">json_encode()</a> Funktion. Die Zeile 6 aus dem vorherigen Quellcode sieht dann folgt aus:</p>
<h3>Speichern der Daten</h3>
<pre class="brush: php; first-line: 3;">
...
$string = serialize($array);
...
</pre>
<p>Hierbei werden die Datei des assoziativen Arrays in die JSON Notation konvertiert. Hierbei ist der resultierende String kompakter als bei der Serialisierung, da die L&#228;nge der einzelnen Arraywerte nicht und Datentypen nicht gespeichert werden:</p>
<h3>Der zu speichernde String</h3>
<pre class="brush: jscript; gutter: false;">
{&quot;vorname&quot;:&quot;Max&quot;,&quot;name&quot;:&quot;Mustermann&quot;}
</pre>
<p>Beim Lesen der Daten aus der Datenbank m&#252;ssen sie dann selbstverst&#228;ndlich auch wieder in das urspr&#252;ngliche Format zur&#252;ck konvertiert werden. Dabei kommt wie ihr schon vermutet die Funktion <a href="http://de.php.net/manual/en/function.json-decode.php">json_decode()</a> zum Einsatz. Diese erzeugt aber normalerweise ein Standard-Objekt. Um das in unserem Beispiel verwendete assoziative Array zu erhalten, wird als zweiter Paramater &#8220;true&#8221; &#252;bergeben. Der &#196;nderung am Quellcode aus dem vorherigen Beispiel sieht dann wie folgt aus:</p>
<h3>Auslesen der Daten</h3>
<pre class="brush: php; first-line: 5;">...
$array = json_decode($string, true);
</pre>
<p>Die Verwendung von JSON sichert nicht nur die Daten sondern auch die Schl&#252;ssel eines Arrays. Dabei spielt es keine Rolle, ob das Array assoziativ ist oder Zahlen als Schl&#252;ssel verwendet. Auch wird die Sortierung dabei nicht ver&#228;ndert. Wer lediglich die Werte eines Array speichern m&#246;chte, also keine Schl&#252;ssel ben&#246;tigt, kann auch einen noch einfacheren Weg gehen.</p>
<h2>Array in der Datenbank light</h2>
<p>Der einfachste Werte mehrere Daten eines Array in einer Datenbank zu speichern sind die Funktionen <a href="http://de.php.net/manual/en/function.explode.php">explode()</a> und <a href="http://de.php.net/manual/en/function.implode.php">implode()</a>. Hierbei werden die einzelnen Werte des Arrays durch den &#8220;Delimiter&#8221;, den man als ersten Parameter angibt voneinander getrennt bzw. miteinander verbunden. Auch bei dieser Variante m&#252;ssen in den beiden Beispiel-Quellcodes nur die Funktionen f&#252;r die Umwandlung ausgetauscht werden. Zu beachte ist hierbei, dass der &#8220;Delimiter&#8221; nicht in den Werten vorkommen darf. Wer also beispielsweise ein Array mit Datumsangaben im Format 2010-01-23 mit implode verbinden m&#246;chte, darf nicht den Bindestrich als &#8220;Delimiter&#8221; verwenden.</p>
<p>Die Werte k&#246;nnen wie auch zuvor in einer VARCHAR oder TEXT Spalte gespeichert werden. Sehr hilfreich sind die beiden Funktionen aber auch beim Speichern in einer Spalte mit dem Spaltentyp <a href="http://">SET</a>. Da hierbei aber die Werte zus&#228;tzlich von Anf&#252;hrungsstrichen umgeben sein m&#252;ssen, muss der &#8220;Delimiter&#8221; auch die Anf&#252;hrungsstriche enthalten. Die implode Funktion w&#252;rde in der Speicherfunktion dann wie folgt eingesetzt:</p>
<h3>Speichern der Daten in einer SET Spalte</h3>
<pre class="brush: php; first-line: 3;">
...
$string = implode('&quot;, &quot;', $array);
...
</pre>
<h2>Fazit</h2>
<p>Wie ihr also seht, gibt es viele Wege komplexere Daten in einer Datenbank zu speichern. Das Beispiel mit JSON als Repr&#228;sentation sollte in jeder serverseitigen Skriptsprache funktionieren, die JSON unterst&#252;tzt. Solltet ihr PHP verwenden m&#252;sst ihr nat&#252;rlich auch sicherstellen, dass JSON bei euch aktiviert ist. Am einfachsten geht das wie immer mit Hilfe der <a href="http://de.php.net/manual/en/function.phpinfo.php">phpinfo()</a> Funktion, die in der Ausgabe einen &#8220;json&#8221; Abschnitt haben sollte.</p>
<p>Diejenigen von euch, die einen WordPress Blog haben und sich schon einmal die Datenbanktabelle angesehen haben, werden vermutlich die JSON Strings schon gesehen haben. Den WordPress speichert z.B. Arrays eines Plugins automatisch in der JSON Notation in der &#8220;options&#8221; Tabelle ab. Das macht es einem Pluginentwickler sehr einfach das Array zu speichern.</p>
<p>Ich hoffe, dass euch das kleine Tutorial weiterhelfen oder auf neue Ideen bringen konnte. &#220;ber Anregungen w&#252;rde ich mich wie immer sehr freuen.</p>
]]></content:encoded>
			<wfw:commentRss>http://kau-boys.de/webentwicklung/arrays-und-andere-komplexe-daten-mit-php-in-einer-mysql-datenbank-speichern/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PDF-Dokument ohne PDFlib mit PHP erzeugen</title>
		<link>http://kau-boys.de/webentwicklung/pdf-dokument-ohne-pdflib-mit-php-erzeugen?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=pdf-dokument-ohne-pdflib-mit-php-erzeugen</link>
		<comments>http://kau-boys.de/webentwicklung/pdf-dokument-ohne-pdflib-mit-php-erzeugen#comments</comments>
		<pubDate>Mon, 04 Jan 2010 17:45:47 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Webentwicklung]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://kau-boys.de/?p=581</guid>
		<description><![CDATA[Viele von euch werden wohl XAMPP benutzen, um lokal in PHP zu entwickeln und zu testen. In der Windows-Version enth&#228;lt es auch die PHP-Extension PDFlib, die aber leider auf vielen Hostingpaketen mit Linux als Betriebssystem nicht enthalten ist. Da PDFlib mehrere hundert Euro Lizenzgeb&#252;hren kostet stellen sich viele die Frage, ob es sinnvolle und kostenlose [...]]]></description>
			<content:encoded><![CDATA[<p>Viele von euch werden wohl <a href="http://www.apachefriends.org/">XAMPP</a> benutzen, um lokal in PHP zu entwickeln und zu testen. In der Windows-Version enth&#228;lt es auch die PHP-Extension <a href="http://www.pdflib.com/">PDFlib</a>, die aber leider auf vielen Hostingpaketen mit Linux als Betriebssystem nicht enthalten ist. Da PDFlib mehrere hundert Euro Lizenzgeb&#252;hren kostet stellen sich viele die Frage, ob es sinnvolle und kostenlose Alternativen gibt. Gl&#252;cklicherweise gibt es Alternativen und eine sehr umfangreiche m&#246;chte ich euch kurz vorstellen.</p>
<h2>Die kostenlose TCPDF Library</h2>
<p>Nachdem ich ein paar kostenlose PDF Klassen f&#252;r PHP getestet habe, hat sich ein klarer Sieger herausgestellt. <a href="http://www.tecnick.com/public/code/cp_dpage.php?aiocp_dp=tcpdf">Die Klasse TCPDF</a> zeichnet sich nicht nur durch seinen gro&#223;en Funktionsumfang, sondern auch durch seine sehr gute Quellcode-Kommentierung und die <a href="http://www.tecnick.com/pagefiles/tcpdf/doc/index.html">gute Dokumentation der Funktionen</a>.</p>
<p><span id="more-581"></span></p>
<h2>Ein einfaches Beispiel</h2>
<p>Um zu zeigen, wie einfach es ist eine PDF zu erzeugen hier ein kleines Beispiel. Und wie man es von einem Programmierbeispiel erwartet schreiben wir einen einfachen Text mit &#8220;Hallo Welt&#8221; in die PDF:</p>
<pre class="brush: php;">
&lt;?php
	require_once('tcpdf/tcpdf.php');

	$pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false);
	$pdf-&gt;setPrintHeader(false);
	$pdf-&gt;setPrintFooter(false); 

	$pdf-&gt;SetFont('times', 'BI', 20);
	$pdf-&gt;AddPage();
	$pdf-&gt;Cell(0, 10, 'Hallo Welt!', 0, 1, 'C', 0, 'http://kau-boys.de');
	$pdf-&gt;Output('example1.pdf', 'I');
?&gt;
</pre>
<p>Zuerst wird die Klasse per <a href="http://de.php.net/manual/de/function.require.php">require</a> eingebunden. Anschlie&#223;end erzeugen wir an neues TCPDF Objekt und weisen ihm als Orientierung Portrait (Hochformat) mit Millimeter als Einheit und einer Seitengr&#246;&#223;e im DIN A4 Format zu. Anschlie&#223;end deaktivieren wir noch die Standard Kopf- und Fu&#223;zeile.</p>
<p>Mit <a href="http://www.tecnick.com/pagefiles/tcpdf/doc/com-tecnick-tcpdf/TCPDF.html#methodSetFont">setFont()</a> k&#246;nnen wir die Schriftart, die Formatierung und die Schriftgr&#246;&#223;e festlegen. Jetzt f&#252;gen wir eine neue Seite hinzu und erzeugen eine Zelle mit unserem Text und einem Link. Zuletzt geben wir die Datei aus und der Browser zeigt sie direkt an. Alternativ kann auch der Download-Dialog erzwungen werden. Das Beispiel k&#246;nnt ihr euch hier ansehen:</p>
<p><a href="http://kau-boys.de/beispiele/tcpdf/example1.php">Beispiel</a></p>
<p>Das Beispiel ist stark vereinfach und nutzt nur die allern&#246;tigsten Funktionen. Auf der Seite von TCPDF findet ihr auch <a href="http://www.tecnick.com/public/code/cp_dpage.php?aiocp_dp=tcpdf_examples">eine Liste mit vielen weiteren Beispielen</a>, die ihr euch ansehen solltet. Sehr beeindruckend sind auch die Beispiele mit Formularen, die entweder mit Funktionen von TCPDF oder mit einem einfachen HTML-Formular erzeugt werden k&#246;nnen.</p>
<p>Ich hoffe, dass euch das kleine Beispiel weiterhelfen konnte und euch dazu ermutigt hat, es einfach einmal selbst auszuprobieren. &#220;ber Kommentare w&#252;rde ich mich wie immer sehr freuen.</p>
]]></content:encoded>
			<wfw:commentRss>http://kau-boys.de/webentwicklung/pdf-dokument-ohne-pdflib-mit-php-erzeugen/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Plesk Cronjob f&#252;r ein PHP-Skript mit Parametern einrichten</title>
		<link>http://kau-boys.de/webserver/plesk-cronjob-fuer-ein-php-skript-mit-parametern-einrichten?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=plesk-cronjob-fuer-ein-php-skript-mit-parametern-einrichten</link>
		<comments>http://kau-boys.de/webserver/plesk-cronjob-fuer-ein-php-skript-mit-parametern-einrichten#comments</comments>
		<pubDate>Mon, 23 Nov 2009 21:09:00 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Webserver]]></category>
		<category><![CDATA[Administration]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Plesk]]></category>
		<category><![CDATA[Server]]></category>

		<guid isPermaLink="false">http://kau-boys.de/?p=490</guid>
		<description><![CDATA[Bei vielen Webhosting Paketen gibt es die M&#246;glichkeit einen Cronjob einzurichten. Leider musste ich nach dem Umstieg von einem 1&#038;1 Managed Homepage Server auf einen 1&#038;1 Linux Root Server feststellen, dass diese Option im Control Center nicht mehr verf&#252;gbar war. Auch meine Suche nach dem &#8220;Crontab&#8221; in Plesk war erst einmal erfolglos, da die Funktion [...]]]></description>
			<content:encoded><![CDATA[<p>Bei vielen Webhosting Paketen gibt es die M&#246;glichkeit einen <a href="http://de.wikipedia.org/wiki/Cronjob">Cronjob</a> einzurichten. Leider musste ich nach dem Umstieg von einem 1&#038;1 Managed Homepage Server auf einen 1&#038;1 Linux Root Server feststellen, dass diese Option im Control Center nicht mehr verf&#252;gbar war. Auch meine Suche nach dem &#8220;Crontab&#8221; in Plesk war erst einmal erfolglos, da die Funktion an der beschriebenen Stelle nicht zu finden war. Durch Zufall habe ich sie dann doch gefunden.</p>
<p><img title="Plesk Hauptmen&#252; - Server" alt="Plesk Hauptmen&#252; - Server" src="http://kau-boys.de/wp-content/uploads/2009/11/Plesk-Hauptmen&#252;-Server.png"/></p>
<p><span id="more-490"></span></p>
<p>Um einen Cronjob anzulegen navigiert ihr im Hauptmen&#252; zum Abschnitt Server und w&#228;hlt dort &#8220;Geplante Aufgaben&#8221;. Anschlie&#223;end bekommt ihr eine Liste mit allen Benutzern angezeigt, die auf eurem Server vorhanden sind. Jedem dieser Benutzer k&#246;nnt ihr einen Cronjob zuteilen. Um ein PHP-Skript auszuf&#252;hren solltet ihr den Benutzer w&#228;hlen, der auf eurem Server den Apache-Server ausf&#252;hrt. Dies ist meistens der Benutzer namens &#8220;wwwrun&#8221;. Bl&#228;ttert also einfach auf die entsprechende Seite oder sucht nach dem Benutzer:</p>
<p><img title="Geplante Aufgaben" alt="Geplante Aufgaben" src="http://kau-boys.de/wp-content/uploads/2009/11/Geplante-Aufgaben.png"/></p>
<p>Nachdem ihr den Benutzer ausgew&#228;hlt habt klickt auf &#8220;Weiter&#8221;. Ihr gelangt nun auf die Seite mit den &#8220;Crontab-Aufgaben&#8221; f&#252;r den entsprechenden Benutzer. Hier hat sich also die Crontab Einstellung versteckt. Ihr k&#246;nnt nun oben eine &#8220;Neue Aufgabe hinzuf&#252;gen&#8221;:</p>
<p><img title="Crontab Aufgaben von wwwrun" alt="Crontab Aufgaben von wwwrun" src="http://kau-boys.de/wp-content/uploads/2009/11/Crontab-Aufgaben-von-wwwrun.png"/></p>
<p>In die Felder Minute, Stunde und Tag des Monat k&#246;nnt ihr entweder eine Zahl eingeben oder einen Stern, um den Cronjob f&#252;r jeden Wert auszuf&#252;hren. In dem Beispiel wird als der Cronjob an jedem Tag eines Monat um 00:00 Uhr ausgef&#252;hrt. Wenn ihr den Cronjob auch jeden Monat und an jedem Tag einer Woche ausf&#252;hren lassen m&#246;chtet, dann tragt unten ebenfalls einen Stern ein.</p>
<p><img title="Bearbeitung der Crontab-Aufgabe von wwwrun" alt="Bearbeitung der Crontab-Aufgabe" src="http://kau-boys.de/wp-content/uploads/2009/11/Bearbeitung-der-Crontab-Aufgabe-von-wwwrun.png"/></p>
<p>Wenn ihr ein lokales Programm oder ein PHP-Skript ohne Parameter starten m&#246;chtet, k&#246;nnt ihr einfach den Befehlsnamen in der Feld &#8220;Befehl&#8221; eintragen. Wenn ihr allerdings etwas in der Form &#8220;php /srv/www/vhosts/example.com/httpdocs/skript.php?var1=value&#8221; eintragt, dann versucht PHP die Datei mit dem Namen &#8220;skript.php?var1=value&#8221; zu finden, die es nat&#252;rlich nicht gibt. Ein sehr einfacher Trick dies zu l&#246;sen ist die Verwendung von <a href="http://de.wikipedia.org/wiki/Wget">wget</a>. Dieser Befehlt wird normalerweise dazu genutzt eine Datei von einer Website zu laden. Damit aber nicht eine Datei mit dem Namen &#8220;skript.php?var1=value&#8221; erzeugt wird, nutzen wir den Parameter &#8220;&#8211;spider&#8221;, der den Download unterdr&#252;ckt. Wir f&#252;hren also somit einfach nur ein PHP-Skript auf einer beliebigen URL aus. Sobald alle Einstellungen vorgenommen sind, k&#246;nnt ihr die Einstellungen mit einem Klick auf &#8220;OK&#8221; speichern.</p>
<p><img title="Crontab-Aufgaben von wwwrun aktualisiert" alt="Crontab-Aufgaben aktualisiert" src="http://kau-boys.de/wp-content/uploads/2009/11/Crontab-Aufgaben-von-wwwrun-aktualisiert.png"/></p>
<p>Ihr solltet nun in der &#220;bersicht euren eben erzeugt Cronjob sehen k&#246;nnen. Sobald der Zeitpunkt, den ihr angegeben habt erreicht ist, sollte das Skript ausgef&#252;hrt werden. Zu den Cronjobs wird ein Bereicht erstellt und an eine E-Mail-Adress verschickt. Diese k&#246;nnt ihr &#252;ber &#8220;Einstellungen&#8221; eintragen:</p>
<p><img title="Crontab-Eigenschaften von wwwrun bearbeiten" alt="Crontab-Eigenschaften bearbeiten" src="http://kau-boys.de/wp-content/uploads/2009/11/Crontab-Eigenschaften-von-wwwrun-bearbeiten.png"/></p>
<p>Bei meinen Cronjobs wurde bisher noch keine E-Mail verschickt. Eventuell wird auch nur im Fehlerfall eine Mail mit der Fehlermeldung verschickt. Oder aber mein Server leitet die Mail nicht korrekt an den externen 1&#038;1 Mailserver weiter, da es sich bei der E-Mail-Adresse um eine Domain handelt, die er selbst verwaltet. Sobald ich das R&#228;tsel gel&#246;st habe werde ich euch nat&#252;rlich davon berichten.</p>
<p>Ich hoffe der Artikel konnte euch weiterhelfen. Kennt ihr vielleicht auch noch eine tollt versteckte Funktion? Oder sucht ihr eine bestimmte Einstellung? &#220;ber Kommentare w&#252;rde ich mich wie immmer sehr freuen.</p>
]]></content:encoded>
			<wfw:commentRss>http://kau-boys.de/webserver/plesk-cronjob-fuer-ein-php-skript-mit-parametern-einrichten/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mail Versand per SMTP auf 1&amp;1 Linux Root Server einrichten</title>
		<link>http://kau-boys.de/webserver/mail-versand-per-smtp-auf-1un1-linux-root-server-einrichten?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=mail-versand-per-smtp-auf-1un1-linux-root-server-einrichten</link>
		<comments>http://kau-boys.de/webserver/mail-versand-per-smtp-auf-1un1-linux-root-server-einrichten#comments</comments>
		<pubDate>Thu, 05 Nov 2009 13:17:58 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Webserver]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Server]]></category>

		<guid isPermaLink="false">http://kau-boys.de/?p=466</guid>
		<description><![CDATA[Ich bin auf einen neues Problem mit dem Standard-Setup der 1&#038;1 Linux Root Server geto&#223;en. Vor dem Umzug auf den Root Server wurde ein 1&#038;1 Managed Homepage Server genutzt. Dieser hat keinen eigenen Mailserver installiert. Der Root Server hingegen verschickt die Mails direkt an den Empf&#228;nger und nicht wie der Managed Server &#252;ber den 1&#038;1 [...]]]></description>
			<content:encoded><![CDATA[<p>Ich bin auf einen neues Problem mit dem Standard-Setup der 1&#038;1 Linux Root Server geto&#223;en. Vor dem Umzug auf den Root Server wurde ein 1&#038;1 Managed Homepage Server genutzt. Dieser hat keinen eigenen Mailserver installiert. Der Root Server hingegen verschickt die Mails direkt an den Empf&#228;nger und nicht wie der Managed Server &#252;ber den 1&#038;1 SMTP Server. Doch wieso ist das ein Problem?</p>
<p>Nun, durch das zunehmende Problem von SPAM werden bei den meisten Mailanbeitern alle Mails von Severn abgelehnt, die nicht als vertrauersw&#252;rdiger Mailserver in einer Whitelist eingetragen sind. Der eigene Root-Server ist in diesen Listen allerdings fast nie gelistet. Beim Versuch eine Mail an einen Freemailer wie z.B. GMX zu senden resultiert dann in einer Ablehnung seitens GMX. Diese sehen in der Regel wie folgt aus:</p>
<p><span id="more-466"></span></p>
<pre class="brush: plain; gutter: false;">
Hi. This is the qmail-send program at sXXXXXXXX.
I'm afraid I wasn't able to deliver your message to the following addresses.
This is a permanent error; I've given up. Sorry it didn't work out.

&lt;user@gmx.de&gt;:
XXX.XXX.XX.XXX does not like recipient.
Remote host said: 550-5.7.1 {mx087} Sorry, your helo has been denied.
550 5.7.1 ( http://portal.gmx.net/serverrules ) Giving up on XXX.XXX.XX.XXX.
</pre>
<p>Die L&#246;sung des Problems ist die Versendung der Mail &#252;ber den SMTP-Server von 1&#038;1. Hierbei gibt es allerdings ein kleines Problem. Damit der 1&#038;1 Mailserver nicht als SPAM-Verteiler missbraucht werden kann, muss sich das sendende Skript an diesem Server authentifizieren. Dazu ist eine beliebiege E-Mail Adresse eures Servers notwendig. Ich w&#252;rde euch empfehlen dazu eine spezielle Adresse wie z.B. &#8220;websitesend@example.com&#8221; anzulegen.</p>
<p>Das w&#228;re soweit auch kein Problem, allerdings unterst&#252;tzen einigen Skriptsprachen nicht von Hause aus die SMTP-Authentifizierung an einem Server. Auch PHP bietet leider keinerlei Einstellungen f&#252;r die Authentifizierung. Lediglich der Mailserver kann angegeben werden, &#252;ber den die Mail versendet werden soll. Die <a href="http://de.php.net/manual/de/function.mail.php">mail()</a> Funktion von 1&#038;1 k&#246;nnt ihr also nicht verwenden. </p>
<p>Abhilfe schafft hier eine Mail-Klasse, die auch eine SMTP-Authentifizierung anbieten. Ich nutze schon seit l&#228;ngerem in allen Projekte die PHP-Klasse <a href="http://phpmailer.worxware.com/">PHPMailer</a>. Diese bietet auch eine SMTP-Authentifizierung. Einfache Beispiele zur <a href="http://phpmailer.worxware.com/index.php?pg=examplebsmtpna">Verwendung der SMTP-Authentifizierung mit PHPMailer</a> findest ihr auch auf der Website von PHPMailer. Ein Beispiel f&#252;r den Versand einer Mail &#252;ber den SMTP von 1&#038;1 k&#246;nnte wie folgt aussehen:</p>
<pre class="brush: php;">
require_once('class.phpmailer.php');
$mail = new PHPMailer();
$mail-&gt;CharSet = 'utf-8';
$mail-&gt;IsSMTP();
$mail-&gt;SMTPAuth = true;
$mail-&gt;Host = &quot;smtp.1und1.de&quot;;
$mail-&gt;Username = &quot;websitesend@example.com&quot;;
$mail-&gt;Password = &quot;password_for_websitesend&quot;;
$mail-&gt;AddReplyTo('your_mail_address@example.com');
$mail-&gt;Subject = 'Subject of the mail';
$mail-&gt;AltBody = 'Text for users without a HTML mail viewer';
$mail-&gt;MsgHTML('Text for users with a HTML ready mail viewer');
$mail-&gt;AddAddress('user@gmx.de');
if(!$mail-&gt;Send()) {
	echo &quot;Fehler beim Senden der Mail: &quot; . $mail-&gt;ErrorInfo;
} else {
	echo &quot;Mail wurde erfolgreich versandt!&quot;;
}
</pre>
<p>Zugegebenerma&#223;en sind das sehr vielke Zeilen f&#252;r den Mailversand einer einzelnen Mail. Aber leider ist es nicht sehr viel k&#252;rzen m&#246;glich. Damit ihr aber nicht in jedem Skript, in dem ihr eine Mail versenden m&#246;chtet, alles von neuem schreiben und bei &#196;nderungen in jedem Skript anpassen m&#252;sst, empfiehlt es sich die Zeilen 1.8 in eine PHP-Datei zu exporieren und diese per &#8220;require&#8221; in das Skript zu importieren, in der ihr die Mail verschicken wollt.</p>
<p>Die Verwendung der PHPMailer Klasse bietet aber auch ein paar Vorteile gegen&#252;ber der mail() Funktion von PHP. Ihr k&#246;nnt n&#228;mlich sehr einfach weitere Empf&#228;nger hinzuf&#252;gen, indem ihr die &#8220;$mail->AddAddress()&#8221; mehrfach anwendet. Es gibt auch eine Funktion f&#252;r Kopien: &#8220;$mail->AddCC()&#8221; und blinde Kopien: &#8220;$mail->AddBCC()&#8221; oder auch Anh&#228;nge: &#8220;$mail->AddAttachment()&#8221;. Seht euch dazu einfach mal die <a href="http://phpmailer.worxware.com/index.php?pg=methods">Liste der Methoden</a> an.</p>
<p>Ich hoffe, dass euch die kleine Anleitung helfen konnte. Wenn ihr noch Anmerkungen oder Fragen habt, oder auch eine andere gute PHP-Klasse oder eine entsprechende Funktion f&#252;r andere Skrtipsprachen kennt, w&#252;rde ich mich &#252;ber einen Kommentar sehr freuen.</p>
]]></content:encoded>
			<wfw:commentRss>http://kau-boys.de/webserver/mail-versand-per-smtp-auf-1un1-linux-root-server-einrichten/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Google Maps Suggest &#8211; Adress-Autovervollst&#228;ndigung mit Scriptaculous</title>
		<link>http://kau-boys.de/webentwicklung/google-maps-suggest-adress-autovervollstaendigung-mit-scriptaculous?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=google-maps-suggest-adress-autovervollstaendigung-mit-scriptaculous</link>
		<comments>http://kau-boys.de/webentwicklung/google-maps-suggest-adress-autovervollstaendigung-mit-scriptaculous#comments</comments>
		<pubDate>Tue, 06 Oct 2009 22:22:36 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Webentwicklung]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Prototype]]></category>
		<category><![CDATA[Scriptaculous]]></category>

		<guid isPermaLink="false">http://kau-boys.de/?p=364</guid>
		<description><![CDATA[Viele nutzen Autovervollst&#228;ndigungen auf ihrer Website. Es ist nicht nur eine sehr beeindruckende Technik, sondern zudem eine sehr nutzerfreundliche. Zus&#228;tzlich kann sie dazu dienen, dass in einem Formular m&#246;glichst g&#252;ltige Werte gespeichert werden. Selbstverst&#228;ndlich m&#252;ssen alle Daten serverseitig erneut &#252;berpr&#252;ft werden. Ich m&#246;chte heute zeigen, wie einfach es mit Scriptaculous m&#246;glich ist, eine Autovervollst&#228;ndigung mit [...]]]></description>
			<content:encoded><![CDATA[<p>Viele nutzen Autovervollst&#228;ndigungen auf ihrer Website. Es ist nicht nur eine sehr beeindruckende Technik, sondern zudem eine sehr nutzerfreundliche. Zus&#228;tzlich kann sie dazu dienen, dass in einem Formular m&#246;glichst g&#252;ltige Werte gespeichert werden. Selbstverst&#228;ndlich m&#252;ssen alle Daten serverseitig erneut &#252;berpr&#252;ft werden.</p>
<p>Ich m&#246;chte heute zeigen, wie einfach es mit Scriptaculous m&#246;glich ist, eine Autovervollst&#228;ndigung mit Google-Maps-Adressen umzusetzen. Da man per AJAX nicht auf fremde Website einen AJAX-Request durchf&#252;hren kann, m&#252;ssen wir ein Skript als Schnittstelle zwischen Google Maps und unserer Website verwenden. Fangen wir also dieses Mal mit der serverseitigen Script an:</p>
<p><span id="more-364"></span></p>
<pre class="brush: php;">
$json = json_decode(file_get_contents('http://maps.google.com/maps/geo?output=json&amp;oe=utf8&amp;sensor=false&amp;hl=de&amp;key=DEIN_GOOGLE_MAPS_API_KEY&amp;q='.urlencode($_REQUEST['address'])));

echo '&lt;ul&gt;';
if(!empty($json-&gt;Placemark)){
	foreach($json-&gt;Placemark as $value){
		echo '&lt;li&gt;'.$value-&gt;address.'&lt;/li&gt;';
	}
}
echo '&lt;/ul&gt;';
</pre>
<p>Zuerst stellen wir eine Suchanfrage an Google Maps, wobei wir den zu suchenden Text einfach im Parameter &#8220;q&#8221; &#252;bergeben. Der Parameter &#8220;output&#8221; gibt hierbei das von Google Maps zur&#252;ckgelieferte Format an. Ich habe hier JSON verwendet und wandle die Daten anschlie&#223;end mit der <a href="http://de.php.net/manual/de/function.json-decode.php">json_decode()</a> Funktion in ein Objekt um. Es kann aber genauso gut XML in Kombination mit einer XML Funktion sie <a href="http://de.php.net/manual/de/function.simplexml-load-string.php">simplexml_load_string()</a> verwendet werden. Da JSON da kompaktere Format ist habe ich mich in diesem Beispiel daf&#252;r entschieden.</p>
<p>Ein weiterer interessanter Parameter ist &#8220;hl&#8221;, der die Sprache der Adressen angibt. Viele werden den Parameter auch von der Google Suche kenne. Hier werden die Adressen also in deutsch zur&#252;ckgegeben. Mit Hilfe dieses einen Parameters k&#246;nnt ihr also sehr schnell die Funktion auf andere Spracheversionen eurer Seite anpassen.</p>
<p>Damit ihr &#252;berhaupt eine Anfrage an Google Maps stellen d&#252;rft, ben&#246;tigt ihr einen <a href="http://code.google.com/intl/de-DE/apis/maps/signup.html">kostenlosen Google Maps API Key</a>, den ihr an den &#8220;key&#8221; Parameter anh&#228;ngen m&#252;sst (Danke an paddy, der mich auf das Fehlen des Keys hingewiesen hat).</p>
<p>Nachdem die Daten von Google Maps empfangen wurden und im Objekt vorhanden sind, geben wir sie an die JavaScript Funktion zur&#252;ck. Dazu erzeugen wir einfach eine unsortierte Liste mit einem Eintrag pro gefundener Adresse.</p>
<p>Und jetzt kommen wir zum sehr umfangreichen clientseitigen Script. Dazu m&#252;ssen wir erst einmal ein Formular mit einem Textfeld erzeugen. Au&#223;erdem ben&#246;tigen wir ein DIV, in dem die Ergebnisse ausgegeben werden. Zu guter Letzt kommt dann noch das JavaScript, das den ganzen AJAX-Request und das Behandeln der Empfangenen Daten erledingen muss. Was aber sehr kompliziert klingt, ist recht kurz umgesetzt:</p>
<pre class="brush: xml; gutter: false;">
&lt;input type=&quot;text&quot; id=&quot;address&quot; name=&quot;address&quot; /&gt;
&lt;div id=&quot;adresse_choices&quot; class=&quot;autocomplete&quot;&gt;&lt;/div&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
	new Ajax.Autocompleter('address', 'adresse_choices', 'get_addresses.php');
&lt;/script&gt;
</pre>
<p>Die ganze Sache l&#228;sst sich mit einer einzigen Zeile JavaScript erledigen. Selbstverst&#228;ndlich m&#252;ssen dazu noch im Kopfbereich die &#8220;prototype.js&#8221; sowie anschlie&#223;end die &#8220;scriptaculous.js&#8221; eingebunden werden. Die Funktion <a href="http://wiki.github.com/madrobby/scriptaculous/ajax-autocompleter">Ajax.Autocompleter()</a> geh&#246;rt hierbei zum Funktionsumfang von Scriptaculous. Das fertige Resultat sieht dann wie folgt aus:</p>
<p><img src="http://kau-boys.de/wp-content/uploads/2009/10/google_maps_suggest.png" alt="Google Maps Suggest" title="Google Maps Suggest Beispiel Formular" /></p>
<p>Die hier verwendete ABC-Stra&#223;e ist kein Witz, sondern die Adresse von Google Deutschland. Eine weitere sch&#246;ne Eigenschaft von Google Maps ist die automatische Rechtschreibkorrektur, die bei fehlehaften Eingaben durchgef&#252;hrt wird. Selbst eine Eingabe wie &#8220;plazt der luftbl&#246;cke&#8221; f&#252;hrt trotzdem zu dem gew&#252;nschten Platz vor dem ehemaligen Berliner Flughafen. Um die Sache testen zu k&#246;nnen, habe ich hier ein kleines Beipsiel erstellt, dass ihr euch auch gerne im Quellcode runterladen k&#246;nnt. Ich habe zus&#228;tzlich noch eine Funktion verwendet, die den Suchbegriff hervorhebt:</p>
<p><a href="http://kau-boys.de/beispiele/google_maps_suggest/maps.html">Beispiel</a><br />
<a href="http://kau-boys.de/beispiele/google_maps_suggest/google_maps_suggest.zip">Download</a></p>
<p>Wir ihr also sehen k&#246;nnt, ist es mit der Ajax.Autocompleter() Funktion und einem servreseitigen Skript sehr einfach m&#246;glich, auch Daten von anderen Seiten auszuliefern. Das dazu ben&#246;tigte PHP Skript kann durch kleine Ver&#228;nderungen an die entsprechende extrene Datenquelle und das zur&#252;ckgelieferte Format angepasst werden. Die Funktion l&#228;sst sich aber nat&#252;rlich auch genauso gut mit jQuery oder einem anderen Framework umsetzen. Dazu muss dann aber eventuell das zur&#252;ckgelieferte Format des PHP Skript auch noch angepasst werden.</p>
<p>Ich hoffe das Beispiel hat euch gezeigt, wie vielf&#228;ltig sich eine Autovervollst&#228;ndigung einsetzen l&#228;sst. Habt ihr auch schon einmal mit externen Daten gearbeitet? Oder habt ihr vielleicht eine Idee, konntet sie aber bisher nicht umsetzen? &#220;ber ein Kommentar dazu w&#252;rde ich mich sehr freuen.</p>
]]></content:encoded>
			<wfw:commentRss>http://kau-boys.de/webentwicklung/google-maps-suggest-adress-autovervollstaendigung-mit-scriptaculous/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Die Grenzen der Frame-Weiterleitung sprengen</title>
		<link>http://kau-boys.de/webentwicklung/die-grenzen-der-frame-weiterleitung-sprengen?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=die-grenzen-der-frame-weiterleitung-sprengen</link>
		<comments>http://kau-boys.de/webentwicklung/die-grenzen-der-frame-weiterleitung-sprengen#comments</comments>
		<pubDate>Tue, 29 Sep 2009 18:09:29 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Webentwicklung]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Server]]></category>

		<guid isPermaLink="false">http://kau-boys.de/?p=315</guid>
		<description><![CDATA[Viele Hoster bieten g&#252;nstige Domains ohne Webhosting Komponenten an. Bei einigen Hoster wie z.B. Strato handelt es sich aber leider nur um Domains mit der M&#246;glichkeit der Frame-Weiterleitung. Das ist aber teilweise vor der Bestellung nicht zu sehen. Manch einer wird sich eventuell dar&#252;ber freuen, da er irgendwo ein kostenloses Hosting mit einer sehr langen [...]]]></description>
			<content:encoded><![CDATA[<p>Viele Hoster bieten g&#252;nstige Domains ohne Webhosting Komponenten an. Bei einigen Hoster wie z.B. Strato handelt es sich aber leider nur um Domains mit der M&#246;glichkeit der Frame-Weiterleitung. Das ist aber teilweise vor der Bestellung nicht zu sehen.</p>
<p>Manch einer wird sich eventuell dar&#252;ber freuen, da er irgendwo ein kostenloses Hosting mit einer sehr langen URL hat und durch die Frameweiterleitung den Besuchern immer eine kurze Domain pr&#228;sentieren kann. Doch die Sache hat auch ihre Haken.</p>
<p><span id="more-315"></span></p>
<h2>Das Lesezeichen-Problem</h2>
<p>Das navigieren innerhalb der Seite gestaltet sich f&#252;r den Besucher, wie er es erwartet. Er kann alle Links anklicken und der Hauptframe &#246;ffnet daraufhin die richtige Seite. Auch das Navigieren mit den &#8220;Vor&#8221; und &#8220;Zur&#252;ck&#8221; Buttons funktioniert tadellos. Aber sobald der Benutzer eine Seite gefunden hat, die er seinen Favoriten hinzuf&#252;gen m&#246;chte f&#228;ngt der &#196;rger an. Nicht nur, dass der Name des Lesezeichens oft nur die Domain enth&#228;lt, viel schlimmer ist, dass das Lesezeichen auch auf die selbige zeigt. Wenn der Besucher also sp&#228;ter das Lesezeichen aufruft kommt er nicht auf die gew&#252;nschte Seite, sondern auf die Startseite und muss von dort aus erst wieder m&#252;hsam auf die richtige Seite navigieren.</p>
<h2>Das Suchmaschinen-Problem</h2>
<p>Die meisten Suchmaschinen (Google eingeschlossen) haben Probleme mit framebasierten Seiten. Sie sehen oft nur das Frameset-Konstrukt und nicht die Inhalte der einzelnen Frames. Das bedeutet in den meisten F&#228;llen, das eure Internet-Seiten, die tausende von Seiten haben k&#246;nnen, bei Suchmaschinen genau EINE Seite als Eintrag enthalten. Und das ist die Startseite oder genauer gesagt das Frameset der Domain. Eine M&#246;glichkeit den Suchmaschinen doch die anderen Seiten mitzuteilen ist das Erstellen einer <a href="http://www.sitemaps.org/">Sitemap</a>. Diese solltet ihr dann aber manuell den Suchmaschinen mitteilen, da sie die Datei unter umst&#228;nden auch nicht finden k&#246;nnen. Dabei k&#246;nnt ihr entweder die Domain um die Seitennamen erweitern, oder aber die URL eures Webspace verwenden und um die Seitennamen erweitern.</p>
<h2>Die L&#246;sung</h2>
<p>Beide Probleme zeigen also, dass Frame-Weiterleitungen ein Relikt aus alten Zeiten sind und nicht mehr verwendet werden sollten. Aber was kann man tun, wenn der Hoster keine HTTP-Weiterleitung bietet, oder daf&#252;r einen Aufpreis verlangt? Ganz einfach, man bedient sich eines recht simplen Tricks. Dazu legt man zuerst einen Ordner mit beliebigen Namen auf dem Server an. Dann stellt man die Domain so ein, dass sie als Ziel den Ordner enth&#228;lt. In diesem Ordner erzeugt man dann eine index.php (oder eine Index-Datei einer andern Scriptsprache) mit folgendem Inhalt:</p>
<pre class="brush: xml; gutter: false;">
&lt;script type=&quot;text/javascript&quot;&gt;
	top.location.href = &quot;http://example.com&quot;;
&lt;/script&gt;
</pre>
<p>Dieser einfache JavaScript Snippet &#228;ndert die URL des Top-Frame auf einen neuen Wert. Wenn der Besucher also eure Domain aufruft, die lediglich eine Frame-Weiterleitung unters&#252;tzt, sorgt der Code daf&#252;r, dass das oberste Frameset auf eine andere URL umgeleitet wird. Hierbei m&#252;sste ihr natr&#252;lich &#8220;example.com&#8221; durch eure eigene Domain ersetzen (das &#8220;http://&#8221; dabei nicht vergessen). F&#252;r alle Besucher, die keine JavaScript Unterst&#252;tzung aktiviert haben solltet ihr zus&#228;tzlich einen NOSCRIPT Tag einf&#252;gen der einen Link enth&#228;lt:</p>
<pre class="brush: xml; gutter: false;">
&lt;noscript&gt;
	Sollten Sie nicht weitergeleitet werden, klicken Sie auf den folgenden Link:
	&lt;a href=&quot;http://example.com&quot; target=&quot;top&quot;&gt;http://example.com&lt;/a&gt;
&lt;/noscript&gt;
</pre>
<p>Der Link bekommt dabei das Attribut &#8220;traget&#8221; mit dem Wert &#8220;top&#8221;. Somit wird auch hier der Link im obersren Frameset aufgerufen. Um Benutzern, die ein Lesezeichen auf eure umzuleitende Domain haben, k&#246;nntet ihr auch noch den Request an die Domain anh&#228;ngen. Somit wird der Besucher dann auf die richtige Zielseite auf der anderen Domain umgeleitet. Zusammengesetzt sieht das ganze Beispiel dann wie folgt aus (oder &#228;hnlich in einer anderen Skriptsprache):</p>
<pre class="brush: php; gutter: false;">
&lt;script type=&quot;text/javascript&quot;&gt;
	top.location.href = &quot;http://example.com&quot;.$_SERVER['REQUEST_URI'];
&lt;/script&gt;
&lt;noscript&gt;
	Sollten Sie nicht weitergeleitet werden, klicken Sie auf den folgenden Link:
	&lt;?php echo '&lt;a href=&quot;http://example.com'.$_SERVER['REQUEST_URI'].'&quot; target=&quot;top&quot;&gt;http://example.com'.$_SERVER['REQUEST_URI'].'&lt;/a&gt;'; ?&gt;
&lt;/noscript&gt;
</pre>
<p>Diesen Codeblock platziert Ihr einfach im BODY Tag der Index-Seite. Dabei solltet ihr aber Besuchern ohne JavaScript eine sch&#246;nere Seite pr&#228;sentieren, als eine die nur den Link auf wei&#223;em Untergrund enth&#228;lt.</p>
<p><del datetime="2009-12-06T14:33:09+00:00">Da ich selbst noch eine Domain besitze, die ich leider zur Zeit noch nicht auf ein aktuelles Hostingpaket umziehen kann, k&#246;nnt ihr euch das ganze in einem kleinen Beispiel auch ansehen.</del> <a href="http://kau-boys.de/allgemein/der-blog-hat-eine-neue-domain">Die Domain ist mittlerweile endlich umgezogen</a> und daher habe ich nun das Beispiel auf die alte Subdomain abge&#228;ndert. Dazu solltet ihr einfach JavaScript vor&#252;bergehen deaktivieren, damit ihr auch die Seite und den Quelltext betrachten k&#246;nnt. Wenn ihr dann JavaScript wieder aktiviert und die Seite aktualisiert, solltet ihr auf meinen Blog umgeleitet werden.</p>
<p><a href="http://kau-boys.ramarka.de">Beispiel</a></p>
<p>Mit diesem Trick k&#246;nnt ihr also die Frame-Weiterleitung umgehen, aber ihr pr&#228;sentiert dann dem Besucher die entsprechend andere URL, als sie aufgerufen haben. Dies sollte aber einer sch&#246;nen URL aber daf&#252;r der eingeschr&#228;nkten Suchmaschinenfreundlichkeit und der Verhinderung von Lesezeichen bevorzugt werden. Ihr k&#246;nnt weiterhin die sch&#246;ne URL in Mails verbreiten und den Besucher trotzdem umleiten. Wenn ihr die Domain vollst&#228;ndig nutzen m&#246;chtet bleibt euch leider nichts anderes M&#246;glich, als diese in das Webhosting-Paket zu &#252;bertragen oder zu einem reinen Domain-Anbieter zu wechseln, der auch eine HTTP-Weiterleitung anbietet, auch wenn das eventuell einen Aufpreis bedeutet.</p>
]]></content:encoded>
			<wfw:commentRss>http://kau-boys.de/webentwicklung/die-grenzen-der-frame-weiterleitung-sprengen/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>CakeFest 2009 in Berlin</title>
		<link>http://kau-boys.de/webentwicklung/cakefest-berlin?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=cakefest-berlin</link>
		<comments>http://kau-boys.de/webentwicklung/cakefest-berlin#comments</comments>
		<pubDate>Mon, 13 Jul 2009 16:12:44 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[Webentwicklung]]></category>
		<category><![CDATA[cake]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://kau-boys.de/?p=26</guid>
		<description><![CDATA[Ich war dabei! Wie ist war und was es alles zu sehen gab seht k&#246;nnt ihr auf der offiziellen CakeFest website nachlesen. Empfehlenswert ist auch ein Blick auf die Twitter Nachrichten. Auf der Suche nach neuen Inspirationen zur PHP-Programmierung bin ich auf das Buch Webentwicklung mit CakePHP gesto&#223;en. Der Inhalt des Buchs beschrieb ziemlich genau [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.cakefest.org"><img class="alignright" title="cakefest Berlin" src="http://kau-boys.de/wp-content/uploads/2009/07/cakefest_berlin_gray_large.png" alt="cakefest 2009 in Berlin" width="222" height="91" /></a>Ich war dabei! Wie ist war und was es alles zu sehen gab seht k&#246;nnt ihr auf der <a href="http://www.cakefest.org">offiziellen CakeFest website</a> nachlesen. Empfehlenswert ist auch ein Blick auf die Twitter Nachrichten.</p>
<p>Auf der Suche nach neuen Inspirationen zur PHP-Programmierung bin ich auf das Buch <a href="http://webentwicklung-mit-cakephp.de/">Webentwicklung mit CakePHP</a> gesto&#223;en. Der Inhalt des Buchs beschrieb ziemlich genau das Projekt, dass ich f&#252;r meine Bachelor-Thesis gew&#228;hlt hatte. Ich habe mich auch damals an den Prinzipien von Ruby-on-Rails orientiert. Wenn das Buch ein halbes Jahr fr&#252;her erschienen w&#228;re, h&#228;tte ich viel Zeit und Probleme sparen k&#246;nnen.</p>
<p><span id="more-26"></span></p>
<p>Ich war von den Prizipien von CakePHP sehr &#252;berzeugt. Beim Besuch auf der <a href="http://www.cakephp.org">Website von CakePHP</a> bin ich dann auf das CakeFest aufmerksam geworden. Und wenn man die einmalige Gelegenheit hat, so ein Event in Berlin erleben zu k&#246;nnen muss man die Gelegenheit auch nutzen.</p>
<p>F&#252;r alle, die sich schon immer gew&#252;nscht haben Programme so leicht wie in Ruby-on-Rails programmieren zu k&#246;nnen, aber leider an PHP gebunden sind, ist CakePHP mit Abstand das beste Framework in PHP, da es die besten Ideen von Ruby-on-Rails aufgreift und durch viele weitere geniale Ideen erweitert.</p>
]]></content:encoded>
			<wfw:commentRss>http://kau-boys.de/webentwicklung/cakefest-berlin/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Kau-Boy&#8217;s AutoCompleter Plugin</title>
		<link>http://kau-boys.de/wordpress/kau-boys-autocompleter-plugin?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=kau-boys-autocompleter-plugin</link>
		<comments>http://kau-boys.de/wordpress/kau-boys-autocompleter-plugin#comments</comments>
		<pubDate>Thu, 02 Jul 2009 16:11:34 +0000</pubDate>
		<dc:creator>Bernhard</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Prototype]]></category>

		<guid isPermaLink="false">http://kau-boys.de/?p=24</guid>
		<description><![CDATA[Dieses Plugin verwendet den Ajax.Autocompleter von script.aculo.us bzw. die jQuery Autocomplete Funktoin um Beitr&#228;ge zu finden, die den Suchbegriff im Titel oder Inhaltstext enthalten. Der eingegebene Text kann in den Titel der Beitr&#228;ge und/oder im Inhalt gesucht werden. Es kann zus&#228;tzlich die Formatierung der Ergebnisse &#252;ber eine eigene CSS Datei an den Blog angepasst werden. [...]]]></description>
			<content:encoded><![CDATA[<p>Dieses Plugin verwendet den Ajax.Autocompleter von script.aculo.us bzw. die jQuery Autocomplete Funktoin um Beitr&#228;ge zu finden, die den Suchbegriff im Titel oder Inhaltstext enthalten.</p>
<p>Der eingegebene Text kann in den Titel der Beitr&#228;ge und/oder im Inhalt gesucht werden. Es kann zus&#228;tzlich die Formatierung der Ergebnisse &#252;ber eine eigene CSS Datei an den Blog angepasst werden. Es kann jeweils der Titel oder zus&#228;tzlich ein Teil des Inhalts angegeben werden, wobei hier auch die L&#228;nge des auszugebenden Inhaltes eingestellt werden kann.</p>
<p><span id="more-24"></span></p>
<h2>Installation:</h2>
<h3>Installation &#252;ber die WordPress Adminstrator-Seiten:</h3>
<ol>
<li>Gehe zur Admin-Seite <code>Plugins -&gt; Installieren</code></li>
<li>Suche nach <code>kau-boy</code> und w&#228;hle das Plugin aus</li>
<li>W&#228;hle die Aktion <code>Jetzt installieren</code></li>
<li>Klicke auf <code>Jetzt installieren</code></li>
<li>Aktiviere das Plugin &#252;ber den <code>Plugins</code> Men&#252;punkt in WordPress</li>
<li>Du musst eventuell die Einstellungen anpassen, gerade wenn dein Suchfeld eine andere ID als <code>s</code> hat</li>
</ol>
<h3>Installation unter Verwendung der WordPress Adminstrator-Seiten:</h3>
<ol>
<li>Lade die zip-Datei des Plugins herunter: <a href="http://downloads.wordpress.org/plugin/kau-boys-autocompleter.2.2.zip">kau-boys-autocompleter.2.2.zip</a></li>
<li>Gehe zur Admin-Seite <code>Plugins -&gt; Installieren</code></li>
<li>W&#228;hle den Link <code>Hochladen</code> unter <code>Plugins Installieren</code> &#220;berschrift</li>
<li>W&#228;hle die zip-Datei aus und klicke <code>Jetzt installieren</code></li>
<li>Aktiviere das Plugin &#252;ber den <code>Plugins</code> Men&#252;punkt in WordPress</li>
<li>Du musst eventuell die Einstellungen anpassen, gerade wenn dein Suchfeld eine andere ID als <code>s</code> hat</li>
</ol>
<h3>Installation unter Verwendung von FTP</h3>
<ol>
<li>Lade die zip-Datei des Plugins herunter: <a href="http://downloads.wordpress.org/plugin/kau-boys-autocompleter.2.2.zip">kau-boys-autocompleter.2.2.zip</a></li>
<li>Entpacke es und lade es in dein <code>/wp-content/plugins/</code> Verzeichnis hoch</li>
<li>Aktiviere das Plugin &#252;ber den <code>Plugins</code> Men&#252;punkt in WordPress</li>
<li>Du musst eventuell die Einstellungen anpassen, gerade wenn dein Suchfeld eine andere ID als <code>s</code> hat</li>
</ol>
<h2>Screenshots:</h2>
<h3>Screenshot des Plugins in einem neuen WordPress blog</h3>
<p><img title="Screenshot des Plugins in einem neuen WordPress blog" src="http://kau-boys.de/wp-content/uploads/2009/08/screenshot-1.png" alt="Screenshot des Plugins" /></p>
<h3>Screenshot der Einstellungsseite (auch in englisch erh&#228;ltlich)</h3>
<p><img title="Screenshot der Einstellungsseite (auch in englisch erh&#228;ltlich)" src="http://kau-boys.de/wp-content/uploads/2009/08/screenshot-2-de.png" alt="Screenshot der Einstellungsseite" /></p>
<h2>Versionsgeschichte:</h2>
<ul>
<li><strong>2.2</strong> Deaktivieren der Suche f&#252;r Suchfelder im Adminbereich und Erm&#246;glichen der Verwendung zusammen mit dem relevanssi Plugin</li>
<li><strong>2.1</strong> Hinzuf&#252;gen einer neuen Version von jQuery Autocomplete</li>
<li><strong>2.0.1</strong> Entfernen von &#8220;short open tags&#8221;, die auf blogs die Fehler verursachen die &#8220;short_open_tag&#8221; nicht auf &#8220;On&#8221; gesetzt haben</li>
<li><strong>2.0</strong> Autocompleter mit mehreren Textfelder auf einer Seite nutzbar machen, verbessern der K&#252;rzung des Inhalt von Artikeln</li>
<li><strong>1.9</strong> Beheben von Problemen mit PHP4, funktioniert nun auch mit qTranslate im &#8220;Query-Modus&#8221; (?lang=de)</li>
<li><strong>1.8</strong> Hinzuf&#252;gen der Einstellung f&#252;r die L&#228;nge des Titels und des Inhalts in den Ergebnissen</li>
<li><strong>1.7</strong> Erstzen von jQuery suggest durch jQuery autocomplete, da das suggest Plugin HTML Auszeichnungen zerst&#246;rt</li>
<li><strong>1.6.1</strong> Verwendung des id Attributs als Standard anstelle des name Attributs</li>
<li><strong>1.6</strong> Hinzuf&#252;gen der M&#246;glichkeit das Suchfeldes anhand des name Atrrbiuts auszuw&#228;hlen</li>
<li><strong>1.5.2</strong> Hinzuf&#252;gen der richtigen Kodierung zu <code>html_entity_decode()</code> um das Zerteilen von XML Enit&#228;ten zu verhindern</li>
<li><strong>1.5.1</strong> Fehler im AJAX repsonse behoben, der die Einstellung f&#252;r die Ergebnisfelder nicht geladen hat</li>
<li><strong>1.5</strong> Hinzuf&#252;gen Auswahlm&#246;glichkeiten f&#252;r die Such- und Ergebnisfelder</li>
<li><strong>1.4.1</strong> Aktualisierung der &#220;bersetzungsdatei</li>
<li><strong>1.4</strong> Kombinieren der Styles f&#252;r jQuery und script.aculo.us, Hinzuf&#252;gen  einer Einstellung zur Multibyte-Kodierung</li>
<li><strong>1.3.5</strong> Fehler bei der <code>html_entity_decode()</code> Konvertierung beseitigt</li>
<li><strong>1.3</strong> Enfternen eines Kommentars in autocompleter.js.php, welcher eine PHP header warning  erzeugt hat</li>
<li><strong>1.2</strong> Verwendung von <code>html_entity_decode()</code> um das Zerteilen von Enit&#228;ten zu verhindern</li>
<li><strong>1.1</strong> Entfernen von WordPress shortcodes um leere oder falsche Seiten zu verhindern</li>
<li><strong>1.0</strong> M&#246;glichkeit jQuery ODER script.aculo.us zu verwenden, &#220;bersetzen der Einstellungsseite ins Deutsche</li>
<li><strong>0.4</strong> Hinzuf&#252;gen der Einstellung f&#252;r die Anzahl der Suchergebnisse und der eigenen CSS Date</li>
<li><strong>0.3</strong> Hinzuf&#252;gen der Einstellung f&#252;r die Suchfeld ID</li>
<li><strong>0.2</strong> Erste stabile Version</li>
</ul>
<p>Wenn dir dieses Plugin gef&#228;llt oder dir etwas fehlt, w&#252;rde ich mich freuen es zu erfahren. Hinterlasse einfach ein Kommentar auf dieser Seiter oder auf meiner <a href="http://wordpress.org/tags/kau-boys-autocompleter">WordPress Plugin Seite</a>.</p>
<p><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=6104701"><img style="border: 0pt none ;" src="http://kau-boys.de/wp-content/uploads/2009/07/btn_donate_LG_en_US.gif" alt="PayPal - The safer, easier way to pay online!" /></a> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&amp;hosted_button_id=6104638"><img style="border: 0pt none ;" src="http://kau-boys.de/wp-content/uploads/2009/07/btn_donate_LG_de_DE.gif" alt="PayPal - The safer, easier way to pay online!" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://kau-boys.de/wordpress/kau-boys-autocompleter-plugin/feed</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
	</channel>
</rss>
