<?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>ROAE-Blog &#187; PHP</title>
	<atom:link href="http://blog.root-of-all-evil.com/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.root-of-all-evil.com</link>
	<description>Studium, Codeing und Gedachtes</description>
	<lastBuildDate>Mon, 30 Jan 2012 22:58:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Punkte in Google-Mail-Adressen</title>
		<link>http://blog.root-of-all-evil.com/2010/05/punkte-in-google-mail-adressen/</link>
		<comments>http://blog.root-of-all-evil.com/2010/05/punkte-in-google-mail-adressen/#comments</comments>
		<pubDate>Tue, 18 May 2010 18:09:29 +0000</pubDate>
		<dc:creator>Felix</dc:creator>
				<category><![CDATA[Codeschnipsel]]></category>
		<category><![CDATA[Erklärungen]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[gmail]]></category>
		<category><![CDATA[google]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=797</guid>
		<description><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/05/punkte-in-google-mail-adressen/" title="Punkte in Google-Mail-Adressen"></a>Registriert man bei Google Mail eine E-Mailadresse &#8211; z.B. dasIstEineEMailAdresse@googlemail.com &#8211; so wird der komplette Benutzername unabhängig von Groß-/Kleinschreibung und Punkten (.) interpretiert: registriert man die E-Mail-Adresse dasIstEineEMailAdresse@googlemail.com, so hat man automatisch auch folgende weitere Adressen das.ist.eine.emailadresse@googlemail.com oder das.istEineEmailAdresse@googlemail.com etc. &#8230;<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/05/punkte-in-google-mail-adressen/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/05/punkte-in-google-mail-adressen/" title="Punkte in Google-Mail-Adressen"></a><p>Registriert man bei Google Mail eine E-Mailadresse &#8211; z.B. dasIstEineEMailAdresse@googlemail.com &#8211; so wird der komplette Benutzername unabhängig von Groß-/Kleinschreibung und Punkten (.) interpretiert: registriert man die E-Mail-Adresse dasIstEineEMailAdresse@googlemail.com, <strong>so hat man automatisch auch folgende weitere Adressen</strong> das.ist.eine.emailadresse@googlemail.com oder das.istEineEmailAdresse@googlemail.com etc.</p>
<p>Welche <strong>Vorteile sich für den Benutzer</strong> und welche <strong>Nachteile für einen Webmaster</strong> sich hierdurch ergeben soll hier kurz aufgezeigt werden.</p>
<p><span id="more-797"></span></p>
<h2>Vorteile für den Benutzer</h2>
<p>Durch unterschiedliche E-Mail-Adressen, welche aber alle zu einem Postfach führen, gibt es für den Benutzer eine Reihe von Vorteilen.</p>
<h3>Organisation/Kategorisierungen</h3>
<p>Der Benutzer kann die E-Mails besser organisieren bzw. kategorisieren. Beispielsweise wird für alle <strong>Newsletter die E-Mail-Adresse m.ax.mueller@googlemail.com</strong> verwendet, für den <strong>privaten Kontakt max.mueller@googlemail.com.</strong> Mit Hilfe der <strong>Filtereinstellungen bei Google-Mail</strong> können dann alle Newsletter unabhängig vom Absender mit einem Label versehen und aus dem Posteingang verschoben werden &#8211; so findet man im Posteingang dann wirklich nur die &#8220;wichtigen&#8221; E-Mails.</p>
<p><img class="aligncenter size-medium wp-image-804" title="Filter-Einstellungen bei Google-Mail" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/05/screen-capture-300x60.jpg" alt="" width="300" height="60" /></p>
<h3>Privatsphäre</h3>
<p>Manche Plattformen bieten die Möglichkeit über eine E-Mail-Adresse zu prüfen ob ein User angemeldet ist (z.B. Facebook). Dies ist nicht von jedem User gewünscht. Hier bietet sich dann mit einer Google-Mail-Adresse die Möglichkeit seine <strong>E-Mail-Adresse auf der Plattform z.B. auf max.m.u.e.l.l.e.r@googlemail.com zu ändern.</strong> Sucht ein User nach max.mueller@googlemail.com so wird er nicht fündig werden &#8211; und trotzdem muss man nicht eine weitere E-Mail-Adresse registrieren.</p>
<h2>Nachteile für den Webmaster</h2>
<p>Natürlich ergeben Sie durch dieses Feature auch Nachteile. Oft wird die <strong>E-Mail-Adresse als primary Key</strong> verwendet um so Mehrfachanmeldungen oder Nutzungen schnell und einfach zu unterbinden. Dies wird genutzt unter anderem bei:</p>
<ul>
<li>Serialversand<br />
Das Produkt X darf 14 Tage mit der Serial Y getestet werden. Wird danach versucht erneut eine Serial anzufordern, schlägt das für die benutzte Adresse fehl</li>
<li>Unterbinden von Mehrfachregistrierung<br />
Es soll verhindert werden dass sich ein Benutzer mehrfach registriert &#8211; unabhängig ob das Verhalten gewollt oder ungewollt ist. Sei es auf Community-Seiten oder auch finanziell orientierten Homepages wie Online-Shops.</li>
</ul>
<p>Natürlich gibt es neben der &#8220;Google-Mail-Problematik&#8221; auch noch andere Möglichkeiten wie Wegwerf-E-Mail-Adressen, Automatische Erstellung von E-Mail-Konten, oder sogar der Besitz einer (E-Mail-)Domain (ich@meineDomain.de, ich1@meineDomain.de, &#8230;). Wir wollen uns aber hier nur mit Google-Mail beschäftigen.</p>
<p>Eine Möglichkeit das Problem zu umgehen ist der folgende einfache Algorithmus:</p>
<ol>
<li>Prüfe ob Google-Mail-Adresse</li>
<li>Wenn Ja entferne im Benutzername alle Punkte</li>
<li>Speichere E-Mail-Adresse</li>
</ol>
<p>Wenn nun geprüft werden soll, ob ein Account schon eine E-Mail-Adresse verwendet, wird auf diese der Algorithmus angewandt, und dann z.B. die Datenbank nach der Mail-Adresse durchsucht. Bleibt die Suche erfolglos, darf sich der User registrieren, wenn nicht, ist der User wohl mit einer ähnliche Adresse bereits registriert und sollte darauf hingewiesen werden. <strong>Wichtig ist hierbei, dass der Datenbestand, in dem die Mail-Adresse gesucht wird, bereits die &#8220;gesäuberte Adressen&#8221; besitzt.</strong></p>
<p><span style="text-decoration: underline;"><span style="color: #ff0000;">Hinweis:</span></span> Bei Google-Mail sind gmail.com und googlemail.com möglich. Dies wird vom Script entsprechend beachtet und alle Adressen auf gmail.com umgeschrieben.<strong><br />
</strong></p>
<p>Die Implementierung könnte in PHP z.B. gefolgt aussehen:</p>
<pre class="php" title="code">/**
 * Cleans an e-mail-address (especially Google-Mail-adresses) to avoid duplicates.
 * @param String $emailStr e-mail-address
 */
function clean_email($emailStr) {
	$emailStr = strtolower ($emailStr);
	$tokens = preg_split ("/@/", $emailStr);

	if ($tokens [1] == "gmail.com" || $tokens [1] == "googlemail.com") {
		return str_replace (".", "", $tokens [0]) . "@googlemail.com";
	} else {
		return $emailStr;
	}
}</pre>
<p>Ein Aufruf von</p>
<pre class="php" title="code">echo clean_email("m.a.x.MUELLE.R@gmail.com") . "&lt;br/&gt;";
echo clean_email("m.a.x.MUELLE.R@googlemail.com") . "&lt;br/&gt;";
echo clean_email("max.mueller@web.de");</pre>
<p>hat dann entsprechende folgende Ausgabe:</p>
<pre>maxmueller@googlemail.com
maxmueller@googlemail.com
max.mueller@web.de</pre>
<h2>Epilog</h2>
<p>Nicht immer wenn sich ein User versucht nochmal zu registrieren ist dies beabsichtigt. Ggf. hat der User schlicht vergessen dass er auf einer Seite registriert ist, oder kann sich nicht mehr einloggen, weil er seine Logindaten nicht mehr kennt. Deshalb sollte immer eine entsprechende Meldung ausgegeben werden wie z.B. &#8220;Es ist bereits ein User mit dieser E-Mail-Adresse registriert. Haben Sie Ihr Passwort vergessen?&#8221; mit entsprechenden Link zu einer Seite, wo ein neues Passwort beantragt werden kann.</p>
<p>Auch ist bei Prüfung auf Google-Mail-Adressen und Wegwerf-Adressen natürlich nicht vor einer Mehrfachregistrierung geschützt. Sicher ist das nur über das kostenpflichtige und  zeitaufwendige Postident-Verfahren &#8211; was jedoch im Internet an der Praxis scheitert.</p>
<p><strong>Weitere Informationen:</strong></p>
<ul>
<li><a href="http://mail.google.com/support/bin/answer.py?hl=de&amp;answer=10313">Google Mail-Hilfe &#8211; Empfangen von E-Mail-Nachrichten anderer Personen</a></li>
<li><a href="http://bspamfree.org/">bspamfree.org &#8211; Wegwerf-E-Mail-Adressen</a></li>
<li><a href="http://de.wikipedia.org/wiki/Postident">Wikipedia &#8211; Postident</a></li>
<li><a href="http://www.deutschepost.de/dpag?xmlFile=1015469">Deutsche Post &#8211; Identitätsprüfung</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/05/punkte-in-google-mail-adressen/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP und Geolocation &#8211; Lokalisierung leicht gemacht</title>
		<link>http://blog.root-of-all-evil.com/2010/05/php-und-geolocation-lokalisierung-leicht-gemacht/</link>
		<comments>http://blog.root-of-all-evil.com/2010/05/php-und-geolocation-lokalisierung-leicht-gemacht/#comments</comments>
		<pubDate>Sun, 09 May 2010 17:39:03 +0000</pubDate>
		<dc:creator>Philipp</dc:creator>
				<category><![CDATA[Codeschnipsel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[geocity]]></category>
		<category><![CDATA[geolocation]]></category>
		<category><![CDATA[ip]]></category>
		<category><![CDATA[location]]></category>
		<category><![CDATA[maxmind]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=700</guid>
		<description><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/05/php-und-geolocation-lokalisierung-leicht-gemacht/" title="PHP und Geolocation - Lokalisierung leicht gemacht"></a>Ein Besuch auf www.regnets.in zeigt kurz und knapp die aktuelle Wetterlage für den Standort des Besuchers an. Ermöglicht wird das über Geolocation anhand der IP-Adresse des Benutzers. Natürlich kann der Benutzer auch andere Städte abfragen: www.regnets.in/Hamburg oder www.regnets.in/Berlin. Geolocation lässt &#8230;<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/05/php-und-geolocation-lokalisierung-leicht-gemacht/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/05/php-und-geolocation-lokalisierung-leicht-gemacht/" title="PHP und Geolocation - Lokalisierung leicht gemacht"></a><p>Ein Besuch auf <a href="http://www.regnets.in" target="_blank">www.regnets.in</a> zeigt kurz und knapp die aktuelle Wetterlage für den Standort des Besuchers an. Ermöglicht wird das über Geolocation anhand der IP-Adresse des Benutzers. Natürlich kann der Benutzer auch andere Städte abfragen: <a href="http://www.regnets.in/Hamburg" target="_blank">www.regnets.in/Hamburg</a> oder <a href="http://www.regnets.in/Berlin" target="_blank">www.regnets.in/Berlin</a>.</p>
<p>Geolocation lässt sich beispielsweise mit (kostenlosen) <a href="http://www.maxmind.com/app/geolitecity" target="_blank">GeoLite City von MaxMind</a> sehr einfach in PHP-Projekte integrieren. Mit nur wenigen Dateien und wenigen Zeilen Code lässt sich so der Standort des Besuchers relativ genau (für Deutschland mit<a href="http://www.maxmind.com/app/geolite_city_accuracy" target="_blank"> 71% Trefferquote</a>) bestimmen.<span id="more-700"></span></p>
<p>Die benötigten Dateien&#8230;</p>
<ul>
<li>geoip.inc</li>
<li>geoipcity.inc</li>
<li>geoipregionvars.php</li>
<li>GeoLiteCity.dat &#8211; die eigentliche Datenbank</li>
</ul>
<p>&#8230; lassen sich<a href="http://geolite.maxmind.com/download/geoip/api/php/" target="_blank"> hier herunterladen</a>.</p>
<p>Folgender PHP Code liefert die Geolocation des Besuchers:</p>
<pre class="php" title="code">include("geoipcity.inc");
include("geoipregionvars.php");

function getCity() {

	$gi = geoip_open("GeoLiteCity.dat", GEOIP_STANDARD);
	$record = geoip_record_by_addr($gi, $_SERVER['REMOTE_ADDR']);
	geoip_close($gi);

	return $record-&gt;city;
}</pre>
<p>Das $record-Objekt enthält aber auch noch andere, interessante Daten:</p>
<pre class="php" title="code">print $record-&gt;country_code . " " . $record-&gt;country_code3 . " " . $record-&gt;country_name . "\n";
print $record-&gt;region . " " . $GEOIP_REGION_NAME[$record-&gt;country_code][$record-&gt;region] . "\n";
print $record-&gt;city . "\n";
print $record-&gt;postal_code . "\n";
print $record-&gt;latitude . "\n";
print $record-&gt;longitude . "\n";
print $record-&gt;metro_code . "\n";
print $record-&gt;area_code . "\n";
</pre>
<p>Fragen, Anregungen? Dafür sind die Kommentare da!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/05/php-und-geolocation-lokalisierung-leicht-gemacht/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>fsockopen statt file_get_contents für HTTP-Requests</title>
		<link>http://blog.root-of-all-evil.com/2010/04/fsockopen-statt-file_get_contents-fur-http-requests/</link>
		<comments>http://blog.root-of-all-evil.com/2010/04/fsockopen-statt-file_get_contents-fur-http-requests/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 13:00:05 +0000</pubDate>
		<dc:creator>Felix</dc:creator>
				<category><![CDATA[Codeschnipsel]]></category>
		<category><![CDATA[Erklärungen]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[post]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=737</guid>
		<description><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/04/fsockopen-statt-file_get_contents-fur-http-requests/" title="fsockopen statt file_get_contents für HTTP-Requests"></a>Bei zahlreichen Webspace-Providern ist die Funktionalität von file_get_contents für http deaktiviert. Es treten dann Fehlermeldungen wie Warning: file_get_contents() [function.file-get-contents]: URL file-access is disabled in the server configuration in [..] und Warning: file_get_contents([..]) [function.file-get-contents]: failed to open stream: no suitable wrapper &#8230;<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/04/fsockopen-statt-file_get_contents-fur-http-requests/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/04/fsockopen-statt-file_get_contents-fur-http-requests/" title="fsockopen statt file_get_contents für HTTP-Requests"></a><p>Bei zahlreichen Webspace-Providern ist die Funktionalität von file_get_contents für http deaktiviert. Es treten dann Fehlermeldungen wie</p>
<p><em>Warning: file_get_contents() [function.file-get-contents]: URL file-access is disabled in the server configuration in [..] </em>und<em></em></p>
<p><em>Warning: file_get_contents([..]) [function.file-get-contents]: failed to open stream: no suitable wrapper could be found in [..]</em></p>
<p>auf. Mit folgender Funktion kann man das Verhalten von file_get_contents jedoch emulieren.</p>
<p><span id="more-737"></span></p>
<p>Die Funktion <em>get_contents_by_uri</em> benutzt <em>fsockopen </em>um Inhalte zu laden:</p>
<pre class="php" title="code">/**
 * Gets contents of any webside by an URI.
 * @author http://blog.root-of-all-evil.com
 * @param String $uri
 */
function get_contents_by_uri($uri) {
	$uriElem = parse_url ( $uri );
	$fp = @fsockopen ( $uriElem ['host'], 80, $errno, $errstr, 10 );

	if (! $fp) {
		throw new Exception ( "Could not create socket: '" . $errnstr . "' (" . $errno . ")." );
	}

	$request = "GET " . $uriElem ['path'] . (isset ( $uriElem ['query'] ) ? "?" . $uriElem ['query'] : "") . " HTTP/1.1\r\n";
	$request .= "Host: " . $uriElem ['host'] . "\r\n";
	$request .= "Connection: Close\r\n\r\n";

	fwrite ( $fp, $request );
	$response = "";
	while ( ! feof ( $fp ) ) {
		$response .= fgets ( $fp, 128 );
	}
	fclose ( $fp );

	// split headers from data
	$responseSplit = explode ( "\r\n\r\n", $response, 2 );

	return $responseSplit [1];
}</pre>
<h1>Erklärung</h1>
<p><strong>Socket erstellen</strong></p>
<p>Die übergebene URI wird über die PHP-Funktion<em> parse_url</em> in ihre Teilmengen zerlegt. Anschließend wird ein Socket erstellt für den entsprechenden Host, auf Port 80 mit einem Timeout von 10 Sekunden. Fehlermeldungen unterdrücken wir durch das <em>@</em>, da wir explizit nach Erfolg abfragen und ggf. eine Ausnahme werfen.</p>
<p><strong>Anfrage schicken, Antwort lesen</strong></p>
<p>Danach wird über <em>fwrite </em>eine entsprechende GET-Anfrage geschickt, welche auch &#8211; falls vorhanden &#8211; die Parameter der URI und nicht nur den Pfad beachtet. Die darauffolgende Antwort wird in die Variable <em>response </em>gelesen.</p>
<p><strong>Antwort bearbeiten und zurückgeben</strong></p>
<p>Da diese neben dem eigentlichen Inhalt auch den Antwortheader enthält wird die Funktion <em>explode </em>benutzt um den Inhalt davon abzuschneiden. Durch den dritten Parameter bei <em>explode </em>mit dem Wert 2, stellen wir sicher, dass nur einmalig an Hand einer Leerzeile getrennt wird wie Sie sich zwischen Antwort-Header und HTML-Code befindet und nicht mehrmals, da natürlich auch Leerzeilen im HTML-Code selbst auftreten können.</p>
<p>Das zweite Element von <em>responseSplit </em>wird zurückgegeben, <em>responseSplit[0]</em> würde entsprechend den Antwort-Header liefern.</p>
<h1>Beispielaufrufe</h1>
<p>Der einfachste Aufruf:</p>
<pre class="php" title="code">echo get_contents_by_uri ( 'http://www.google.de/' );</pre>
<p>Aufruf mit Parametern:</p>
<pre class="php" title="code">echo get_contents_by_uri ( 'http://www.google.de/search?hl=de&amp;site=&amp;q=test' );</pre>
<p>Aufruf mit Ausnahmebehandlung:</p>
<pre class="php" title="code">try{
    echo get_contents_by_uri ( 'http://does_not_exist_.com/bogus.html' );
}
catch(Exception $e)
{
    echo "get_contents_by_uri: ".$e-&gt;getMessage();
}</pre>
<p>Weitere Links:</p>
<ul>
<li><a href="http://de2.php.net/parse_url">PHP &#8211; Funktion parse_url</a></li>
<li><a href="http://de2.php.net/fsockopen">PHP &#8211; Funktion file_get_contens</a></li>
<li><a href="http://de2.php.net/fsockopen">PHP &#8211; Funktion fsockopen</a></li>
<li><a href="http://de2.php.net/manual/en/function.explode.php">PHP &#8211; Funktion explode</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/04/fsockopen-statt-file_get_contents-fur-http-requests/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Validierung von URLs mit Zend_Validate</title>
		<link>http://blog.root-of-all-evil.com/2010/04/validierung-von-urls-mit-zend_validate/</link>
		<comments>http://blog.root-of-all-evil.com/2010/04/validierung-von-urls-mit-zend_validate/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 09:45:38 +0000</pubDate>
		<dc:creator>Felix</dc:creator>
				<category><![CDATA[Codeschnipsel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Url erreichbar]]></category>
		<category><![CDATA[Url prüfen]]></category>
		<category><![CDATA[Validator]]></category>
		<category><![CDATA[Validierung]]></category>
		<category><![CDATA[Zend]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend Validator]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=701</guid>
		<description><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/04/validierung-von-urls-mit-zend_validate/" title="Validierung von URLs mit Zend_Validate"></a>Dieser Beitrag beschreibt kurz wie man mit Zend_Validate prüfen kann, ob eine URL / URI syntaktisch korrekt und die verlinkte Ressource erreichbar ist. Aufbau einer URL prüfen Ein eigenständiger Validator ist im Zend Framework nicht vorhanden welcher den Aufbau einer &#8230;<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/04/validierung-von-urls-mit-zend_validate/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/04/validierung-von-urls-mit-zend_validate/" title="Validierung von URLs mit Zend_Validate"></a><p>Dieser Beitrag beschreibt kurz wie man mit Zend_Validate prüfen kann, ob eine <strong>URL / URI syntaktisch korrekt und die verlinkte Ressource erreichbar ist</strong>.</p>
<p><span id="more-701"></span></p>
<h3>Aufbau einer URL prüfen</h3>
<p>Ein eigenständiger Validator ist im Zend Framework nicht vorhanden welcher den Aufbau einer URL / URI prüft. Jedoch bietet <strong>Zend_URI mit der Methode check()</strong> hier eine entsprechende Funktionalität an. Auf diese greifen wir in einem selbst geschriebenen Validator zurück:</p>
<pre class="php" title="code">class Validator_Uri extends Zend_Validate_Abstract {
	const INVALID_URI = 'invalidUri';
	protected $_messageTemplates = array (self::INVALID_URI =&gt; "'%value%' is not a valid URI" );

	public function isValid($value) {
		$this-&gt;_setValue ($value);

		if (! Zend_Uri::check ($value)) {
			$this-&gt;_error ( self::INVALID_URI );
			return false;
		}

		return true;
	}
}</pre>
<h3>Erreichbarkeit einer URL prüfen</h3>
<p>Es ist nicht nur wichtig, dass die Ressourcenangabe in Ihrem Aufbau korrekt ist, sondern auch, dass sich dahinter ein erreichbares Objekt (Webseite, Bild, PDF etc.) befindet.<br />
Mit Hilfe der PHP-Funktion <strong>get_headers prüfen wir den Antwort-Header</strong> auf Erfolg (200 OK). Mit Hilfe des <strong>@ unterdrücken wir eine Fehler-Ausgabe</strong> von PHP, wenn der String an get_headers keine URL sein sollte:</p>
<pre class="php" title="code">class Validator_Uri_Reachable extends Zend_Validate_Abstract {
	const URI_REACHABLE = 'uriReachable';
	protected $_messageTemplates = array (self::URI_REACHABLE =&gt; "'%value%' not reachable" );

	public function isValid($value) {
		$this-&gt;_setValue ( $value );

		$headers = @get_headers ( $value );
		if (! preg_match ( '/200 OK/', $headers [0] )) {
			$this-&gt;_error ();
			return false;
		}

		return true;
	}
}</pre>
<p>Entsprechend kann dann in einem Zend-Formular z.B. eine Homepageadresse geprüft werden:</p>
<pre class="php" title="code">$hpUrl = new Zend_Form_Element_Text ( 'hpUrl' );
$hpUrl-&gt;setLabel ( 'Homepage:' )
			  -&gt;setDescription ( 'Ihre Homepage- oder Blog-Adresse' );
			  -&gt;setAttrib ( 'value', 'http://' )
			  -&gt;addValidator ( new Validator_Uri() )
			  -&gt;addValidator ( new Validator_Uri_Reachable() )</pre>
<p>Weitere Links:</p>
<ul>
<li><a href="http://framework.zend.com/manual/de/zend.validate.writing_validators.html">Zend Framework Dokumentation &#8211; Schreiben von Prüfern</a></li>
<li><a href="http://usphp.com/manual/en/function.get-headers.php">PHP &#8211; Funktion getheaders</a></li>
<li><a href="http://de.wikipedia.org/wiki/URL#Aufbau">Wikipedia &#8211; Aufbau einer URL</a></li>
<li><a href="http://blog.root-of-all-evil.com/2010/03/tools-fur-regex-regulare-ausdrucke/">ROAE Blog &#8211; Tools für Regex / Reguläre Ausdrücke</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/04/validierung-von-urls-mit-zend_validate/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>eBay Trading API Codeschnipsel &#8211; Teil 1</title>
		<link>http://blog.root-of-all-evil.com/2010/04/ebay-trading-api-codeschnipsel-teil-1/</link>
		<comments>http://blog.root-of-all-evil.com/2010/04/ebay-trading-api-codeschnipsel-teil-1/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 16:54:55 +0000</pubDate>
		<dc:creator>Philipp</dc:creator>
				<category><![CDATA[Codeschnipsel]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[duration time format]]></category>
		<category><![CDATA[eBay]]></category>
		<category><![CDATA[ISO 8601]]></category>
		<category><![CDATA[trading]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=343</guid>
		<description><![CDATA[This little sniplet will enable you to parse ISO 8601 Period (Duration) Time Formats into seconds. The ISO 8601 Period is represented by a string like PnYnMnDTnHnMnS where nY represents the number of years, nM the months, nD the days, nH the hours, nM the Minutes and nS the Seconds.
<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/04/ebay-trading-api-codeschnipsel-teil-1/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/04/ebay-trading-api-codeschnipsel-teil-1/" title="eBay Trading API Codeschnipsel - Teil 1"></a><h3>Converting ISO 8601 Duration Time Format in PHP</h3>
<p>This little sniplet will enable you to parse ISO 8601 Period (Duration) Time Formats into seconds. The ISO 8601 Period is represented by a string like PnYnMnDTnHnMnS where nY represents the number of years, nM the months, nD the days, nH the hours, nM the Minutes and nS the Seconds. The T seperates the date (to the left of the T) from the time (to the right of the T). Parsing this string is quite tricky, because unneeded values (like years and months for durations shorter than a month) can be left out. Parsing is also tricky, because we face two &#8220;M&#8221; as identifiers (for months and Minutes).</p>
<p><span id="more-343"></span></p>
<pre class="php" title="code">// ISO 8601 period format PnYnMnDTnHnMnS (e.g., P0Y0M2DT23H32M51S) to seconds
function calcFinishTime($timeleft)
{
	$parsed = array('Y' =&gt; 0, 'Mo' =&gt; 0, 'D' =&gt; 0, 'H' =&gt; 0, 'Mi' =&gt; 0, 'S' =&gt; 0);
	$calcSec = array(12, 31, 24, 60, 60);
	$toParse = preg_split('/T/', strtoupper($timeleft));
	foreach($toParse as $i =&gt; $array) {
		$split = preg_split('/([PYMDTHMS]+)/', $array, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
		$count = count($split);
		for($j = 0; $j &lt; $count; $j++) {
			if(is_numeric($split[$j])) {
				$type = substr($split[$j +1], 0, 1);
				if($i &lt; 1 &amp;&amp; $type == 'M')	$type = 'Mo';
				elseif($type == 'M')		$type = 'Mi';
				$parsed[$type] += (int)$split[$j];
			}
		}
	}
	$k = 0;
	foreach($parsed as $type) {
		$sec = 1;
		for($j = $k; $j &lt; 5; $j++) {
			$sec *= $calcSec[$j];
		}
		$parsed['seconds'] += $sec * $type;
		$k++;
	}
	$parsed['endtime'] = time() + $parsed['seconds'];
	return $parsed;
}</pre>
<p>A input of &#8220;P2DT3H6M24&#8243; will result in an array like this:</p>
<pre class="php" title="code">array(8) {
  ["Y"]=&gt;
  int(0)
  ["Mo"]=&gt;
  int(0)
  ["D"]=&gt;
  int(2)
  ["H"]=&gt;
  int(3)
  ["Mi"]=&gt;
  int(6)
  ["S"]=&gt;
  int(24)
  ["seconds"]=&gt;
  int(183984)
  ["endtime"]=&gt;
  int(1270843142)
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/04/ebay-trading-api-codeschnipsel-teil-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thumbnails erzeugen und Durchschnittsfarbe in PHP ermitteln</title>
		<link>http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln/</link>
		<comments>http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 19:36:22 +0000</pubDate>
		<dc:creator>Philipp</dc:creator>
				<category><![CDATA[Codeschnipsel]]></category>
		<category><![CDATA[Guides]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekt]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[Durchschnittsfarbe]]></category>
		<category><![CDATA[Imagecolorat]]></category>
		<category><![CDATA[Imagecopyresampled]]></category>
		<category><![CDATA[Thumbnails generieren]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=435</guid>
		<description><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln/" title="Thumbnails erzeugen und Durchschnittsfarbe in PHP ermitteln"></a>Eines meiner etwas zurückliegenden Projekte zwang mich externe Bilder durch meinen Server zu laden, zu verkleinern und schließlich auch die Durchschnittsfarbe zu berechnen. Aus Gründen der Performancesteigerung war ich nie ein Fan davon die Durchschnittsfarbe Pixel für Pixel des Originalbildes &#8230;<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln/" title="Thumbnails erzeugen und Durchschnittsfarbe in PHP ermitteln"></a><p>Eines meiner etwas <a title="qolors.net Visual Bookmarking" href="http://www.qolors.net" target="_blank">zurückliegenden Projekte</a> zwang mich externe Bilder durch meinen Server zu laden, zu verkleinern und schließlich auch die Durchschnittsfarbe zu berechnen. Aus Gründen der Performancesteigerung war ich nie ein Fan davon die Durchschnittsfarbe Pixel für Pixel des Originalbildes zu berechnen. <a href="http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln#durchschnittsfarbe" title="zum Berechnen der Durchschnittsfarbe springen">Es gibt eine viel elegantere und fast genauso exakte Lösung</a>:</p>
<p><span id="more-435"></span>Unser Ziel: Wir möchten ein Bild (jpg, gif, png) über einen HTTP-Stream laden,  dieses lokal auf dem Server speichern, ein entsprechendes Thumbnail  (eine verkleinerte Version) erzeugen, speichern und schlussendlich die  dominierende &#8211; oder auch durchschnittliche &#8211; Farbe im Bild berechnen und  abspeichern. Eventuell möchten wir zusätzlich alles in einer Datenbank  hinterlegen &#8211; das soll aber zunächst außerhalb unserer Betrachtung  liegen.</p>
<p>Für das Berechnen der Durchschnittsfarbe gibt es einen wunderbar  einfachen Trick. Doch dazu später mehr. Beginnen wir zunächst einmal mit  einer Konstante und einer Funktion, die wir später noch benötigen:</p>
<pre class="php" title="code">DEFINE('CTX', stream_context_create(array(
    'http' =&gt; array(
        'timeout' =&gt; 20,
        'method' =&gt; 'get',
        'header' =&gt; 'Referer: XYZ'
    )
)));</pre>
<p>Unsere Konstante CTX ist also ein array. Wir benötigen es für unsere  HTTP-Anfrage, mit der wir das gewünschte Bild auf unseren Server laden.  Für diese Anfrage verwenden wir die HTTP-GET-Methode, definieren einen  Timeout von maximal 20 Sekunden und senden einen Referer im Header, den  ich hier mal einfach nur &#8220;XYZ&#8221; genannt habe.</p>
<pre class="php" title="code">function randomstring_creator($len = 20) {
    $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    $string = '';
    mt_srand((double) microtime() * 1000000);
    for($i = 0; $i &lt; $len; $i++) {
        $string .= $chars{mt_rand(0, strlen($chars))};
    }
    return($string);
}</pre>
<p>Die Funktion randomstring_creator() generiert uns eine zufällige Zeichenfolge mit einer beliebigen Länge. Wir benötigen diese Funktion, da wir in diesem Beispiel die Bilder lokal unter einem zufälligem Namen speichern werden.</p>
<p>Weiter geht es mit unseren Klassen. Beginnen wir mit der Klasse <em>Image</em>:</p>
<pre class="php" title="code">class Image {
    var $img;
    var $source;
    var $local;
    var $dimX;
    var $dimY;
    var $avg_colour;
    function get($source, $quality = 90) {
// siehe unten
    }
    function calc_avg_colour() {
// siehe unten
    }
}</pre>
<p>Unsere Klasse besitzt also die Eigenschaften <em>source </em>(die Url,  von der das Bild stammt), <em>local </em>(den lokalen Speicherpfad), <em>dimX</em>,  <em>dimY </em>(die Abmessungen des Bildes in Pixel) und <em>avg_colour</em> (den farblichen Durchschnittswert als HEX-Code in der Form rrggbb). Die  Eigenschaft <em>img </em>ist eine Referenz auf das Image-Objekt, dass ich  aber später noch näher beleuchten werde.</p>
<p>Die beiden Funktionen <em>get()</em> und <em>calc_avg_colour()</em> der  Klasse sollten selbsterklärend sein. Mit der Funktion <em>get()</em>, die  gleichzeitig auch als Konstruktor dient, laden wir das Bild, dass unter <em>source </em>zu finden ist, auf unseren Server und speichern es in der  gewünschten JPEG-Qualität (90 als Standard) lokal.</p>
<p><em>calc_avg_colour()</em> berechnet &#8211; wie der Name schon sagt &#8211; die  Durchschnittsfarbe des in der Eigenschaft <em>img</em> gespeicherten  Bildes.</p>
<p>Wir wollen zusätzlich aber auch kleine Abbilder des Originalbildes  erstellen und erweitern dazu unsere <em>Image</em>-Klasse um die Klasse <em>Thumbnail</em>:</p>
<pre class="php" title="code">class Thumbnail extends Image {
    function create($parent, $X = 300, $Y = 300, $quality = 60) {
// siehe unten
    }
}</pre>
<p>Diese Erweiterung besitzt zunächst nur eine Funktion, mit der das  Thumbnail erstellt wird. Die übergebene Variable <em>parent </em>enthält  dabei eine bereits existierende <em>Image</em>-Klasse, die  herunterskaliert werden soll. Die maximale Breite und Höhe werden mit  den Variablen <em>X</em> und <em>Y</em> (standard bei 300 Pixel) übergeben.  Die JPEG-Qualität beträgt standardmäßig nur 60.</p>
<p>Das eigentliche Programm sieht dann nur noch so aus:</p>
<pre class="php" title="code">$imgurl = 'original.jpg';
// neues Objekt der Klasse Image erzeugen
$img = new Image;
// Bild aus der imgurl laden
if($img-&gt;get($imgurl)) {
    // ein Objekt der Klasse Thumbnail erzeugen
    $thumb = new Thumbnail;
    // und ein Thumbnail des oben definierten Objektes der Klasse Image generieren
    $thumb-&gt;create($img, 300, 300);
    // dann noch die Durschschnittsfarbe berechnen
    $thumb-&gt;calc_avg_colour();
    // und Daten ausgeben... fertig
    echo('Image: ' . $img-&gt;source . "\n");
    echo('Thumbnail: ' . $thumb-&gt;source . "\n");
    echo('Average colour: #' . $thumb-&gt;avg_colour . "\n");
} else {
    echo('Could not get the image.');
}</pre>
<p>So, dann sehen wir uns also mal unsere Funktionen der Klassen an.  Beginnen wir mit der Funktion <em>get()</em>:</p>
<pre class="php" title="code">function get($source, $quality = 90) {
    $this-&gt;source = $source;
    // wir laden das Bild von $source:
    if(($file = file_get_contents($this-&gt;source, false, CTX))) {
        // wenn erfolgreich, erzeugen wir mit den geladenen Daten
        // ein neues Bild und speichern dieses in der Eigenschaft img
        $this-&gt;img = imagecreatefromstring($file);
        // wir lesen die Höhe und Breite des Bildes aus
        $this-&gt;dimX = imagesx($this-&gt;img);
        $this-&gt;dimY = imagesy($this-&gt;img);
        // und speichern das Bild unter zufälligem Namen mit imagejpeg lokal im Ordner "raw"
        $this-&gt;local = 'raw/' . randomstring_creator() . '.jpg';
        imagejpeg($this-&gt;img, $this-&gt;local, $quality);
        // bei Erfolg true zurückgeben
        return(true);
    } else {
        // false, wenn das Bild nicht geladen werden konnte
        return(false);
    }
}</pre>
<p>Ein Thumbnail erzeugen wir mit dieser Funktion der Klasse <em>Thumbnail</em>:</p>
<pre class="php" title="code">function create($parent, $X = 300, $Y = 300, $quality = 60) {
    // zunächst die vorläufigen Abmessungen speichern
    $this-&gt;dimX = $X;
    $this-&gt;dimY = $Y;
    // die Abmessungen und deren Verhältnis des Originalbildes holen
    $origX = $parent-&gt;dimX;
    $origY = $parent-&gt;dimY;
    $ratio = $origX / $origY;
    // wenn das Originalbild breiter als hoch ist, kürzen wir die Höhe
    if($X / $Y &gt; $ratio) {
        $this-&gt;dimX = $Y * $ratio;
    } else {
    // wenn das Originalbild höher als breit ist, kürzen wir die Breite
        $this-&gt;dimY = $X / $ratio;
    }
    // hier erstellen wir ein neues Bild mit den oben berechneten Abmessungen
    $this-&gt;img = imagecreatetruecolor($this-&gt;dimX, $this-&gt;dimY);
    // und kopieren das Originalbild einfach in das eben erstellte kleinere, dabei wird es verkleinert
    imagecopyresampled($this-&gt;img, $parent-&gt;img, 0, 0, 0, 0, $this-&gt;dimX, $this-&gt;dimY, $origX, $origY);
    // jetzt speichern wir das neue Thumbnail noch unter zufälligem Namen im Ordner "thumb"
    $this-&gt;source = $parent-&gt;local;
    $this-&gt;local = 'thumb/' . randomstring_creator() . '.jpg';
    imagejpeg($this-&gt;img, $this-&gt;local, $quality);
}</pre>
<p>Das Herzstück: Wir wollen die  Durchschnittsfarbe ermitteln. Dazu könnten wir einfach alle Farbwerte  aller Pixel zusammen addieren und dann durch die Anzahl der Pixel  teilen. Bei einem Thumbnail von der Größe 300 x 300 Pixel, würden wir  aber eine Schleife mit 90.000 Durchläufen benötigen. Es gibt einen  besseren Weg &#8211; einen ganz logischen Trick.<br />
<a name="durchschnittsfarbe"></a><br />
<h3>Durchschnittsfarbe berechnen</h3>
<p>Wir haben oben beim Erstellen des Thumbnails die Funktion <em>imagecopyresampled()</em> verwendet. Was wenn wir unser Thumbnail einfach auf eine Größe von 1&#215;1  Pixel skalieren? Genau: Es bleibt ein Pixel mit der Durschnittsfarbe  übrig. Dessen Farbe auszulesen ist mit <em>imagecolorat()</em> dann nur  noch eine Kleinigkeit. Los gehts:</p>
<pre class="php" title="code">function calc_avg_colour() {
    // ein temporäres Bild mit den Abmessungen 1x1 Pixel erstellen
    $avrg = imagecreatetruecolor(1, 1);
    // Das Thumbnail einfach reinkopieren, dabei auf 1x1 Pixel skalieren
    imagecopyresampled($avrg, $this-&gt;img, 0, 0, 0, 0, 1, 1, $this-&gt;dimX, $this-&gt;dimY);
    // Die Farbe des verbleibenden Pixels auslesen
    $rgb = imagecolorat($avrg, 0, 0);
    // Das temporäre Bild wieder löschen
    imagedestroy($avrg);
    // Und die Farbe in HEX umwandeln
    $r = dechex($rgb &gt;&gt; 16);
    $g = dechex($rgb &gt;&gt; 8 &amp; 255);
    $b = dechex($rgb &amp; 255);
    if(strlen($r) &lt; 2) $r = 0 . $r;
    if(strlen($g) &lt; 2) $g = 0 . $g;
    if(strlen($b) &lt; 2) $b = 0 . $b;
    // tataaaa... da ist unsere Durchschnittsfarbe:
    $this-&gt;avg_colour = $r . $g . $b;
}</pre>
<p>Super. Das wäre es. Ende und aus.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/02/thumbnails-erzeugen-und-durchschnittsfarbe-in-php-ermitteln/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Serverseitig den Webseitenaufbau mit DNS CNAMES und mehr parallele HTTP-Verbindungen beschleunigen</title>
		<link>http://blog.root-of-all-evil.com/2010/02/serverseitig-den-webseitenaufbau-mit-dns-cnames-und-mehr-parallele-http-verbindungen-beschleunigen/</link>
		<comments>http://blog.root-of-all-evil.com/2010/02/serverseitig-den-webseitenaufbau-mit-dns-cnames-und-mehr-parallele-http-verbindungen-beschleunigen/#comments</comments>
		<pubDate>Sat, 06 Feb 2010 13:44:43 +0000</pubDate>
		<dc:creator>Philipp</dc:creator>
				<category><![CDATA[Codeschnipsel]]></category>
		<category><![CDATA[Guides]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekt]]></category>
		<category><![CDATA[beschleunigen]]></category>
		<category><![CDATA[bilder]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[cnames]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[media]]></category>

		<guid isPermaLink="false">http://blog.root-of-all-evil.com/?p=380</guid>
		<description><![CDATA[Man stelle sich folgendes Szenario vor: Es existiert eine Webseite, die eine Vielzahl von Grafiken, die auf dem gleichem Server hinterlegt sind, einbindet. Diese Webseite wird erfahrungsgemäß eine überdurchschnittlich lange Ladezeit haben. Aber nicht nur aufgrund der zu übertragenen Datenmengen, sondern auch aufgrund der maximalen Anzahl von Verbindungen, die ein Browser auf ein und denselben Server erlaubt. Hier werde ich etwas über die Beschleunigung vom Aufbau von Webseiten schreiben. Dabei verwende ich gewisse DNS Einstellungen, so genannte CNAME-Records mit denen ich serverseitig mehrere parallele HTTP-Verbindungen erlauben kann und so das Laden der Webseite durch den Browser des Nutzers beschleunige.<p class="read-more"><a href="http://blog.root-of-all-evil.com/2010/02/serverseitig-den-webseitenaufbau-mit-dns-cnames-und-mehr-parallele-http-verbindungen-beschleunigen/">Read more &#187;</a></p>]]></description>
			<content:encoded><![CDATA[<a href="http://blog.root-of-all-evil.com/2010/02/serverseitig-den-webseitenaufbau-mit-dns-cnames-und-mehr-parallele-http-verbindungen-beschleunigen/" title="Serverseitig den Webseitenaufbau mit DNS CNAMES und mehr parallele HTTP-Verbindungen beschleunigen"></a><p>Man stelle sich folgendes Szenario vor: Es existiert eine Webseite, die eine Vielzahl von Grafiken, die auf dem gleichem Server hinterlegt sind, einbindet. Diese Webseite wird erfahrungsgemäß eine überdurchschnittlich lange Ladezeit haben. Aber nicht nur aufgrund der zu übertragenen Datenmengen, sondern auch aufgrund der maximalen Anzahl von Verbindungen, die ein Browser auf ein und denselben Server erlaubt. Hier werde ich etwas über die Beschleunigung vom Aufbau von Webseiten schreiben. Dabei verwende ich gewisse DNS Einstellungen, so genannte CNAME-Records mit denen ich serverseitig mehrere parallele HTTP-Verbindungen erlauben kann und so das Laden der Webseite durch den Browser des Nutzers beschleunige.<br />
<span id="more-380"></span></p>
<p>Standardmäßig sind moderne Browser mit maximalen Anzahl von <a href="http://stevesouders.com/ua/report.php?v=top&amp;nosparse=1" target="_blank">sechs Verbindungen (IE 6 und IE 7 maximal zwei Verbindungen)</a> zu ein und demselben Host begrenzt. Das führt dazu, dass das Laden von Dateien (Bilder, HTML-Seiten, JavaScripts oder Stylesheets) von einer Webseite in Blöcken unterteilt wird. Dabei würde es um einiges schneller gehen können, wenn ich die zu ladenden Dateien auf verschiedene Hostnamen verteile. So können für jeden Hostnamen mehr Verbindungen gleichzeitig ermöglicht werden.</p>
<p>Man betrachte zum Beispiel Google Maps. Die angezeigte Karte besteht aus einer vielzahl von so genannten Tiles. Tiles sind einfach Kacheln. Jede Kachel stellt einen Kartenausschnitt dar:</p>
<p><img class="aligncenter size-full wp-image-383" title="2009-08-13_1515-526x395" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/02/2009-08-13_1515-526x395.png" alt="" width="526" height="395" /></p>
<p>Damit die Karte schnellstmöglich trotz der Browserbegrenzung von sechs Verbindungen geladen werden kann, verteilt Google Maps die zu ladenden Kacheln auf verschiedene Hostnamen (Subdomains). Google verwendet vier Subdomains: mt0, mt1, mt2 und mt3.google.de:</p>
<p><img class="aligncenter size-full wp-image-384" title="2009-08-13_1520-526x326" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/02/2009-08-13_1520-526x326.png" alt="" width="526" height="326" /></p>
<p>Grundsätzlich ist es kein großes Problem verschiedene Subdomains anzulegen und die Dateien einer Webseite auf diese Subdomains zu verteilen. Allerdings besteht so recht schnell die Gefahr, dass man als Administrator den Überblick verliert, wo welche Dateien abgespeichert sind. Einfacher wäre es, zB. alle Mediendateien (zB. Bilder, Videos) unter einer Subdomain abzuspeichern. Um das Laden der Startseite erheblich zu beschleunigen, aber ohne zahlreiche Subdomains zu arbeiten kann man wie folgt vorgehen:</p>
<ol>
<li> Ich lege unter der Hauptdomain eine einzige subdomain namens  media.domain an. Hier speichere ich alle Bilder ab.</li>
<li>Ich lege so genannte CNAMES Einträge in meinen DNS Einstellungen an.  Ein CNAME ist &#8211; einfach erklärt &#8211; ein Domain-Alias. In meinem Fall  wähle ich zwei CNAME-Einträge namens &#8220;media0.domain.de&#8221; und  &#8220;media1.domain.de&#8221; an. Am einfachsten geht es über die Adminoberfläche  Plesk und sieht folgendermaße aus:<img class="aligncenter size-full wp-image-385" title="2009-08-13_1601" src="http://blog.root-of-all-evil.com/wp-content/uploads/2010/02/2009-08-13_1601.png" alt="" width="520" height="209" /></li>
<li>Diese beiden Einträge bewirken, dass media0.domain.de und  media1.domain.de auf die gleiche subdomain media.domain.de umleiten. Ich  habe jetzt also eine Subdomain, die auf drei unterschiedliche Weisen  erreicht werden kann. Der Browser des Nutzers interpretiert die drei  Domains als drei unterschiedliche Adressen, die aber auf den gleichen  Speicherort verweisen. So sind drei mal so viele Verbindungen zum eigentlich  gleichen Host möglich. Der Browser wird einfach ausgetrickst.</li>
<li>Bei der Einbindung der Bilder in die Webseite muss ich jetzt nur die  zwei verschiedenen &#8220;subdomains&#8221; media0 und media1 verteilen. Ich löse  das über einen Zufallsgenerator in meinem PHP Script, dass den HTML-Code  generiert. Dieser könnte zB. so aussehen:</li>
</ol>
<pre class="php" title="code">$media_domains = array('media0', 'media1');
foreach($bilder as $bild) {
  shuffle($media_domains);
  echo('&lt;img src="' . $media_domains[0] . '.domain.tld/img/'. $bild . '" /&gt;');
}</pre>
<p>Und fertig. Kommentare, Verbesserungsvorschlage? Dazu sind die Kommentare da.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.root-of-all-evil.com/2010/02/serverseitig-den-webseitenaufbau-mit-dns-cnames-und-mehr-parallele-http-verbindungen-beschleunigen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

