<?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>Matu´s Blog - Webprogrammierung und jede Menge Tipps &#38; Tricks &#187; PHP</title>
	<atom:link href="http://einmal-am-tag.de/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://einmal-am-tag.de</link>
	<description>Das Weblog zum Thema Webprogrammierung &#38; Design:(X)HTML und CSS, PHP, mySQL, CMS u.v.m.</description>
	<lastBuildDate>Sat, 10 Apr 2010 14:37:37 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>WordPress memory_limit erhöhen</title>
		<link>http://einmal-am-tag.de/2009-06/wordpress-memory-limit-erhoehen/</link>
		<comments>http://einmal-am-tag.de/2009-06/wordpress-memory-limit-erhoehen/#comments</comments>
		<pubDate>Sat, 27 Jun 2009 01:12:20 +0000</pubDate>
		<dc:creator>Matu</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[memory_limit]]></category>
		<category><![CDATA[php.ini]]></category>
		<category><![CDATA[Webserver]]></category>
		<category><![CDATA[WP_MEMORY_LIMIT]]></category>

		<guid isPermaLink="false">http://einmal-am-tag.de/?p=1501</guid>
		<description><![CDATA[

In den letzten Tagen nach Erscheinen der neuen WordPress-Version häuften sich in den Blogs die Artikel zum Thema Speichererhöhung in Verbindung mit der Fehlermeldung 
Fatal error: Allowed memory size of &#8230; bytes exhausted &#8230; 
WordPress Deutschland hat dazu am 16. Juni 2009 eine gute Erklärung in den FAQ veröffentlicht. Besonders der Trick mit der Sprachdatei [...]]]></description>
			<content:encoded><![CDATA[
<!-- google_ad_section_start -->
<p>In den letzten Tagen nach Erscheinen der neuen WordPress-Version häuften sich in den Blogs die Artikel zum Thema Speichererhöhung in Verbindung mit der Fehlermeldung </p>
<blockquote><p><strong>Fatal error: Allowed memory size of &#8230; bytes exhausted &#8230; </strong></p></blockquote>
<p>WordPress Deutschland hat dazu am 16. Juni 2009 eine gute Erklärung in den <a href='http://faq.wordpress-deutschland.org/exhausted-php-memory/' title='WordPress-Speicher erhöhen'><acronym title='frequently asked questions/häufig gestellte Fragen'>FAQ</acronym></a> veröffentlicht. Besonders der Trick mit der Sprachdatei ist interessant (senkt bei mir den Speicherverbrauch um 13%).<br />
Am gleichen Tag wurde dazu ebenfalls ein kleiner Beitrag auf <a href='http://bueltge.de/mehr-speicher-fuer-wordpress/957/' title='Mehr Speicher für WordPress'>bueltge.de</a> veröffentlicht.<br />
Beide weisen auf das Plugin „WP-Memory-Usage“ von Alex Rabe hin, das </p>
<ul>
<li>die Version</li>
<li>den verfübaren Speicher</li>
<li>sowie den aktuellen Speicherbedarf der WordPress-Installation</li>
</ul>
<p> anzeigt.<br />
Dieses Plugin ermittelt mit den PHP-Funktionen <a href='http://us2.php.net/manual/en/function.memory-get-usage.php' title='PHP-Funktion memory_get_usage'><em>memory_get_usage()</em></a> den aktuellen Speicherverbrauch und mit <a href='http://us2.php.net/manual/en/function.ini-get.php' title='Funktion ini_get'><em>ini_get(&#8217;memory_limit&#8217;)</em></a> die Lokal zugewiesene Speichergröße. </p>
<p>An dieser Stelle möchte ich Ihnen gerne einen tieferen Einblick in die Materie bieten. <span id="more-1501"></span></p>
<p>Der Arbeitspeicher (memory_limit) für die einzelnen Hosts auf dem Webserver wird an 2 Stellen festgelegt. Die erste allumfassende Einstellung erfolgt durch den Webhoster in der <strong><em>php.ini</em></strong>.<br />
In dieser wichtigen Konfigurationsdatei sind sämtliche Einstellungen für den PHP-Server hinterlegt. Verständlicherweise unterbinden Web-Hoster den Zugriff auf diese Datei, da sich viele Benutzer einen Server teilen. Mietet man sich einen sogenannten Root-Server sieht das natürlich anders aus.<br />
Dort wird (unter vielen anderen Einstellungen) der <strong><em>memory_limit</em></strong> eingestellt, welcher dann als sogenannter <strong><em>master value</em></strong> für den gesamten Server und den darauf befindlichen einzelnen Hosts die maximal zur Verfügung stehende Speichergröße für PHP-Scripte vorgibt.</p>
<p>Dieser Wert bzw. die gesamte <strong><em>php.ini</em></strong> kann mit der PHP-Funktion <strong><em>phpinfo()</em></strong> ausgelesen werden. Wenn Sie das gerne machen möchten, dann führen Sie folgende Schritte aus:</p>
<ul>
<li>Legen Sie im Backend-Bereich von Wordpress eine neue Seite mit dem Titel <strong><em>Backend</em></strong> und einem kurzen Text an</li>
<li>Stellen Sie die Sichtbarkeit rechts oben in der &#8220;Veröffentlichen-Box&#8221; auf Privat (dadurch kann die Seite erstens nur von Ihnen und zweitens nur wenn Sie <strong>eingeloggt</strong> sind aufgerufen werden. Die php.ini sollte aus Sicherheitsgründen nur von Ihnen einsehbar sein)</li>
<li>
Fügen Sie nach dem Speichern der Seite folgendes in die <strong><em>page.php</em></strong> unterhalb des &#8220;Loop&#8221; Ihres Theme-Ordners ein:</p>
<pre>
<span style='color:#aaa'> /* .../wp-content/themes/ihr_theme/page.php */</span>
&lt;?php
if(is_page('backend')){
phpinfo();
}
?&gt;
<span style='color:#aaa'> /* Speichern nicht vergessen!
Anmerkung: Anstatt die page.php zu verändern,
kann diese auch kopiert und umbenannt werden
(backend.php).
Diese kann dann als Template beim Neuanlegen
der Seite ausgewählt werden.
Dadurch halten Sie die page.php "sauber"
und können in Zukunft noch weitere php-Scripte
einfügen ...*/</span>
</pre>
</li>
<li>
Rufen Sie nun die zuvor angelegte Seite auf, in dem Sie deren Permalink (z.B. http://ihre_domain/backend) in die Adresszeile Ihres Browser eingeben. Dazu müssen Sie sich wie schon erwähnt vorher eingeloggt haben (der Browser speichert das als Cookie ab).
</li>
</ul>
<p>Nun sollte die Seite mit der gesamten php.ini angezeigt werden. Suchen Sie dort (STRG+F) nach <strong><em>memory_limit</em></strong>. Es werden 3 Spalten angezeigt:</p>
<ul>
<li>Directive &#8211;> gibt den Namen an</li>
<li>Local Value &#8211;> gibt den lokal verfügbaren maximalen Speicher an (&#8230; der Ihrer WordPress-Installation in Ihrem Host-Verzeichnis zur Verfügung steht)</li>
<li>Master Value &#8211;> gibt den durch Ihren Webhoster freigegebenen bzw. vorgegebenen maximalen Speicher an (dieser Wert gildet auf dem gesamten Server für alle Hosts)</li>
</ul>
<p>Somit wären wir auch schon bei der zweiten Einstellungsmöglichkeit, dem <em>local value</em>. Local value &#8230; master value? Etwas verwirrend, oder?! Ging mir zuerst genauso. Vor allem das Zusammenspiel bzw. die Abhängigkeit brachte mich etwas ins Grübeln. </p>
<p>Wenn der Webhoster das maximale Speicherlimit für alle Hosts auf dem Server schon durch den <strong><em>master value</em></strong> in der <strong><em>php.ini</em></strong> festgelegt hat (auf die ich keinen Zugriff habe), kann ich diesen Wert etwa Lokal in meinem eigenen Verzeichnis hochschrauben und mir so mehr Speicher zuschieben, als alle anderen zur Verfügung haben?</p>
<p><strong><em>Richtig, genau so ist es!</em></strong></p>
<p>Aber nür, wenn der Webhoster das auch zuläßt.<br />
Dazu gibt es verschiedene Möglichkeiten. Eine wäre, in der <strong><em>wp-config.php</em></strong> die globale Variable <strong><em>WP_MEMORY_LIMIT</em></strong> neu zu setzen und ihr einen Wert zuzuweisen, der höher liegt als die Grundeinstellung von 32 MB (definiert in der <strong><em>wp-settings.php</em></strong>).</p>
<pre>
&lt;?php
...
define('WP_MEMORY_LIMIT', '64M');
...
?&gt;
</pre>
<p>Wobei die 65 MB nur ein Beispiel sind, ich konnte den Wert bei mir auch höher schrauben, &#8230;</p>
<p><img src="http://einmal-am-tag.de/wp-content/uploads/2009/06/memory_limit1.jpg" alt="Memory Limit1 in " width="645" height="49" /></p>
<p> &#8230; was mich etwas stutzig machte. Also habe ich mal bei meinem Webhoster nachgefragt und bekam folgende Antwort, die ich nur in Auszügen veröffentliche:</p>
<blockquote><p>
Hallo,</p>
<p>erst einmal möchte ich Ihnen mitteilen, dass ich bisher sehr zufrieden bin.<br />
Und nun eine kleine Frage:<br />
Ist es von Ihnen gewollt, dass der &#8216;memory_limit&#8217; in der &#8216;php.ini&#8217; lokal per htaccess oder ini_set() überschrieben werden kann?</p>
<p>Gruß<br />
Jörg Mathuszczyk
</p></blockquote>
<p>Darauf kam folgende Antwort:</p>
<blockquote><p>
Hallo Herr Mathuszczyk,</p>
<p>vielen Dank für Ihre Anfrage.</p>
<p>Dies ist gewollt, da einige Scripte dies benötigen. Wenn sich dadurch jedoch feststellt, das besagter Kunde damit den Server überlastet müssen wir einschreiten.</p>
<p>Bei weiteren Fragen stehen wir Ihnen gern zur Verfügung.</p>
<p>&#8230;
</p></blockquote>
<p>An dieser Stelle noch mal vielen Dank an den Support für die (sehr) schnelle Antwort.</p>
<p>Kommen wir nun zu einer weiteren Möglichkeit, den <em><strong>memory_limit</em></strong> hochzusetzen.<br />
Dazu benutzen wir die PHP-Funktion <a href='http://www.php.net/manual/de/function.ini-set.php' title='PHP-Funktion ini_set'><em><strong>ini_set()</em></strong></a> und fügen diese an Stelle der zuvor genannten <em>WP_MEMORY_LIMIT</em> in die <em>wp-config.php</em> ein. </p>
<pre>
&lt;?php
...
ini_set('memory_limit', '65M');
...
?&gt;
</pre>
<p>Auch dies funktionierte bei mir ohne Probleme. Ist auch logisch, denn beim Setzen von <em>WP_MEMORY_LIMIT</em> wird haargenau die gleiche Funktion benutzt, um den <em>memory_limit</em> festzulegen. Dies geschieht per Zuweisung in der <em>wp-settings.php</em>.</p>
<pre>
&lt;?php
/**
 * Used to setup and fix common variables and include
 * the WordPress procedural and class library.
 *
 * You should not have to change this file and allows
 * for some configuration in wp-config.php.
 *
 * @package WordPress
 */

if ( !defined('WP_MEMORY_LIMIT') )
	define('WP_MEMORY_LIMIT', '32M');

if ( function_exists('memory_get_usage') &#038;&#038; ( (int) @ini_get('memory_limit') < abs(intval(WP_MEMORY_LIMIT)) ) )
	<span style='color:red'>@ini_set('memory_limit', WP_MEMORY_LIMIT);</span>

 ...
</pre>
<p>Eine dritte Möglichkeit ermöglicht das Speicherlimit in der <strong><em>.htacces</em></strong>-Datei festzulegen, indem dort folgendes eingefügt wird:</p>
<pre>
<span style='color:red'>php_value memory_limit 65M</span>

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
...
</pre>
<p>Dieser Weg war bei mir ebenfalls möglich, muss aber wiederum durch  den jeweiligen Webhoster zugelassen werden.</p>
<p>Auch wenn es verlockend klingt, den Wert gleich um ein vielfaches hochzusetzen, rate ich davon dringend ab. Ein schlecht programmiertes oder fehlerhaftes Script (Plugin, &#8230;) könnte so den gesamten zur Verfügung stehenden Arbeitsspeicher &#8220;in Beschlag nehmen&#8221;, was den gesamten Server beinträchtigen würde. Aus diesem Grund empfehle ich einen eher kleinen Wert mit etwas Spielraum nach oben (65 MB sollten bei einem WordPress-Blog dicke ausreichen).<br />
Ansonsten würde ich nach Plugins Ausschau halten, die &#8220;mächtig Hunger haben&#8221;. Eine schnelle Senkung kann durch die oben bereits angesprochene Deaktivierung der deutschen Sprachdatei in der <em>wp-config.php</em> erzielt werden.</p>
<pre>
define ('WPLANG', 'de_DE');
<span style='color:#aaa'> /* hier 'de_DE' entfernen */</span>
define ('WPLANG', '');
</pre>
<p>Durch diese Maßnahme wird das Backend von WordPress zwar wieder in Englisch angezeigt (Grundeinstellung), senkt aber den Ressourcenverbrauch um einiges. Wenn Sie nicht erst seit kurzem mit WordPress arbeiten, sollte das nicht weiter stören.</p>
<p>Bietet Ihr Webhoster von Haus aus nur wenig Arbeitspeicher und das Limit kann auch nicht lokal durch die genannten Maßnahmen erhöht werden, wäre ein Wechsel anzuraten. Dadurch treten auch in Zukunft solche Probleme gar nicht erst auf.</p>
<!-- google_ad_section_end -->
]]></content:encoded>
			<wfw:commentRss>http://einmal-am-tag.de/2009-06/wordpress-memory-limit-erhoehen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quellcode strukturieren und kürzen!</title>
		<link>http://einmal-am-tag.de/2009-06/quellcode-strukturieren-und-kuerzen/</link>
		<comments>http://einmal-am-tag.de/2009-06/quellcode-strukturieren-und-kuerzen/#comments</comments>
		<pubDate>Mon, 22 Jun 2009 14:50:58 +0000</pubDate>
		<dc:creator>Matu</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Quellcode]]></category>
		<category><![CDATA[Ternary Operators]]></category>

		<guid isPermaLink="false">http://einmal-am-tag.de/?p=1434</guid>
		<description><![CDATA[

In der Programmierung, besonders bei größeren Projekten/ Scripten, wird der Quellcode schnell unübersichtlich und schwer wartbar. Wer schon einmal ein Programm/ Script mit mehr als 1000 Zeilen geschrieben hat, wird mir da sicherlich zustimmen. Aus diesem Grund empfiehlt es sich, den Quellcode zu kommentieren und übersichtlich einzurücken. Zu dem können if/else-Kontrollstrukturen und Datenbankabfragen verkürzt dargestellt [...]]]></description>
			<content:encoded><![CDATA[
<!-- google_ad_section_start -->
<p>In der Programmierung, besonders bei größeren Projekten/ Scripten, wird der Quellcode schnell unübersichtlich und schwer wartbar. Wer schon einmal ein Programm/ Script mit mehr als 1000 Zeilen geschrieben hat, wird mir da sicherlich zustimmen. Aus diesem Grund empfiehlt es sich, den Quellcode zu kommentieren und übersichtlich einzurücken. Zu dem können <em>if/else</em>-Kontrollstrukturen und Datenbankabfragen verkürzt dargestellt werden. In diesem Tutorial möchte ich Ihnen dazu einige Beispiele bieten.<span id="more-1434"></span></p>
<p><strong>Kommentare einsetzen</strong><br />
In der Programmierung sind Kommentare (Comments) meiner Meinung nach das Salz in der Suppe. Sie ermöglichen es uns auch noch nach Monaten, jeden Abschnitt des jeweiligen Quellcodes besser und somit schneller zu verstehen.  Dies ist besonders wichtig, wenn fremder (nicht von uns selbst programmierter) Code vorliegt. Ich habe mir angewöhnt, besonders komplexe Passagen direkt mit einem Kommentar zu versehen. In PHP gibt es dazu zwei Möglichkeiten:</p>
<pre>
<span style='color:#aaa;'>/*Einzeiliger Kommentar*/</span>
// einzeilige Kommentare können mit ’//’ (zwei Backslashes) in den Quellcode eingefügt werden

<span style='color:#aaa;'>/*Mehrzeiliger Kommentar*/</span>
/* mehrzeilige Kommentare werden mit einem
* beginnenden ’/*’ (Slash und folgendem Sternchen)
* eingeleitet und mit ’*/’ (also umgekehrt)
* wieder abgeschlossen.
* In jeder neuen Zeile empfehle ich ein
* Sternchen als Einleitung einzufügen
*/
</pre>
<p>Auch wenn Kommentare Mehrarbeit bedeuten, möchte ich Ihnen nahelegen, davon ausgiebig Gebrauch zu machen. Spätestens wenn ein älteres Projekt verändert/angepasst werden muss,  werden sie dies zu schätzen wissen. Zudem wird der Lerneffekt verstärkt, da Sie sich mit dem erstellten Quellcode intensiver auseinandersetzen.</p>
<p><strong>Quellcode einrücken</strong><br />
Genau wie beim Kommentieren erfordert das durchgehende Einrücken des Quellcodes zunächst mehr Aufwand (obwohl es bei mir eigentlich schon automatisch erfolgt). Aber neben der verbesserten Lesbarkeit wird durch diese Maßnahme vor allem die Fehlersuche enorm erleichert. Dabei haben sich folgende zwei Möglichkeiten/ Stile etabliert (<a href='http://de.wikipedia.org/wiki/Einr%C3%BCckungsstil' title='Wikipedia Einrückungsstile Programmierung'>Einrückunsstile</a>)</p>
<pre>
<span style='color:#aaa;'>/* Stil 1 */</span>
if($ausruf == 'Hallo') <span style='color:red'>{</span>
	echo "Er hat 'Hallo' gerufen";
<span style='color:red'>}</span> else  <span style='color:red'>{</span>
	echo "Er hat nichts gerufen";
<span style='color:red'>}</span>

<span style='color:#aaa;'>/* Stil 2 */</span>
if($ausruf == 'Hallo')
<span style='color:red'>{</span>
	echo "Er hat ‘Hallo’ gerufen";
<span style='color:red'>}</span>
else
<span style='color:red'>{</span>
	echo "Er hat nichts gerufen";
<span style='color:red'>}</span>
</pre>
<p>Die Einrückungstiefe kann dabei getrost selbst bestimmt werden. Einige nehmen einen ganzen &#8216;Tab&#8217;, andere nur zwei oder drei Leerzeichen. Ich denke, dabei kommt es auf die Verschachtelungstiefe an. </p>
<p>Ich persönliche ertappe mich regelmäßig dabei, dass ich Mal den einen und Mal den anderen Einrückungsstil verwende. Den ersteren Aufgrund meiner Java/C++-Erfahrung (der etwas mehr Platz spart) und den zweiten hinsichtlich PHP (den ich als etwas übersichtlicher empfinde). Des Weiteren achte ich darauf, dass z.B. Gleichheitszeichen bei Zuweisungen ordentlich untereinanderstehen.</p>
<pre>
$string    = 'Hallo Welt';
$boolean   = true;
$int       = 5;
...
</pre>
<p>Entscheiden Sie selber, wie Sie Ihren Quellcode überschaubarer gestalten! Viele Editoren besitzen bereits eine automatische Einrückung oder das sogenannte <em>Syntaxhighlighting</em>, wodurch dieser Schritt vereinfacht wird.</p>
<p><strong>Quellcode verkürzen</strong><br />
Dies ist ein heikles Thema und es gehört viel Erfahrung und eine Menge Grips dazu, Algorithmen oder einfacher gesagt die Programmierlogik zu verkürzen. Während der ersten Schritte, in denen man sich die Basics der Programmierung aneignet, kommt es meistens zu ausufernden Konstrukten, um z.B. eine Anweisung zu programmieren.<br />
Ausgiebiger Gebrauch von verschachtelten if/else-Kontollstrukturen führen zwar letztendlich ebenfalls zum Ziel, sind jedoch fehleranfälliger und verlangsamen das Programm/ Script (mal ganz abgesehen von der bereits zuvor angesprochenen schlechteren Übersichtlichkeit). </p>
<p>Während diverser Weiterbildungen war es ein beliebter „Wettbewerb“ unter den Teilnehmern, alles möglichst kurz zu programmieren. Die Königsklasse hierbei war der legendäre „Einzeiler“: Unter Verwendung der ausgeklügelsten Techniken (Stichworte: Modulo, Reguläre Ausdrücke, …) wurde mehrzeiliger Code zu einer einzigen Zeile komprimiert. </p>
<p>Ich habe dabei ein ums andere Mal große Augen bekommen, mir dies aber möglichst nicht anmerken lassen <img src='http://einmal-am-tag.de/wp-includes/images/smilies/icon_wink.gif' alt="Icon Wink in " class='wp-smiley' />  !<br />
Doch neben genug Gehirnschmalz und Erfahrung gibt es auch ein paar Techniken, die leicht erlernbar sind und den Quellcode ebenfalls kürzer und überschaubarer gestalten.<br />
Eine Möglichkeit besteht darin, einfache if/else-Kontrollstrukturen in einer einzigen Zeile auszuführen:</p>
<pre>
<span style='color:#aaa'>/* Lange Version */</span>

if(isset($_POST['color']))
{
	$backgroundcolor =  $_POST['color'];
}
else
{
	$backgroundcolor =  'white';
}

<span style='color:#aaa'>/* Kurze Version */</span>
$backgroundcolor = (isset($_POST['color'])) <span style='color:red; font-weight:bold;'>?</span> ($_POST['color'] <span style='color:red; font-weight:bold;'>:</span> 'white';
</pre>
<p>Das Beispiel ist aus der Luft gegriffen und bezieht sich auf PHP. Eine ähnliche Syntax gibt es auch für Java und C++ (&#8230;). Es handelt sich hierbei um die sogenannten &#8216;Ternary Operators&#8217; (engl. Dreifach-Operatoren). Am Anfang etwas gewöhnungsbedürftig, möchte man sie später (einmal verinnerlicht) nicht mehr missen.<br />
Mit dem PHP-Befehl <em>sprintf</em> läßt sich der Quellcode ebenfalls oftmals verürzt und übersichtlicher darstellen.</p>
<pre>
<span style='color:#aaa;'>/* Beipiel herkömmliche Schreibweise */</span>
&lt;?php
$query = "SELECT telefon
          FROM kunde
          WHERE vorname = '".addslashes($vorname)."'
          AND name = '".addslashes($name)."'
          AND strasse = '".addslashes($strasse)."'";
$result = mysql_query($query);
...
<span style='color:#aaa;'>/* Nicht sehr übersichlich, oder?!
Dann schauen Sie sich mal dieses Beispiel an*/</span>

$query = sprintf("SELECT telefon
                  FROM kunde
                  WHERE vorname= '%s'
                  AND name = '%s'
                  AND strasse = '%s'",
                  addslashes($vorname),
                  addslashes($name),
                  addslashes($strasse));
$result = mysql_query($query);
?&gt;
</pre>
<p>Hierbei werden im Quellcode Platzhalter (Literale) eingesetzt, die anschließend in der gleichen Reihenfolge durch die angefügten Parameter ersetzt werden.<br />
Ein <em>%s</em> bedeutet hierbei, dass an dieser Stelle ein String gesetzt wird. Es können auch Dezimalzahlen (<em>%d</em>) oder Zahlen vom Typ <em>float</em> (<em>%f</em>) übergeben werden. Zudem lassen sich neben anderen Angaben auch Ausrichtung und Länge einfügen, auf die ich hier aber nicht weiter eingehen werde (<a href='http://www.selfphp.de/funktionsreferenz/string_funktionen/sprintf.php' title='SELFPHP zu sprintf'>weiterführende Informationen</a>).</p>
<p>Tun Sie sich (und eventuell anderen) einen Gefallen und schreiben Sie lesbaren Quellcode!</p>
<!-- google_ad_section_end -->
]]></content:encoded>
			<wfw:commentRss>http://einmal-am-tag.de/2009-06/quellcode-strukturieren-und-kuerzen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamisches Stylesheet (Dynamic CSS)</title>
		<link>http://einmal-am-tag.de/2009-06/dynamisches-stylesheet/</link>
		<comments>http://einmal-am-tag.de/2009-06/dynamisches-stylesheet/#comments</comments>
		<pubDate>Sun, 14 Jun 2009 19:35:21 +0000</pubDate>
		<dc:creator>Matu</dc:creator>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Cascading Stylesheet]]></category>
		<category><![CDATA[Programmierung]]></category>

		<guid isPermaLink="false">http://einmal-am-tag.de/?p=1287</guid>
		<description><![CDATA[

Web 2.0 ist in aller Munde. Nachrichten werden zwischen einzelnen Webseiten ausgetauscht (Stichwort Abonnementdienste wie RSS/Atom). Weblogs schießen wie Pilze aus den Boden. Dynamische Webseiten (DHTML) sowie DOM-Scripting sind in der heutigen Zeit zum Standard geworden. Menüs klappen auf, Texte werden eingeblendet, Seiteninhalte lassen sich einfach verschieben … überall bewegt sich etwas. 
Es werden Techniken [...]]]></description>
			<content:encoded><![CDATA[
<!-- google_ad_section_start -->
<p><strong>Web 2.0</strong> ist in aller Munde. Nachrichten werden zwischen einzelnen Webseiten ausgetauscht (Stichwort Abonnementdienste wie <strong>RSS/Atom</strong>). <strong>Weblogs</strong> schießen wie Pilze aus den Boden. Dynamische Webseiten (<strong>DHTML</strong>) sowie <strong><acronym title='Document Object Model'>DOM</acronym></strong>-Scripting sind in der heutigen Zeit zum Standard geworden. Menüs klappen auf, Texte werden eingeblendet, Seiteninhalte lassen sich einfach verschieben … überall bewegt sich etwas. </p>
<p>Es werden Techniken eingesetzt, die Web-Anwendungen wie Desktop-Anwendungen aussehen lassen (Stichwort <strong>Ajax</strong>). Rein statische Seiten fristen in den Weiten des Internet nur noch ein Schatten-Dasein.<br />
Und wenn wir ehrlich sind, haben wir uns daran gewöhnt. </p>
<p>Wir erwarten, das Webprogrammierer -und Designer die Seiten so gestalten, das sie attraktiv und „<acronym title='Benutzerfreundlichkeit'>usability</acronym>“ daher kommen. Das Webseiten auch körperlich beeinträchtigten Menschen zugänglich sind (Stichwort Barrierefreiheit) und nach Möglichkeit in jedem Browser … zumindest einigermaßen … ähnlich aussehen. <span id="more-1287"></span></p>
<p>Es können Videos und Fotos betrachtet, Musik gehört und Spiele gespielt werden. Animationen, erstellt mit Java, Flash, Javascript oder als GIF-Bild, lassen Webseiten „leben“ (wenn sie uns nicht gerade stören).</p>
<p>Und da ich von diesen Dingen einfach fasziniert bin, habe ich mich daran gesetzt, dem <strong>Stylesheet</strong> meines Blogs mit Hilfe von PHP ebenfalls etwas Dynamik einzuhauchen. </p>
<p><strong>Anleitung dynamisches Stylesheet</strong><br />
Zuerst muss die Endung der normalen Stylesheet-Datei …</p>
<pre>
style.<span style='color:red;'>css</span>
</pre>
<p>&#8230; durch &#8230;</p>
<pre>
style.css.<span style='color:red;'>php</span>
</pre>
<p>&#8230; ersetzt werden.<br />
Eingebunden wird die neue dynamische Stylesheet-Datei wie gewohnt im Head-Bereich der Seite:</p>
<pre>
&lt;!DOCTYPE html PUBLIC …
&lt;html&gt;
  &lt;head&gt;
    <span style='color:red;'>&lt;link rel="stylesheet" type="text/css" href="pfad_zur_datei/style.css.php" /&gt;</span>
  &lt;/head&gt;
  &lt;body&gt;
  ...
  &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Nun wird im neuen Stylesheet innerhalb eines PHP-Blocks der <a href=' http://de.wikipedia.org/wiki/Internet_Media_Type' title='Wikipedia Content-Type'>Content-type</a> angegeben, da der Server beim Parsen sonst davon ausgeht, dass es sich hierbei um eine gewöhnliche HTML-Datei handelt. Dazu wird im Kopf der css.php-Datei folgendes deklariert:</p>
<pre>
&lt;?php
  <span style='color:red;'>header('Content-type: text/css');</span>
  <span style='color:#aaa;'> /*
    An dieser Stelle wird der Quellcode eingefügt.
    Mehr dazu später …
   */</span>
?&gt;

/* Begin Typography &#038; Colors */

body {

	font-size: 62.5%; /* Resets 1em to 10px */

	font-family: Arial, Helvetica, Sans-Serif;

	background: #063164; 

	color: #999;

	text-align: center;

	}
…
</pre>
<p>Nun „weiß“ der Server Bescheid, gibt die PHP-Datei als CSS-Datei an den Browser und dieser kann die Datei anschließend richtig interpretieren.</p>
<h5 class='trigger'>Erklärung</h5>
<div>
Im Gegensatz zu einer normalen Stylesheet-Datei, die der jeweilige Browser direkt durch den angegebenen Pfad im Head-Bereich der Webseite <acronym title='einliest'> „annektiert“</acronym>, wird die neue PHP-CSS-Datei zuerst vom Server (auf Grund der <span style='color:red;'>.php</span>-Endung!) durch den PHP-Parser geschickt.<br />
Dieser erkennt den eingefügten PHP-Block </p>
<pre>
&lt;?php
 …
?&gt;
</pre>
<p>und arbeitet den dort eingefügten Quellcode ab. Erst danach wird die (inhaltlich geänderte) Datei zurückgeschickt und steht nun dem jeweiligen Browser zur Verfügung. Dieser erkennt, genau wie der Besucher der Seite, durch die explizite Angabe des Content-Types eine ganz normale CSS-Datei. Der PHP-Code kann dagegen nicht eingesehen werden!
</p></div>
<p>Da mir diese Webseite neben dem Bloggen auch als „Bastelstube“ dient (siehe auch mein <a href='http://einmal-am-tag.de/kolophon/' title='Kolophon'>Kolophon</a>), um Webtechniken anzuwenden, hatte ich mir überlegt, die Hintergrundfarbe beim ersten Aufruf der Seite zufällig aus einem Pool von Hintergrundgrafiken generieren zu lassen. Diese sind bereits als PNG-Dateien auf dem <acronym title='Speicherplatz der Webseite bei einem Server-Hosting-Provider'>Webspace </acronym> hinterlegt und werden über den Name eingebunden.</p>
<pre>
   bg_hellgruen.png
   bg_blau.png
   bg_beige.png
   ...
</pre>
<p>Dazu legte ich zunächst ein Array an, in das die Namen derjenigen Grafiken einfügte wurde, die später angezeigt werden sollen.</p>
<pre>
$farben = array('weiss', 'schwarz', 'blau', 'gruen',
        'beige', 'hellblau', 'hellgruen', 'rose',
        'sand', 'grau_gruen');
</pre>
<p>Aus diesem wird ein zufälliges ausgewählt</p>
<pre>
 $zufall = array_rand($farben, 1);<span style='color:#aaa;'>/* ... die 1 kann bei einem
Wert auch weggelassen werden */</span>
 $zufalls_farbe = $farben[$zufall];
</pre>
<p>und danach in einem switch-Kontrollblock die Textfarbe an die jeweilige Hintergrundfarbe angepasst, um einen ausreichenden Kontrast zu garantieren.</p>
<pre>
switch ($zufalls_farbe) {
    case 'weiss':
     $_SESSION['textcolor'] = '#222';
        break;
    case 'beige':
      $_SESSION['textcolor'] = '#222';
        break;
    case 'hellblau':
      $_SESSION['textcolor'] = '#222';
        break;
    case 'oliv':
      $_SESSION['textcolor'] = '#222';
        break;
    case 'rose':
      $_SESSION['textcolor'] = '#222';
        break;
    case 'hellgruen':
      $_SESSION['textcolor'] = '#222';
        break;
    case 'sand':
      $_SESSION['textcolor'] = '#222';
        break;
    case 'grau_gruen':
      $_SESSION['textcolor'] = '#222';
        break;
    default:
      $_SESSION['textcolor'] = '#aaa';
        break;
  }
</pre>
<p>Anstatt des <em>switch</em>-Kontrollblocks kann natürlich auch eine if-Abfrage eingesetzt werden. Ich habe dies lediglich auf diese Art gelöst, um wieder mal mit der <em>switch</em>-Syntax zu arbeiten. Hinsichtlich der Geschwindigkeit dürften sich beide Möglichkeiten (auch bei größeren Datenmengen) nicht wesentlich unterscheiden (unter Programmierern führt dieser Aspekt gern zu ausufernden Diskussionen &#8211;> kürzer, schneller …).</p>
<p>Um die einmal ausgewählte Hintergrundfarbe während des Besuchs beizubehalten, wird noch eine Session-Variable erstellt. In dieser wird beim ersten Einlesen der css.php-Datei ebenfalls die zufällig generierte Hintergrundfarbe gespeichert. </p>
<pre>
 $_SESSION['color'] = $zufalls_farbe;
</pre>
<p>Dies wurde für die Textfarbe bereits schon im <em>switch</em> realisiert.<br />
Normalerweise legt der Browser die CSS- Datei (und noch einige andere Dateien, z.B. Grafiken) im eigenen Cache-Speicher ab und ein erneutes Einlesen ist bei Seitenwechsel nicht mehr nötig. Dadurch kann die Webseite nach dem ersten Aufruf schneller geladen werden. </p>
<p>Da dies aber nicht garantiert ist (was mir meine Erfahrungen auch bestätigen), wird bei jedem Einlesen überprüft, ob diese Session-Variable existiert. Sollte dies der Fall sein, erfolgt keine erneute Auswahl der Hintergrundfarbe, sondern es wird dann der gespeicherte Wert der Session-Variable verwendet. Dafür wird der gesamte Quellcode in eine Abfrage eingeschlossen, welche direkt überprüft, ob die Session-Variable bereits existiert.</p>
<pre>
if(!isset($_SESSION['color'])) {
...
}
<span style='color:#aaa;'>/* Nur wenn die SESSION-Variable noch nicht (!)
existiert, wird eine neue Farbe ausgewählt
*/</span>
</pre>
<p>Nun werden die gefüllten Variablen an den jeweiligen Stellen im normalen Stylesheet-Bereich eingefügt und mit dem <em>echo</em>-Befehl ausgegeben.</p>
<pre>
#header {
	background: transparent url('images/layout/<span style='color:green;'>bg_</span>&lt;?php
        if(isset($_SESSION['color'])) echo $_SESSION['color'];
        else echo 'bg_weiss'; ?&gt;<span style='color:green;'>.png</span>') repeat-y top center;
        <span style='color:#aaa;'>/* Der else-Block dient nur als Beispiel
        und dürfte nicht ausgeführt werden*/</span>
	}
...

#content {
	font-size: 1.35em;
        color:&lt;?php if(isset($_SESSION['textcolor'])) echo $_SESSION['textcolor']; else echo '#222'; ?&gt;;
	}
...
</pre>
<p>Durch diese Maßnahme bekommt jeder Besucher der Seite beim ersten Aufruf eine zufällige Hintergrundfarbe, die auch bei Seitenwechsel erhalten bleibt (es sei denn, es wird ein anderer Hintergrund über den <a class='einstellungen'>Einstellungen-Button</a> gewählt).</p>
<p>Aber anstatt der Hintergrundfarbe könnte auch der body-Hintergrund geändert werden. In dem PHP-Bereich kann das ganze Potenzial dieser Scriptsprache eingesetzt werden, um das Stylesheet den eigenen Bedürfnissen <em>dynamisch</em> anzupassen.<br />
Auch eine Darstellung, welche an die jeweilige Tageszeit angepasst wird bzw. von dieser abhängig ist, kann so leicht realisiert werden (time-Funktion von PHP). </p>
<pre>
 <span style='color:#aaa;'>/* H - Stunde im 24-Stunden-Format (00-23 ) */</span>
if (date("H")&gt;8 &#038;&#038; date("H")&lt;20){
$background = "#ffffff";
    $color = "#000000";
  } else {
    $background = "#000000";
    $color = "#ffffff";
  }
</pre>
<p>Doch es traten auch Probleme auf. Die Stylesheet-Anpassungen für die  <img src='http://einmal-am-tag.de/wp-includes/images/smilies/icon_evil.gif' alt="Icon Evil in " class='wp-smiley' />  -Browser der Redmonder habe ich direkt im Stylesheet stehen und nicht wie sonst üblich über eine Browserweiche (Conditional Comments ) als zusätzliches Stylesheet eingebunden.<br />
Die Separierung erfolgt über die &#8220;Holzhammer-Methode&#8221; mit dem <em>!important</em>-Hack:</p>
<pre>
<span style='color:#aaa'>/* Beispiel */</span>
.navigation {
	display: block;
	text-align: center;
        <span style='color:#aaa;'>/* 'Normale' Browser führen diese Zuweisung aus ... */</span>
	margin-top: 10px !important;
        <span style='color:#aaa;'>/* ... während der IE !important nicht kennt und diese
        Zuweisung interpretiert */</span>
        margin-top:0px;
        <span style='color:#aaa;'>/* Dies wird dann wieder von allen ausgeführt */</span>
	margin-bottom: 60px;
	}
</pre>
<p>Diese Art, IE-Bugs zu beheben, sollte eigentlich nicht verwendet werden ( &#8230; um das Grund-Stylesheet sauber zu halten). Da ich jedoch bisher nicht viele Anpassungen vornehmen mußte, habe ich es auf diese (nicht besonders elegante Weise) gelöst.<br />
Nach Umänderung meines Stylesheets zu einer PHP-CSS-Datei mit Content-Type-Deklaration wurde ich auch sofort bestraft und der Hack funktionierte aus mir unerklärlichen Gründen nicht mehr. Als Folge wurde meine Seite 3 Tage lang etwas &#8220;zerissen&#8221; im IE angezeigt, bis ich es als Firefox-Nutzer endlich gemerkt hatte. Dadurch wurde ich mal wieder daran erinnert, dass in der Programmierung umfangreiche Tests unabdingbar sind.<br />
Nun hätte ich mein Grund-Stylesheet ändern und die IE-Anweisungen auslagern können. Ich entschied mich aber dafür, den PHP-Teil in eine separate Datei zu schreiben und zusätzlich in die Seite einzufügen. So können zukünftige weitere Schritte überschaubarer realisiert werden.</p>
<p>Ich hoffe, diese Einführung in dynamische Stylesheets war hilfreich für eigene Projekte. </p>
<h5 class='trigger'>Hier noch mal der gesamte Quellcode</h5>
<div>
<pre>
&lt;?php
session_start(); <span style='color:#aaa;'>/* ... muss am Anfang eingefügt werden */</span>
<span style='color:#aaa;'>/* error_reporting(E_ALL)  und ini_set('display_errors', 'On') zur Fehlersuche */</span>
error_reporting(E_ALL);
ini_set('display_errors', 'On');
header('Content-type: text/css');

<span style='color:#aaa;'>/* Zufallshintergrund */</span>
if(!isset($_SESSION['color'])) {

  $farben = array('weiss', 'schwarz', 'blau', 'gruen', 'beige', 'hellblau', 'hellgruen', 'rose', 'sand', 'grau_gruen');
  $zufall = array_rand($farben, 1);<span style='color:#aaa;'>/* ... die 1 kann bei einem Wert auch weggelassen werden */</span>
  $zufalls_farbe = $farben[$zufall];

  switch ($zufalls_farbe) {
    case 'weiss':
      $_SESSION['textcolor'] = '#222';
        break;
    case 'beige':
      $_SESSION['textcolor'] = '#222';
        break;
    case 'hellblau':
      $_SESSION['textcolor'] = '#222';
        break;
    case 'oliv':
      $_SESSION['textcolor'] = '#222';
        break;
    case 'rose':
      $_SESSION['textcolor'] = '#222';
        break;
    case 'hellgruen':
      $_SESSION['textcolor'] = '#222';
        break;
    case 'sand':
      $_SESSION['textcolor'] = '#222';
        break;
    case 'grau_gruen':
      $_SESSION['textcolor'] = '#222';
        break;
    default:
      $_SESSION['textcolor'] = '#ccc';
        break;
  }
  $_SESSION['color'] = $zufalls_farbe;
}
?&gt;

#header {
	background: transparent url('images/layout/<span style='color:green;'>bg_</span>&lt;?php
             if(isset($_SESSION['color']))
                 echo $_SESSION['color'];
             else
                 echo 'bg_weiss'; ?&gt;<span style='color:green;'>.png</span>') repeat-y top center;
	}

#container_inside {
	background: transparent url('images/layout/<span style='color:green;'>bg_</span>&lt;?php
             if(isset($_SESSION['color']))
                 echo $_SESSION['color'];
             else
                 echo 'bg_weiss'; ?&gt;<span style='color:green;'>.png</span>') repeat-y top center;
	}

#content {
	font-size: 1.35em;
        color:&lt;?php
            if(isset($_SESSION['textcolor']))
               echo $_SESSION['textcolor'];
            else
               echo '#222'; ?&gt;;
	}
</pre>
</div>
<!-- google_ad_section_end -->
]]></content:encoded>
			<wfw:commentRss>http://einmal-am-tag.de/2009-06/dynamisches-stylesheet/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Datenbank-Klasse in PHP</title>
		<link>http://einmal-am-tag.de/2009-05/datenbank-klasse-in-php/</link>
		<comments>http://einmal-am-tag.de/2009-05/datenbank-klasse-in-php/#comments</comments>
		<pubDate>Mon, 25 May 2009 16:15:58 +0000</pubDate>
		<dc:creator>Matu</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Datenbank]]></category>
		<category><![CDATA[Klassen]]></category>
		<category><![CDATA[mySQL]]></category>
		<category><![CDATA[OOP]]></category>
		<category><![CDATA[Programmierung]]></category>
		<category><![CDATA[Tutorial]]></category>

		<guid isPermaLink="false">http://einmal-am-tag.de/?p=549</guid>
		<description><![CDATA[

Um mit PHP eine Verbindung zu einer mySQL-Datenbank herzustellen, benötigt man unter anderem die mysql_connect()-Funktion von PHP. 
Dabei wird es auf Dauer etwas mühselig, immer wieder auf´s Neue alle benötigten Funktionen einzubringen. Aus diesem Grund bietet es sich an, für den Zugriff auf eine Datenbank eine eigene objektorientierte Klasse zu programmieren, die einfach in jedes [...]]]></description>
			<content:encoded><![CDATA[
<!-- google_ad_section_start -->
<h4>Um mit <strong>PHP</strong> eine Verbindung zu einer <strong>mySQL-Datenbank</strong> herzustellen, benötigt man unter anderem die <em>mysql_connect()</em>-Funktion von PHP. </h4>
<p>Dabei wird es auf Dauer etwas mühselig, immer wieder auf´s Neue alle benötigten Funktionen einzubringen. Aus diesem Grund bietet es sich an, für den Zugriff auf eine Datenbank eine eigene <strong>objektorientierte Klasse</strong> zu programmieren, die einfach in jedes neue Projekt eingebunden wird (<acronym title="include()-Funktion"><em>includiert</em></acronym> oder <acronym title="require()-Funktion oder require_once()-Funktion "><em>required</em></acronym>).<br />
Für mein eigenes kleines <acronym title="Content Management System">CMS</acronym> hatte ich vor längerer Zeit mal eine Klasse geschrieben, die nach Instanziierung eines Objektes folgendes ermöglicht:<span id="more-549"></span></p>
<ul>
<li>Verbindung zur mySQL-Datenbank herstellen</li>
<li>Auswahl einer Datenbank/ Tabelle</li>
<li>Senden einer SQL-Anfrage</li>
<li>Daten holen (in einem Array)</li>
<li>Anzahl Datensätze anzeigen<br />
    (z.B. zur Überprüfung).</li>
</ul>
<p>Schritt für Schritt von oben nach unten: </p>
<pre>
&lt;?php
//dbconnect.class.php

class 	DBconnect //Klassenname
{
     private $ers; //Hilfs-Variable

     ...
</pre>
<p>Zunächst kommt nach dem einleitenden PHP-Tag der spätere Name der Datei. Dieser wird auskommentiert und ist nicht zwingend notwendig, sollte ordnungshalber aber aufgeführt werden (Name, Erstellungsdatum &#8230; lasse ich mal außen vor).</p>
<p>Die Klasse bekommt nun ihren Namen, den ich am Anfang groß schreibe (genau wie in Java &#8230;) und wird durch das Schlüsselwort <em>public</em> für den öffentlichen Zugriff freigegeben. Die folgende Variable <em>$ers</em> dient innerhalb der Klasse als <em>Helferlein</em> und ist durch das Schlüsselwort <em>privat</em> nur innerhalb der Klasse verfügbar (kann nicht von außen angesprochen werden).<br />
Darauf folgt der Konstruktor:</p>
<pre>
...

public function __construct($datenbank,$host<span style='color:red;'>="127.0.0.1"</span>,
                   $benutzer<span style='color:red;'>="root"</span>,$passwd<span style='color:red;'>="passwort"</span>)
{
 <span style='color:#888;'> /*
  mysql_connect — ÖFFNET eine VERBINDUNG zu einem MySQL-
  Server und gibt eine Meldung aus, falls ein
  SQL-Fehler erfolgt
  */</span>
  $db_link = mysql_connect($host,$benutzer,$passwd,TRUE)
              or die (mysql_error());
<span style='color:#888;'> /*
 ------------------------------------------------------------
 Anmerkung: Anstatt das Script über '... or die(...)' einfach
 abzubrechen, kann auch eine Fehlermeldung wie folgt ausgegeben
 werden.</span>
 if(!$db_link) {
    trigger_error("Es konnte keine Verbindung zur Datenbank
    hergestellt werden.", E_USER_ERROR);
 }
<span style='color:#888;'>
 -------------------------------------------------------------
*/</span>

 <span style='color:#888;'> /*
  mysql_select_db — AUSWAHL einer MySQL DATENBANK
  */</span>
  mysql_select_db($datenbank) or die("Konnte die Datenbank nicht waehlen.");
}

...
</pre>
<p>Der Konstruktor wird automatisch bei Erzeugung/ Instanziierung eines Objektes der Klasse DBconnect aufgerufen und erwartet Parameter (Datenbankname, Host, Benutzername und Passwort).<br />
Wird stets nur auf eine Datenbank zugegriffen, dann kann den Parametern direkt in der Klasse ein Wert zugewiesen werden. Die Zuweisung erfolgt aber nur dann, wenn kein Wert für den jeweiligen Parameter übergeben wird.<br />
In unserem Beispiel müßte für die Verbindung zur Datenbank lediglich der Name der Tabelle bei der Objekterzeugung mit übergeben werden. Die restlichen Informationen werden der Zuweisung (rot dargestellt) entnommen. Übergibt man aber nicht nur den Name der Tabelle, sondern zum Beispiel ein anderes Passwort (&#8230;), dann müssen alle Parameter in der richtigen Reihenfolge von links nach rechts übergeben werden (und die vordefinierten zählen dann nicht). Das bedeutet, dass zusätzlich zum Passwort auch der Benutzername übergeben werden muss, da dieser vor dem Passwort in der Parameterübergabe liegt.</p>
<p>Dies soll nur der Vollständigkeit halber verdeutlichen, dass einem Parameter so wie oben auch ein fester Wert zugewiesen werden kann.<br />
Würde jetzt der Tabellenname ebenfalls einen festen Wert erhalten, dann bräuchte man überhaupt keinen Parameter übergeben (vorausgesetzt, die Werte stimmen mit denen der anzusprechenden Datenbank überein).<br />
Ich merke, dass ich schon wieder viel zu viel schreibe und <em>abdrifte</em>, daher bremse ich hier etwas ab!<br />
Durch den so definierten Konstruktor könnte nun im jeweiligen Script, wo unsere Klasse eingebunden wurde, schon ein Objekt erzeugt werden:</p>
<pre>
$datenbankverbindung = DBconnect('tabellenname');

<span style='color:#888;'>// oder bei einer anderen Datenbank</span>

$datenbankverbindung = DBconnect('tabellenname','127.0.0.1','willi','geheim');
</pre>
<p>Dadurch wird aber erst die Verbindung hergestellt.<br />
Kommen wir nun weiter zu den Funktionen (auch Methoden genannt), durch die nun mit der Datenbank <em>kommuniziert</em> werden kann, nachdem die Verbindung aufgebaut wurde.</p>
<pre>
function sql($sql_query)
  {
      return $this->ers = mysql_query($sql_query)
      or die ('Anfrage fehlgeschlagen');
     <span style='color:#888;'> /*mysql_query — SENDET eine ANFRAGE an MySQL*/</span>
  }

function data()
  {
      return mysql_fetch_row($this->ers);
      <span style='color:#888;'>/*mysql_fetch_row — LIEFERT einen DATENSATZ
        als indiziertes ARRAY*/</span>
  }

function anzahl()
  {
      return mysql_num_rows($this->ers);
     <span style='color:#888;'> /*mysql_num_rows — LIEFERT die ANZAHL der
        DATENSÄTZE*/</span>

  }

function __destruct()
  {
      mysql_close();
      <span style='color:#888;'>/*mysql_close — SCHLIEßT die VERBINDUNG zur Datenbank*/</span>

  }
</pre>
<p>Die erste Funktion <em>sql</em> ermöglich es, durch die PHP-Funktion <em>mysql_query(&#8217;string&#8217;)</em> ein SQL-Statement an die Datenbank zu stellen (SELECT, UPDATE, DELETE, &#8230;).<br />
Bei den weiteren Funktionen sollte klar sein, was sie bewirken. Wobei die <em>__destruct</em>-Funktion eigentlich nicht nötig ist, da nach Beendigung des jeweiligen Scriptes die Verbindung sowieso getrennt wird. Jedoch kann es vorkommen, dass mehrere Verbindungen hergestellt werden sollen &#8230;!<br />
Was hat man nun gewonnen? Dazu sehen Sie sich bitte folgende Beispiele an.<br />
Ohne DBconnect-Klasse</p>
<pre>
$db_link = mysql_connect($host,$benutzer,$passwd,TRUE)
or die (mysql_error());

mysql_select_db('tabellenname')
or die("Konnte die Datenbank nicht waehlen.");

$sql_query = 'SELECT * FROM datenbank';

$ressource = mysql_query($sql_query)
                  or die ('Anfrage fehlgeschlagen');

$anzahl = mysql_num_rows($ressource);

if($anzahl > 0){
     while ($data = mysql_fetch_array($ressource)){
     ...
     }
}
</pre>
<p>Mit DBconnect-Klasse:</p>
<pre>
$dbconnect = new DBconnect("tabellenname");
$sql_query = 'SELECT * FROM datenbank';
$dbconnect->sql($sql_query);
if($dbconnect->anzahl() > 0){
    while($data=$dbconnect->data()){
    ...
    }
}
</pre>
<p>Sehr viel kürzer und übersichtlicher, oder?! Man beachte im Beispiel ohne DBconnect-Klasse die Variable <em>$ressource</em>. Die Übergabe dieses Wertes erfolgt bei uns schon in der Klasse selber. Sie haben es bestimmt erkannt, dafür wurde unsere Variable <em>$ers</em> &#8230; unser <em>Helferlein</em> eingesetzt.<br />
Der Quellcode steht zur freien Verfügung!</p>
<h5 class="trigger">(Hier noch mal der gesamte Quellcode)</h5>
<div>
<pre>
------------------------------------------------------------------------------------------------------------------------
&lt;?php
//dbconnect.class.php
class 	DBconnect
{
	private $ers;

	 <span style='color:#888;'>/*Konstruktor ... wird automatisch bei Erzeugung/ Instanziierung eines Objektes der Klasse
              aufgerufen und erwartet Parameter (Datenbankname, Host, Benutzername, Passwort)*/</span>
	public function __construct($datenbank,$host="127.0.0.1",$benutzer="root",$passwd="passwort")
	{
		 <span style='color:#888;'>/*mysql_connect — ÖFFNET eine VERBINDUNG zu einem MySQL-Server und
                          gibt eine Meldung aus, falls ein SQL-Fehler erfolgt*/</span>
		$db_link = mysql_connect($host,$benutzer,$passwd,TRUE) or die (mysql_error());
		 <span style='color:#888;'>/*mysql_select_db — AUSWAHL einer MySQL DATENBANK*/</span>
		mysql_select_db($datenbank) or die("Konnte die Datenbank nicht waehlen.");
		 <span style='color:#888;'>/*if(!$db_link) echo "Fehler DB-Verbindung";*/</span>
	}

	function sql($sql_query)
	{
		return $this->ers = mysql_query($sql_query) or die ('Anfrage fehlgeschlagen');
                <span style='color:#888;'>/*mysql_query — SENDET eine ANFRAGE an MySQL*/</span>
	}

	function data()
	{
		return mysql_fetch_row($this->ers);
                <span style='color:#888;'>/*mysql_fetch_row — LIEFERT einen DATENSATZ als indiziertes ARRAY*/</span>
	}

	function anzahl()
	{

		return mysql_num_rows($this->ers);
                 <span style='color:#888;'>/*mysql_num_rows — LIEFERT die ANZAHL der DATENSÄTZE*/</span>

	}

	function __destruct()
	{
		mysql_close();
                <span style='color:#888;'>/*mysql_close — SCHLIEßT die VERBINDUNG zur Datenbank*/</span>
	}
}

?&gt;
</pre>
</div>
<p>Diesen einfach in einen Editor ihrer Wahl kopieren und zum Beispiel als <em>dbconnect.class.php</em> speichern. In ein neues Projekt wird die Klasse direkt oben per <em>include</em> oder <em>require</em> eingebunden:</p>
<pre>
include("class/dbconnect.class.php");
 <span style='color:#888;'>// oder </span>
require("class/dbconnect.class.php");
 <span style='color:#888;'>// oder </span>
require_once("class/dbconnect.class.php");
</pre>
<p>Ich hoffe, ich konnte dem einen oder anderen die Vorteile einer Datenbank-Klasse näherbringen. </p>
<!-- google_ad_section_end -->
]]></content:encoded>
			<wfw:commentRss>http://einmal-am-tag.de/2009-05/datenbank-klasse-in-php/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Captcha in PHP programmieren</title>
		<link>http://einmal-am-tag.de/2009-05/captcha-in-php-programmieren/</link>
		<comments>http://einmal-am-tag.de/2009-05/captcha-in-php-programmieren/#comments</comments>
		<pubDate>Sun, 17 May 2009 23:37:43 +0000</pubDate>
		<dc:creator>Matu</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Captcha]]></category>
		<category><![CDATA[Programmieren]]></category>
		<category><![CDATA[Spamschutz]]></category>

		<guid isPermaLink="false">http://einmal-am-tag.de/blog/?p=183</guid>
		<description><![CDATA[

Captcha ist die Abkürzung für Completely Automated Public Turing test to tell Computers and Humans Apart und dient in Gästebüchern, Foren, Weblog und anderen Eingabe- bzw. Kontaktformularen als Möglichkeit zu entscheiden, ob die Eintragung der Daten durch einen Menschen oder maschinell durch ein Script ( BOT) erfolgt. Dazu wird ein Bild generiert, welches (meist verschleierte) [...]]]></description>
			<content:encoded><![CDATA[
<!-- google_ad_section_start -->
<p><strong>Captcha</strong> ist die Abkürzung für <em><strong>C</strong>ompletely <strong>A</strong>utomated <strong>P</strong>ublic <strong>T</strong>uring test to tell <strong>C</strong>omputers and <strong>H</strong>umans <strong>A</strong>part</em> und dient in Gästebüchern, Foren, Weblog und anderen Eingabe- bzw. Kontaktformularen als Möglichkeit zu entscheiden, ob die Eintragung der Daten durch einen Menschen oder maschinell durch ein Script ( BOT) erfolgt. Dazu wird ein Bild generiert, welches (meist verschleierte) Schriftzeichen enthält, die zur Überprüfung in ein Textfeld eingetragen werden müssen. Diese Aufgabe soll für den Menschen einfach zu bewältigen sein, für die Maschine dagegen eine Hürde darstellen und so vor Spam schützen. <span id="more-183"></span></p>
<p>Leider werden diese sogenannten Spam-Bots immer besser programmiert und setzen Mustererkennungs</span>-Algorithmen ein, welche mittlerweile auch stark verschleierte Captchas auslesen können (wobei diese auch für den Mensch unleserlich werden) und somit den Schutz aufheben. Aus diesem Grund lassen sich Entwickler von Captchas immer neue Hürden einfallen, die dann im Gegenzug von der &#8220;dunklen&#8221; Seite wieder geknackt werden.</p>
<p>Um sich davon mal ein Bild machen zu können ist diese  <a href="http://caca.zoy.org/wiki/PWNtcha">Seite</a> interessant. In der mittleren Spalte wird angegeben, um wie viel Prozent das jeweilige Captcha <strong>keinen</strong> Schutz mehr bietet. Einen weiteren interessanten Artikel hierzu finden Sie auf der Seite der <a href="http://www.w3.org/TR/turingtest/">W3C Working Group</a> (in Englisch).</p>
<p>Letztendlich kann man sagen, das Captchas nicht mehr &#8220;up to date&#8221; sind und vor allem hinsichtlich barrierefreiher Seiten wohl bald der Vergangenheit angehören. Vereinzelt sieht man auf Webseiten Captchas, welche auch eine Sprachausgabe erzeugen können &#8230; ein guter Schritt hinsichtlich der eben angesprochenen Barrierefreiheit wie ich finde.</p>
<p>Soll dennoch ein Captcha eingesetzt werden, dann sollte dieses mit weiteren &#8220;Hürden&#8221; kombiniert werden. Beispielsweise könnte ein weiteres Feld in das Formular eingebracht werden, welches durch CSS versteckt wird und frei bleiben muss. Da ein Spam-Bot in der Regel alles ausfüllt wäre er als Maschine entarnt und der Programmierer kann darauf eingehen. An vielen Stellen werden auch einfache Rechenaufgaben (Was ergibt 7+5?) oder Fragen gestellt (Das Gras ist &#8230;?). Eine weitere Möglichkeit besteht darin, einen Zeitwert beim Aufruf der Webseite zu speichern und diesen mit einem 2. Wert beim Abschicken des Formulars zu vergleichen. Spam-Bots füllen das Formular in wenigen Sekunden aus, ein Mensch benötigt da wesentlich mehr Zeit &#8230; hier sollte klar sein, was ich meine. Über die .htaccess-datei können ebenfalls Spam-Bots über die IP gesperrt werden &#8230;!</p>
<p>Aber eigentlich ging es bei diesem Artikel um das Programmieren eines Captchas. Ich hoffe, dass jetzt nicht die Lust dazu verflogen ist. Denn es ist eine schöne Übung, wie ich finde und zudem leicht verständlich. Außerdem wird ein guter Einstieg in die <em>grafische Programmierung mit PHP</em> geboten.</p>
<p>Auf gehts!</p>
<h3>Wir programmieren ein Captcha</h3>
<p>Öffnen Sie bitte Ihren gewohnten Standard-Editor, ich persönlich benutze dafür meist immer Notepad++. Der ist klein, fein und reicht mir. Für größere Projekte greife ich dann zumeist auf die PHP-Version von Eclipse zurück. In eine neue Datei geben wir den Anfang und den Endtag für PHP ein</p>
<pre>&lt;?php

?&gt;</pre>
<p>und speichern diese dann direkt an einem beliebigen Ort unter captcha.php ab. Danach sollte das Syntax-Highlighting aktiviert sein!</p>
<p>Für das Erzeugen der Zeichen bietet sich eine Funktion an</p>
<pre>&lt;?php
<span style="color:#999">//capture.php</span>
function generate(){
</pre>
<p>Zuerst erzeugen wir ein Array, welches wir mit Zeichen füllen</p>
<pre><span style="color:#999">/*Beispiel-Array für die Zeichen und Zahlen*/</span>
$zeichen = array('a','A','b','A','c','C','d','D','e','E','f','F',
                'g','G','h','H','i','I','j','J','k','l','m','n','o',
                'p','q','r','s','t','u','v','w','x','y','z',
                1,2,3,4,5,6,7,8,9);</pre>
<p>Anstatt ein Array händig zu füllen könnte man auch mit &#8216;range&#8217; die Zeichen/Zahlen erzeugen</p>
<pre>
<span style="color:#999">/*
$abc=range("A","Z");
$abc2=range("a","z");
$zahlen=range(0,9);
...
*/</span>
</pre>
<p>jedoch haben Sie mit dem Array was fürs Auge, daher kommentieren wir diesen Bereich aus.<br />
Das Array mischen wir nun mit der PHP-Funktion shuffle</p>
<pre>shuffle($zeichen);</pre>
<p>Anschließend wählen wir 4 zufällige Einträge (array_rand) aus<br />
dem Array aus. Und Sie haben Recht, &#8217;shuffle&#8217; könnte man sich somit auch sparen!</p>
<pre>$rand_keys = array_rand($zeichen, 4);</pre>
<p>Nun basteln wir aus den 4 Array-Einträgen einen String (Punkt-Operator) und wandeln die 4 Zeichen zu Großbuchstaben um (strtoupper ⇒ string to upper). Natürlich werden hierbei nur Buchstaben und keine Zahlen konvertiert. Lässt man diesen Schritt aus, dann können später auch Kleinbuchstaben (wie im Array angegeben) vorkommen.</p>
<pre>return strtoupper($zeichen[$rand_keys[0]].$zeichen[$rand_keys[1]].
	$zeichen[$rand_keys[2]].$zeichen[$rand_keys[3]]);
}<span style="color:#999">/* Schließende Klammer unserer Funktion nicht vergessen*/</span>
</pre>
<p>Damit ist die Funktion für die Zeichen schon fertig. Ich habe hier bewusst PHP-Funktionen eingebaut, die eigentlich nicht nötig wären. Dazu gehört die shuffle-Funktion, da die array_rand-Funktion ebenfalls zufällige Zeichen aus dem Array raus zieht. Zudem schreiben wir auch Kleinbuchstaben in das Array und konvertieren diese dann vor der Rückgabe zu Großbuchstaben &#8230; ebenfalls unnötig. Aber so sehen Sie gleich mehrere Möglichkeiten, lernen mehr und können selber wählen, was Sie für richtig halten.<br />
Damit ist der erste Schritt getan, kommen wir nun zum Bild.</p>
<p>Als erstes wird das Image erzeugt. Hierzu nutzen wir Funktion imagecreate(), wobei die Werte in der Klammer (Parameter) die Größe des Images in Pixel bestimmen .</p>
<pre>$im = imagecreate(180, 100);<span style="color:#999">// Image erzeugen</span></pre>
<p>Darauf folgt die Erzeugung der Hintergrundfarbe mit der Funktion imagecolorallocate(), wobei hier als Parameter zunächst das zuvor erzeugte Image ($im) übergeben wird, welchem dann RGB-Werte zugeordnet werden:</p>
<pre>$yellow = imagecolorallocate($im, 255, 255, 0);<span style="color:#999">// Farben erzeugen</span>
/*$black = imagecolorallocate($im, 0, 0, 0);*/</pre>
<p>Damit ist das Image an sich schon fertig und könnte <acronym title="zum Beispiel">z.B</acronym> mit imagegif() als gif-Datei abgespeichert werden (dazu gleich mehr).<br />
Aber unser String fehlt noch und den erzeugen wir durch unsere zuvor erstellte Funktion, in dem wir diese einfach aufrufen:</p>
<pre>$string = generate();<span style="color:#999">// String erzeugen</span></pre>
<p>Das war´s schon, in der Variablen (oder heißt es Variabel) ist nun unser zufällig erzeugter 4-Zeichen-String gespeichert und muss jetzt noch in das Image eingefügt werden. An dieser Stelle wird es ein klein wenig komplizierter. Die einzelnen Zeichen (oder auch Texte) werden einzeln nach und nach über eine for-Schleife in das Image eingefügt. Dafür nutzen wir die Funktion imagefttext(), welche mehrere Parameter beinhaltet:</p>
<pre>imagefttext($im, $font_size, $rotation, $shadow_x, $shadow_y, $shadow_color, $font, $string[$i], array());</pre>
<ul>
<li>$im steht für unser Image</li>
<li>$font_size für die Schriftgröße</li>
<li>$rotation für den Drehungswinkel des Zeichens</li>
<li>$shadow_x und $shadow_y für die Position innerhalb vom Image</li>
<li>$shadow_color für die Farbe des jeweiligen Zeichens</li>
<li>$font für die Schriftart (die als .ttf-Datei vorliegen muss)</li>
<li>$string[$i] beinhaltet das jeweilige Zeichen</li>
<li>array() &#8230; keine Ahnung, aber nicht nötig</li>
</ul>
<p>Schauen wir uns jetzt mal gemeinsam den Quelltext an:</p>
<pre>for($i=1; $i &lt;= 4; $i++)
{
	$ro = mt_rand(0, 90);<span style="color:#999">// Zufallszahl Rotation</span>
	$y = mt_rand(35, 100);<span style="color:#999">// Zufallszahl y-Achse</span>
	$font = rand(20, 40);<span style="color:#999">// Schriftgröße</span>
	$color = imagecolorallocate($im, rand(50,200), rand(50, 200), rand(50,200));
	<span style="color:#999">/* Zufallsfarbe --&gt; den RGB-End-Wert tiefer wählen, damit die Zeichen dunkler als der Hintergrund sind*/</span>	

imagefttext ($im, $font, $ro, $i*36, $y, $color, 'arial.ttf', $string[$i-1]);
}</pre>
<p>Zunächst beginnen wir mit einer for-Schleife, die genau 4x den Schleifenkörper durchläuft. Bei jedem einzelnen Durchlauf wird durch die imagefttext-Funktion ein Zeichen aus unserem Zeichen-Array in das Image geschrieben ($string[$i-1]). Beim ersten Durchlauf enthält die Zählvariable den Wert 1, der bei jedem weiteren Durchlauf um 1 ($i++) erhöht wird. Da unsere $string-Array aber mit dem Index 0 für das erste Zeichen beginnt, müssen wir den Wert wie oben angegeben &#8216;jede Runde&#8217; um den Wert 1 reduzieren, um das jeweilige Zeichen zu erhalten. Ich denke, dass sollte klar sein.<br />
Nun erzeugen wir die einzelnen Werte wie Rotation ($ro), Position ($y), Schriftgröße ($font) und Zeichenfarbe ($color) mit Hilfe der Zufalls-Funktion rand(), der wir als Parameter einen <strong>Wertebereich</strong> übergeben. So kann das jeweilige Zeichen zum Beispiel durch Zufall von 0°-90° gedreht werden (Rotation). Die y-Position verläuft innerhalb von 35-100 Pixel (also innerhalb vom Image, welches 100 Pixel hoch ist). Die Schriftgröße variiert zwischen 20 und 40 Pixel. Dazu kommt ein Zufalls-RGB-Wert für die Farbe des jeweilgen Zeichens. Hierbei wurde der Endwert bewußt auf maximal 200 (von möglichen 255 ⇒ weiss) beschränkt, damit das Zeichen nicht zu hell wird und somit vom Benutzer nur noch schlecht oder gar überhaupt nicht mehr gelesen werden kann (sollte der Hintergrund dunkel sein, verhält sich das entsprechend anders).<br />
Der Wert für die x-Position (horizontal) wird einfach dadurch erzeugt, das wir den jeweiligen Wert der Zählvariable mit 36 multiplizieren. Damit bleibt das jeweilige Zeichen auf jeden Fall innerhalb von unserem Image (wir erinnern uns ⇒ 180 Pixel breit), wandert aber automatisch bei jedem neuen Schleifendurchlauf in Folge der höheren Zählvariable weiter auf der y-Achse nach rechts. <em>Somit liegen die Zeichen nebeneinander und verdecken sich nicht eventuell untereinander</em>.<br />
Nun muss noch eine Schriftdatei eingebunden werden, die entweder im gleichen Ordner liegt (wie im Beispiel zu sehen) oder aber per Pfadangabe eingebunden wird. Diese finden Sie zum Beispiel bei den Betriebssystemen der Redmonder unter
<pre>C:\WINDOWS\FONTS\ bzw. C:\WINNT\Fonts\</pre>
<p>Zum Abschluss wird das Image als gif-Datei gespeichert (hier sind auch andere Bildtypen möglich) und per echo-Befehl ausgegeben:</p>
<pre>imagegif($im, "captcha.gif");
echo "&lt;img src='captcha.gif' border='2'&gt;";
}
?&gt;
</pre>
<p>Das schöne daran ist, das bei jedem Neuaufruf unseres Captcha-Scriptes die vorherige Bild-Datei durch das neue Image überschrieben wird.</p>
<h5 class="trigger">(Hier noch mal der gesamte Quellcode)</h5>
<div>
<pre>&lt;?php
<span style="color:#999">//capture.php</span>

function generate()
{
	$zeichen = array('a','A','b','A','c','C','d',
      'D','e','E','f','F','g','G','h','H','i','I','j','J,
      'k','l','m','n','o','p','q','r','s','t',
      'u','v','w','x','y','z',1,2,3,4,5,6,7,8,9);
	<span style="color:#999">/*
	$abc=range("A","Z");
	$abc2=range("a","z");
	$zahlen=range(0,9);
	*/</span>

	shuffle($zeichen);
	$rand_keys = array_rand($zeichen, 4);

	return strtoupper($zeichen[$rand_keys[0]].$zeichen[$rand_keys[1]].
	$zeichen[$rand_keys[2]].$zeichen[$rand_keys[3]]);
}

//------------------------------------------------------------------------------------------

$im = imagecreate(180, 100);<span style="color:#999">// Image erzeugen</span>
$yellow = imagecolorallocate($im, 255, 255, 0);<span style="color:#999">// Farben erzeugen</span>
$black = imagecolorallocate($im, 0, 0, 0);

$string = generate();<span style="color:#999">// String erzeugen</span>

for($i=1; $i &lt;= 4; $i++)
{
	$ro = mt_rand(0, 90);<span style="color:#999">// Zufallszahl Rotation</span>
	$y = mt_rand(35, 100);<span style="color:#999">// Zufallszahl y-Achse</span>
	$font = rand(20, 40);<span style="color:#999">// Schriftgröße</span>
	$color = imagecolorallocate($im, rand(50,200), rand(50, 200), rand(50,200));
	<span style="color:#999">/* Zufallsfarbe --&gt; den RGB-End-Wert tiefer wählen, damit die Zeichen dunkler als
                      der Hintergrund sind*/</span>

	<span style="color:#999">/* imagefttext($im, $font_size, $rotation, $shadow_x, $shadow_y, $shadow_color,
           $font, string[$i], array());*/</span>
	imagefttext ($im, $font, $ro, $i*36, $y, $color, 'arial.ttf', $string[$i-1]);
}

imagegif($im, "captcha.gif");
echo '&lt;img src="captcha.gif" border="2"&gt;';
?&gt;</pre>
</div>
<p>Das hier erstellte Captcha dürfte für viele Spam-Bots kein Hindernis darstellen. Aber da die Grundvoraussetzung für ein eigenes Captcha gelegt ist (hoffe ich zumindest) steht einer Variation von Ihnen nichts mehr im Wege.</p>
<p>Um das Captcha auszuwerten lediglich die Varible $string gegenprüfen.</p>
<p><strong>Ich wünsche viel Spaß beim Ausprobieren!</strong></p>
<p>Ein Beispiel findet sich <a href="/kontakt" title="Kontaktformular mit Captcha">hier</a>.<br />
Das dortige Formular ist übrigens ebenfalls selbst programmiert.</p>
<!-- google_ad_section_end -->
]]></content:encoded>
			<wfw:commentRss>http://einmal-am-tag.de/2009-05/captcha-in-php-programmieren/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
