<?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>Tobis Blog &#187; PHP</title>
	<atom:link href="http://blog.aditu.de/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.aditu.de</link>
	<description>Alles rund um Webentwicklung, Fotografie, PHP und weitere interessante Themen</description>
	<lastBuildDate>Wed, 25 Jan 2012 17:30:38 +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>Hintergründe zu selfoss</title>
		<link>http://blog.aditu.de/2011/12/09/hintergrunde-zu-selfoss/</link>
		<comments>http://blog.aditu.de/2011/12/09/hintergrunde-zu-selfoss/#comments</comments>
		<pubDate>Fri, 09 Dec 2011 19:44:38 +0000</pubDate>
		<dc:creator>Tobi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[selfoss]]></category>
		<category><![CDATA[Webentwicklung]]></category>

		<guid isPermaLink="false">http://blog.aditu.de/?p=934</guid>
		<description><![CDATA[In einem Gastbeitrag bei phphatesme schreibe ich über selfoss. Dort stelle ich auch die verschiedenen Bibliotheken vor, die ich für den RSS Reader verwende. Also für Interessierte: schaut einfach rein. Herzlichen Dank an Nils, dass er mir die Möglichkeit gegeben hat, selfoss in seinem Blog vorzustellen.]]></description>
			<content:encoded><![CDATA[<p>In einem <a title="selfoss phphatesme" href="http://www.phphatesme.com/blog/tools/tobias-zeisings-selfoss/">Gastbeitrag bei phphatesme</a> schreibe ich über <a title="selfoss" href="http://selfoss.aditu.de">selfoss</a>. Dort stelle ich auch die verschiedenen Bibliotheken vor, die ich für den RSS Reader verwende. Also für Interessierte: schaut einfach rein.</p>
<p>Herzlichen Dank an Nils, dass er mir die Möglichkeit gegeben hat, selfoss in seinem Blog vorzustellen.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aditu.de/2011/12/09/hintergrunde-zu-selfoss/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>selfoss 1.0 final</title>
		<link>http://blog.aditu.de/2011/11/13/selfoss-1-0-final/</link>
		<comments>http://blog.aditu.de/2011/11/13/selfoss-1-0-final/#comments</comments>
		<pubDate>Sun, 13 Nov 2011 15:20:08 +0000</pubDate>
		<dc:creator>Tobi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[selfoss]]></category>
		<category><![CDATA[Webentwicklung]]></category>

		<guid isPermaLink="false">http://blog.aditu.de/?p=892</guid>
		<description><![CDATA[So, endlich ist es vollbracht. selfoss 1.0 ist verfügbar. Dazu gibt es jetzt auch eine eigene Webseite, wo natürlich die Werbetrommel ordentlich angeheizt wird und mit Buzzwords nur so um sich geworfen wird. Neu verfügbar ist nun neben MySQL ein Datenbankbackend für Sqlite und MongoDB (danke Harald). Zudem habe ich noch ein paar Bugs entfernt. [...]]]></description>
			<content:encoded><![CDATA[<p>So, endlich ist es vollbracht. <a title="Selfoss" href="http://selfoss.aditu.de">selfoss 1.0</a> ist verfügbar. Dazu gibt es jetzt auch eine eigene <a title="Selfoss" href="http://selfoss.aditu.de/">Webseite</a>, wo natürlich die Werbetrommel ordentlich angeheizt wird und mit Buzzwords nur so um sich geworfen wird.</p>
<p><a href="http://selfoss.aditu.de"><img class="alignnone size-full wp-image-894" title="Selfoss Screenshot" src="http://blog.aditu.de/wp-content/uploads/2011/11/projects-selfoss.png" alt="" width="500" height="302" /></a></p>
<p>Neu verfügbar ist nun neben MySQL ein Datenbankbackend für Sqlite und MongoDB (danke <a title="Haralds Blog" href="http://phpblogger.de/">Harald</a>). Zudem habe ich noch ein paar Bugs entfernt. Vielen Dank an alle Betatester. Euer Feedback war echt super!</p>
<p>Auf <a href="http://selfoss.aditu.de">selfoss.aditu.de</a> ist nun auch eine Dokumentation zu finden. Dort ist auch eine kurze Erklärung, wie eigene spouts, also andere Anwendungen und Quellen an Selfoss angeschlossen werden können. Dazu habe ich <a title="Selfoss: Eigene Datenquellen erstellen" href="http://blog.aditu.de/2011/10/17/selfoss-eigene-datenquellen-erstellen/">hier im Blog</a> ja auch schon einmal ein Tutorial geschrieben.</p>
<p>Tja, sonst kann ich nur sagen: schaut euch selfoss einfach einmal an. Ich nutze es ja schon seit einigen Monaten und schätze die schlichte und übersichtliche Art, News zu lesen sehr.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aditu.de/2011/11/13/selfoss-1-0-final/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Selfoss: Eigene Datenquellen erstellen</title>
		<link>http://blog.aditu.de/2011/10/17/selfoss-eigene-datenquellen-erstellen/</link>
		<comments>http://blog.aditu.de/2011/10/17/selfoss-eigene-datenquellen-erstellen/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 17:45:39 +0000</pubDate>
		<dc:creator>Tobi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[selfoss]]></category>
		<category><![CDATA[Webentwicklung]]></category>
		<category><![CDATA[datenquellen]]></category>
		<category><![CDATA[spouts]]></category>

		<guid isPermaLink="false">http://blog.aditu.de/?p=839</guid>
		<description><![CDATA[Letzte Woche habe ich ja den neuen RSS Reader selfoss als Beta Version veröffentlicht. Ein Vorteil von dem Reader ist die Erweiterbarkeit hinsichtlich der Quellen. So können nicht nur RSS Feeds verarbeitet, sondern auch beliebige Quellen angezapft werden (z.B. Logfiles, Email Accounts, Webseiten ohne RSS Feed, Facebook OpenGraph). Manchmal möchte man aber auch nur einzelne Einträge [...]]]></description>
			<content:encoded><![CDATA[<p>Letzte Woche habe ich ja den neuen RSS Reader selfoss als Beta Version <a title="selfoss 1.0 beta" href="http://blog.aditu.de/2011/10/02/selfoss-1-0-beta/">veröffentlicht</a>. Ein Vorteil von dem Reader ist die Erweiterbarkeit hinsichtlich der Quellen. So können nicht nur RSS Feeds verarbeitet, sondern auch beliebige Quellen angezapft werden (z.B. Logfiles, Email Accounts, Webseiten ohne RSS Feed, Facebook OpenGraph).</p>
<p>Manchmal möchte man aber auch nur einzelne Einträge von RSS Feeds um zusätzliche Informationen anreichern. Ich mache das beim RSS Feed von heise, wo der Inhalt des News Beitrages nicht mitgeliefert wird. Diesen lade ich dann einfach in einer speziellen Datenquelle, die sich um diese Funktion von einem gewöhnlichen RSS Feed unterscheidet, nach.</p>
<p>Nun gibt es eine Schritt-für-Schritt Anleitung, wie so eine Datenquelle erstellt werden kann.</p>
<h2>Eine Datenquelle, eine Klasse</h2>
<p>selfoss stellt ein kleines Framework zur Verfügung, das es erlaubt recht einfach neue Datenquellen hinzuzufügen. Dazu muss nur eine einzelne PHP Datei unter<br />
<code>/spouts/your_spouts/your_spout.php</code><br />
abgelegt werden (<code>your_spouts</code> und <code>your_spout</code> kann frei durch einen anderen Namen ersetzt werden). Diese PHP Datei muss eine einzelne Klasse enthalten, welche von der abstrakten Klasse <code>\spouts\spout</code> abgeleitet ist (man beachte, dass selfoss PHP 5.3 voraussetzt und \spouts der Namespace für alle Datenquellen ist).</p>
<h2>Datenelemente der Klasse</h2>
<p>Die eigene Klasse muss drei Datenelemente definieren:</p>
<ul>
<li><strong>name</strong>: der Name der Datenquelle</li>
<li><strong>description</strong>: eine Beschreibung</li>
<li><strong>params</strong>: hier werden die Optionen der Datenquelle festgelegt. Soll z.B. ein Benutzername eingegeben werden, so kann dies hier vorgegeben werden.</li>
</ul>
<p>Folgend gleich ein Beispiel für so eine Klasse. Natürlich fehlen hier noch die Methode, auf die ich gleich eingehe. Es wird eine Datenquelle für einen Email Account via IMAP definiert. Der Benutzer muss, wenn er eine solche neue Email IMAP Quelle definiert, die Email Adresse, das Passwort und den Server eintragen. <code>$params</code> beschreibt diese drei Parameter, legt fest, was für ein Typ diese darstellen und wie die Eingabe des Benutzers validiert wird.</p>
<pre class="brush: php; title: ; notranslate">
&lt;?PHP
namespace spouts\mail;
class imap extends \spouts\spout {
    public $name = 'Email';
    public $description = 'email imap account as source';
    public $params = array(
            &quot;email&quot; =&gt; array(
            &quot;title&quot;      =&gt; &quot;Email&quot;,
            &quot;type&quot;       =&gt; &quot;text&quot;,
            &quot;default&quot;    =&gt; &quot;&quot;,
            &quot;required&quot;   =&gt; true,
            &quot;validation&quot; =&gt; array(&quot;email&quot;)
        ),
        &quot;password&quot; =&gt; array(
            &quot;title&quot;      =&gt; &quot;Password&quot;,
            &quot;type&quot;       =&gt; &quot;password&quot;,
            &quot;default&quot;    =&gt; &quot;&quot;,
            &quot;required&quot;   =&gt; true,
            &quot;validation&quot; =&gt; array(&quot;notempty&quot;)
        ),
        &quot;host&quot; =&gt; array(
            &quot;title&quot;      =&gt; &quot;URL&quot;,
            &quot;type&quot;       =&gt; &quot;text&quot;,
            &quot;default&quot;    =&gt; &quot;&quot;,
            &quot;required&quot;   =&gt; true,
            &quot;validation&quot; =&gt; array(&quot;notempty&quot;)
        )
    );
}
</pre>
<h2>Methoden der Klasse</h2>
<p>Durch die abstrakte Elternklasse <code>\spouts\spout</code> muss die Datenquelle einige Funktionen implementieren. Diese werden dann im laufenden Betrieb von selfoss aufgerufen. Folgendes UML Diagramm gibt einen Überblick über die Struktur:</p>
<p><img class="alignnone size-full wp-image-867" title="selfoss spouts Klassendiagramm" src="http://blog.aditu.de/wp-content/uploads/2011/10/selfoss_spouts_klassendiagramm.png" alt="" width="500" height="437" /></p>
<p>Die Klasse muss drei Dinge implementieren:</p>
<ul>
<li>Sie muss eine Funktion <code>load($params)</code> für das Laden der Informationen zur Verfügung stellen. Diese wird während der Aktualisierung einmal aufgerufen und erhält als Parameter die aktuellen Einstellungen. <code>load($params)</code> muss von der Datenquelle implementiert werden und holt die Daten von der entfernten Quelle (z.B. führt einen IMAP Zugriff aus und lädt aktuelle Emails).</li>
<li>Sie muss das Interface <code>Iterable</code> implementieren. selfoss iteriert, nachdem <code>load()</code> ausgeführt wurde, dann über die einzelnen Einträge (mit Hilfe der Funktionen, die das Interface Iterable vorgibt: <code>rewind, current, key, next, valid</code>). Die einzelnen Einträge könnten z.B. neue Emails sein.</li>
<li>Während selfoss über die einzelnen Einträge iteriert, werden dann die Informationen dieser einzelnen Einträge abgerufen. Dies geschieht über Funktionen, welche durch die abstrakte Klasse <code>\spouts\spout</code> vorgegeben werden. Informationen sind z.B. Betreff einer Email, Email Body usw.</li>
</ul>
<p>Der Ablauf ist dann folgender:</p>
<ol>
<li>Im Beispiel würde <code>load($params)</code> von selfoss mit der vom Benutzer eingegebenen Email, Passwort und Host aufgerufen.</li>
<li>Diese Methode würde dann die Emails vom IMAP Account herunterladen und zwischenspeichern.</li>
<li>selfoss iteriert über die einzelnen Emails (mit <code>rewind, current, key, next, valid</code>).</li>
<li>Bei jedem einzelnen Iterationsschritt (also für jede Email) werden die Email-Informationen abgerufen (Inhalt, Betreff, Datum usw.) und zwar mit Hilfe der Funktionen: <code>getId(), getTitle(), getContent(), getIcon(), getLink(), getDate()</code>.</li>
<li>Um den Rest kümmert sich selfoss (prüfen ob es den Eintrag schon gibt, alte Einträge löschen usw.)</li>
</ol>
<p>Eine Implementierung für diese Funktionen liegt natürlich völlig in der Hand des Entwicklers einer Datenquelle. Daher verweise ich an dieser Stelle auf die vorhandenen Datenquellen. <code>\spouts\spout\feed (\spouts\rss\feed.php)</code> stellt ein gutes Beispiel dar. Wer diese als Vorlage nimmt, kommt recht schnell sehr weit, denn dort werden alle Funktionen genutzt. Soll nur ein Standard RSS Feed um Funktionen erweitert oder angepasst werden, dann verweise ich auch die Klasse <code>\spouts\spout\heise (\spouts\rss\heise.php)</code>. Hier wird lediglich die <code>getContent()</code> überschrieben und ansonsten verhält sich die Datenquelle wie ein gewöhnliches RSS Feed.</p>
<h2>Thumbnails</h2>
<p>Soll anstelle eines Textes ein Vorschaubild angezeigt werden, so muss die Methode <code>getThumbnail()</code> implementiert werden. Diese liefert für einen einzelnen Eintrag das Vorschaubildchen (die URL auf das Bild). <code>\spouts\spout\images (\spouts\rss\images.php)</code> ist ein Beispiel dafür. Diese Datenquelle geht von einem gewöhnlichen RSS Feed aus, durchsucht es nach Bilder (entweder ausgezeichnete Thumbnails im XML des Beitrages, oder das erste Bild im Content des Beitrages) und liefert die URL an selfoss. Das Laden, Verkleinern, Speichern und Aufräumen der Bilder übernimmt selfoss.</p>
<h2>Los gehts&#8230;</h2>
<p>Das war sie, die kurze und knackige Einführung, wie Datenquellen für selfoss entwickelt werden können. Gerne könnt ihr mir dazu Fragen stellen und bei Problemen schreiben (am besten hier im Blog, so dass auch andere von den Antworten profitieren können). Sehr freue ich mich auch über fertige Datenquellen. Gerne nehme ich neue in selfoss auf.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aditu.de/2011/10/17/selfoss-eigene-datenquellen-erstellen/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>selfoss 1.0 beta</title>
		<link>http://blog.aditu.de/2011/10/02/selfoss-1-0-beta/</link>
		<comments>http://blog.aditu.de/2011/10/02/selfoss-1-0-beta/#comments</comments>
		<pubDate>Sun, 02 Oct 2011 21:23:58 +0000</pubDate>
		<dc:creator>Tobi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[selfoss]]></category>
		<category><![CDATA[aggregieren]]></category>
		<category><![CDATA[facebook]]></category>
		<category><![CDATA[RSS]]></category>
		<category><![CDATA[RSS Reader]]></category>
		<category><![CDATA[rsslounge]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[webbased]]></category>

		<guid isPermaLink="false">http://blog.aditu.de/?p=805</guid>
		<description><![CDATA[Wie es scheint, sind einige an selfoss interessiert und nachdem der Reader bei mir schon seit einiger Zeit stabil läuft, ist eine Beta durchaus angebracht. Einführend sollte ich aber ein wenig das Prinzip hinter selfoss erklären, denn das unterscheidet sich von rsslounge. Wer sich also eine verbesserte oder umfangreichere Version von rsslounge erhofft, wird wohl an [...]]]></description>
			<content:encoded><![CDATA[<p>Wie es scheint, sind einige an selfoss interessiert und nachdem der Reader bei mir schon seit einiger Zeit stabil läuft, ist eine Beta durchaus angebracht. Einführend sollte ich aber ein wenig das Prinzip hinter selfoss erklären, denn das unterscheidet sich von <a title="rsslounge webbased RSS Reader" href="http://rsslounge.aditu.de">rsslounge</a>. Wer sich also eine verbesserte oder umfangreichere Version von rsslounge erhofft, wird wohl an dieser Stelle enttäuscht werden.</p>
<p><a title="selfoss screenshot" href="http://blog.aditu.de/wp-content/uploads/2011/10/selfoss-screenshot.png"><img class="alignnone size-full wp-image-808" title="selfoss-screenshot-thumb" src="http://blog.aditu.de/wp-content/uploads/2011/10/selfoss-screenshot-thumb.png" alt="" width="500" height="488" /></a></p>
<p>Benannt habe ich Selfoss nach dem isländischen Wasserfall. Aus vielen Quellen werden Informationen abgegriffen und landen am Ende in einem immerwährenden Storm an Informationen. Das kommt einem Wasserfall irgendwie nahe.</p>
<h2>Features</h2>
<p>selfoss sammelt Nachrichten von verschiedenen Quellen und stellt diese in einem einzigen Stream dar. Es gibt keine Kategorien, keine umfangreichen Optionen oder ein Prioritätensystem, wie bei rsslounge. Die Idee ist nicht neu, immerhin bieten twitter, facebook und wie sie alle heißen als zentrale Anlaufstelle eine &#8220;Pinnwand&#8221; in der aktuelle Meldungen einfach untereinander angezeigt werden. selfoss ist aber darauf ausgelegt, Informationen aus verschiedensten Quellen zu aggregieren. Ein offenes Pluginsystem erlaubt es, einfach neue Datenquellen hinzuzufügen (ein Tutorial dazu werde ich noch verfassen).</p>
<p>Out of the Box unterstützt selfoss folgende Quellen (Wer rsslounge kennt, wird die Liste wiedererkennen):</p>
<ul>
<li>RSS Feeds</li>
<li>RSS Feeds mit Bilder</li>
<li>deviantArt Benutzer, Favoriten und Daily Deviations</li>
<li>Tumblr Blogs</li>
<li>Eigene Twitter Timeline</li>
<li>Twitter Benutzer</li>
<li>Heise Feed mit vollem Text</li>
</ul>
<p>Unterstützt werden auch wieder Bilder, von denen automatisch Thumbnails erzeugt und angezeigt werden. Interessante Einträge können markiert werden und gefiltert angezeigt werden. Zudem steht eine Suche zur Verfügung.</p>
<h2>selfoss als mashup</h2>
<p>Darüber hinaus stellt selfoss die aggregierten Beiträge als ein neues RSS Feed zur Verfügung. Wer also selfoss nur zum Sammeln von Informationen verwenden will, um diese dann via RSS weiter zu verarbeiten, wird hier das Tool seiner Wahl finden. Nachdem es möglich ist, auch eigene Plugins für Datenquellen zu schreiben, können beispielsweise Informationen aus RSS Feeds, Emails und Logfiles zusammengefasst werden.</p>
<h2>selfoss als lifestream</h2>
<p>selfoss lässt sich auch als schreibgeschützte Version konfigurieren, die es nur mit einem angemeldeten Benutzer erlaubt Einstellungen zu ändern. selfoss kann also mit eigenen Inhalten befüllt werden. So könnte man eigene Einträge von Twitter, Facebook, deviantArt und anderen Seiten zusammenfassen und gesammelt in einer Seite anzeigen. Für mich ist das jetzt nicht wirklich ein Feature, aber da es sich angeboten hat auch einen &#8220;Public&#8221; Modus einzubauen, habe ich das vorgesehen.</p>
<h2>Anforderungen</h2>
<p>selfoss benötigt folgende Ausstattung:</p>
<ul>
<li>WebServer (Apache, lighttpd usw.)</li>
<li>MySQL</li>
<li>PHP 5.3 oder höher</li>
<li>Browser (Chrome, Firefox, Safari, IE7+)</li>
<li>iPad und Android</li>
</ul>
<p>Clientseitig läuft es auf allen gängigen Browsern und ist insbesondere auch auf dem iPad oder unter Android lauffähig. Zumindest war mir das wichtig, denn ich will auch mal unterwegs oder vom Sofa aus kurz die aktuellsten News checken.</p>
<p>Standardmäßig ist die .htaccess Konfigurationsdatei für den Apache Webserver dabei, aber eine Konfiguration ist auch unter nginx oder lighttpd möglich (siehe dazu das <a title="Routing Manual PHP Fat Free" href="http://fatfree.sourceforge.net/page/routing-engine">Manual von Fat Free PHP Framework</a>).</p>
<h2>Installation</h2>
<p>Die Installation ist simpel:</p>
<ol>
<li>alle Dateien hochladen (auch die versteckten nicht vergessen)</li>
<li>das data Verzeichnis und dessen Unterverzeichnisse schreibbar machen</li>
<li>in die config.ini die Datenbankverbindung eintragen</li>
<li>CronJob http://&lt;yourselfossurl&gt;/update einrichten</li>
<li>selfoss im Browser aufrufen und Quellen eintragen</li>
</ol>
<h2>Download</h2>
<p>Herunterladen könnt ihr selfoss hier:</p>
<ul>
<li><del>selfoss 1.0 beta (644 kb)</del> mittlerweile gibt es die finale Version: <a title="selfoss" href="http://selfoss.aditu.de">http://selfoss.aditu.de</a></li>
</ul>
<p>Die Sourcen sind auf <a title="selfoss auf github" href="https://github.com/SSilence/selfoss">github</a> zu finden. An der Stelle will ich natürlich auch auf den <a title="Artcore Illustrations" href="http://blog.artcore-illustrations.de/aicons/">Künstler des Logos</a> verweisen.</p>
<h2>Feedback</h2>
<p>Über Feedback freue ich mich natürlich sehr. Ihr könnt mir Emails schreiben, auf diesen Beitrag kommentieren oder das <a title="Ticket System github" href="https://github.com/SSilence/selfoss/issues">Ticket System von github</a> verwenden.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aditu.de/2011/10/02/selfoss-1-0-beta/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>PHP Fat-Free Framework</title>
		<link>http://blog.aditu.de/2011/10/01/php-fat-free-framework/</link>
		<comments>http://blog.aditu.de/2011/10/01/php-fat-free-framework/#comments</comments>
		<pubDate>Sat, 01 Oct 2011 11:10:34 +0000</pubDate>
		<dc:creator>Tobi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[selfoss]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[PHP Fat-Free Framework]]></category>
		<category><![CDATA[Routing]]></category>

		<guid isPermaLink="false">http://blog.aditu.de/?p=759</guid>
		<description><![CDATA[Es gibt ja eine ganze Fülle an PHP Frameworks und jedes wartet mit seinen ganz eigenen Vor- und Nachteilen auf. Für rsslounge habe ich das Zend Framework gewählt und bereue diese Entscheidung nicht, denn es bietet eine Vielzahl an sehr nützlichen Funktionen und sorgt für eine saubere und aufgeräumte Struktur. Ein gravierender Nachteil ist allerdings [...]]]></description>
			<content:encoded><![CDATA[<p>Es gibt ja eine ganze Fülle an PHP Frameworks und jedes wartet mit seinen ganz eigenen Vor- und Nachteilen auf. Für <a title="rsslounge der webbasierte RSS Feed Reader" href="http://rsslounge.aditu.de">rsslounge</a> habe ich das <a title="Zend Framework" href="http://framework.zend.com">Zend Framework</a> gewählt und bereue diese Entscheidung nicht, denn es bietet eine Vielzahl an sehr nützlichen Funktionen und sorgt für eine saubere und aufgeräumte Struktur. Ein gravierender Nachteil ist allerdings die Größe und die hohe Anzahl an Dateien, die das Framework mit sich bringt. Für ein Webprogramm, das anderen zur Verfügung gestellt werden soll und die dies dann auf einen eigenen Server hochladen sollen, ist das ziemlich lästig. Hinzu kommt doch eine gewisse Komplexität, wie man beispielsweise am <a title="Cache es was es wolle" href="http://blog.aditu.de/2009/08/20/cache-es-was-es-wolle/">Cachingverhalten</a> sieht.</p>
<p>Für mein neuestes Projekt wollte ich etwas einfaches, das eine saubere Struktur ermöglicht, aber nicht mit tausenden Dateien und riesigem Funktionsumfang daher kommt. Da ich schon vor einiger Zeit auf das <a title="PHP Fat-Free Framework" href="http://fatfree.sourceforge.net/">PHP Fat-Free Framework</a> gestoßen bin, und es einen sehr guten ersten Eindruck hinterlassen hat, habe ich mich entschlossen mir das Framework etwas genauer anzusehen. Sehr schnell war klar, dass es perfekt geeignet ist.</p>
<p><a href="http://fatfree.sourceforge.net"><img class="alignnone size-full wp-image-762" title="PHP Fat Free Framework" src="http://blog.aditu.de/wp-content/uploads/2011/09/logo.png" alt="" width="320" height="136" /></a></p>
<h2>Features</h2>
<p>Das <a title="PHP Fat-Free Framework" href="http://fatfree.sourceforge.net/">PHP Fat-Free Framework</a> verfügt über alle wichtigen Features, die mittlerweile so Standard sind:</p>
<ul>
<li>Routing Mechanismus (sehr einfach auch im MVC Style realisierbar)</li>
<li>Datenbankzugriff (sogar mit einem mini ORM und einem MongoDB mapper)</li>
<li>Template Engine</li>
<li>Schnick Schnack wie: On-the-fly JavaScript/CSS compressor, CAPTCHA generator, OpenID, usw.</li>
</ul>
<p>Die Template Engine konnte mich nicht ganz überzeugen, hier habe ich selbst Hand angelegt, eine kleine Hilfsklasse geschrieben und auf den in PHP integrierten Syntax zurückgegriffen. Ansonsten konnte das Framework in voller Linie überzeugen. Selbst eine Migration um eine Major Version funktionierte mit sehr geringem Aufwand, was mich doch sehr überrascht hat.</p>
<h2>Anforderungen</h2>
<p>Das Framework selbst ist sehr klein und wird mit einer einzigen 55KB großen PHP Datei beworben. Ganz richtig ist das aber nicht: Der Datenbankzugriff und weitere Funktionen wurden in Plugins ausgelagert. Nimmt man den gesamten Funktionsumfang, so hat man 27 Dateien mit einer gesamten Größe von 223 KB, was natürlich immernoch sehr schlank ist.</p>
<p>Ein bestimmter Server ist nicht erforderlich und das Manual bietet Anleitungen für das Umschreiben der URLs für den <a title="Manual mod_rewrite Apache für Fatfree PHP" href="http://fatfree.sourceforge.net/page/routing-engine/sample-apache-configuration">Apache Webserver</a>, <a title="Manual URL Umschreiben in lighttpd" href="http://fatfree.sourceforge.net/page/routing-engine/sample-lighttpd-configuration">lighttpd</a> und <a title="Manual URL Umschreiben nginx" href="http://fatfree.sourceforge.net/page/routing-engine/sample-nginx-configuration">nginx</a>. Einziger Wermutstropfen: Es benötigt mindestens PHP 5.3, was für einen simplen RSS Reader, der möglichst überall laufen soll eine doch recht hohe Anforderung ist. Gleichzeitig liefert diese Anforderung auch zahlreiche Vorteile, wie beispielsweise schlankeren Code durch Lambda-Funktionen oder der Einsatz von Namespaces.</p>
<h2>F3 in der Praxis</h2>
<p>Warum mir das Framework so zusagt, sieht man schnell, wenn man ein paar Zeilen Code sieht. Ein Beispiel ist das Routing:</p>
<pre class="brush: php; title: ; notranslate">
require __DIR__.'/libs/f3/base.php';
F3::set('AUTOLOAD','libs/f3/|libs/|libs/WideImage/|models/|libs/twitteroauth|libs/FeedWriter');
F3::route('GET /', 'controllers\Index-&gt;home');
F3::route('GET /mark/@item', 'controllers\Items-&gt;mark');
F3::route('POST /source', 'controllers\Sources-&gt;add');
F3::route('PUT /source/@id', 'controllers\Sources-&gt;write');
</pre>
<p>Mit der ersten Zeile wird das Framework eingebunden. Mit der zweiten wird ein Autoloader registriert und die entsprechenden Inlcude-Pfade gesetzt (das Pipe Symbol | dient hier als Trennzeichen. Dann werden die Routen definiert. Das Fat-Free Framework unterstützt hierbei auch den REST Ansatz und einzelne URLs können mehrfach, je nach Art des HTTP Requests belegt werden. In diesem Beispiel wird bei einem GET Aufruf der URL / die Klasse \controllers\Index instaziiert und dort die Methode home aufgerufen.</p>
<p>Ähnlich einfach ist der Datenbankzugriff:</p>
<pre class="brush: php; title: ; notranslate">
F3::set('DB',
	new DB(
		'mysql:host=localhost;port=3306;dbname=mysqldb',
		'admin',
		'p455w0rD'
	)
);
DB::sql('SELECT brandName FROM wherever');
foreach (F3::get('DB-&gt;result') as $row) {
	// whatever you want to do with $row
}
</pre>
<p>Um SQL Injection vorzubeugen, werden natürlich auch <a title="Manual PHP Fat Free Framework parameterized Queries" href="http://fatfree.sourceforge.net/page/sql-handler/parameterized-queries">parametrisierte Queries</a> unterstützt.</p>
<p>Ähnlich simpel ist das gesamte Framework gestrickt und meist bietet es verschiedene Wege etwas umzusetzen. Besonders elegant finde ich das Routing mit Lambda Funktionen:</p>
<pre class="brush: php; title: ; notranslate">
F3::route('GET /about',
	function() {
		echo 'No subliminal messages here...';
	}
);
</pre>
<h2>Lizenz und Downloads</h2>
<p>Das Framework steht unter der GPLv3 Lizenz zur Verfügung, es wird aber auch eine kostenpflichtige, kommerzielle Lizenz angeboten. Das finde ich das einzige Manko, hier bietet beispielsweise das Zend Framework unter der MIT Lizenz sehr viel mehr Möglichkeiten.</p>
<p>Zur Projektseite des PHP Fat-Free Frameworks: <a href="http://fatfree.sourceforge.net/">http://fatfree.sourceforge.net/</a></p>
<pre></pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.aditu.de/2011/10/01/php-fat-free-framework/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Neue Version rsslounge 1.7</title>
		<link>http://blog.aditu.de/2011/02/20/neue-version-rsslounge-1-7/</link>
		<comments>http://blog.aditu.de/2011/02/20/neue-version-rsslounge-1-7/#comments</comments>
		<pubDate>Sun, 20 Feb 2011 11:58:25 +0000</pubDate>
		<dc:creator>Tobi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[rsslounge]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[feed reader]]></category>
		<category><![CDATA[google reader]]></category>
		<category><![CDATA[RSS]]></category>

		<guid isPermaLink="false">http://blog.aditu.de/?p=715</guid>
		<description><![CDATA[Nach langer Zeit ist es nun mal wieder so weit: eine neue Version von rsslounge ist verfügbar. Es gibt einige Änderungen und Optimierungen. Neue Features und größere Umbauten sind immer eine Frage der Zeit. Ich habe ja einiges auf der Wunschliste und auch im Forum haben einige Wünsche geäußert. Besonders interessant ist eine Funktion, so [...]]]></description>
			<content:encoded><![CDATA[<p>Nach langer Zeit ist es nun mal wieder so weit: eine neue Version von <a title="RSS Feed aggregator rsslounge" href="http://rsslounge.aditu.de">rsslounge</a> ist verfügbar. Es gibt einige <a title="Changelog" href="http://code.google.com/p/rsslounge/wiki/Changelog">Änderungen und Optimierungen</a>. Neue Features und größere Umbauten sind immer eine Frage der Zeit. Ich habe ja einiges auf der <a title="Feature Request Liste rsslounge" href="http://code.google.com/p/rsslounge/issues/list?can=2&amp;q=Feature+Request">Wunschliste</a> und auch im <a title="rsslounge forum" href="http://rsslounge.aditu.de/forum">Forum</a> haben einige Wünsche geäußert. Besonders interessant ist eine Funktion, so dass aus den gesammelten Feedbeiträgen wieder ein RSS Feed erzeugt wird. Das kann dann an beliebiger Stelle (z.B. in einer Android RSS App) eingebunden werden.</p>
<p><a title="rsslounge" href="http://rsslounge.aditu.de"><img class="alignnone size-full wp-image-718" title="rsslounge" src="http://blog.aditu.de/wp-content/uploads/2011/02/rsslounge.jpg" alt="" width="500" height="334" /></a></p>
<p>An dieser Stelle vielen Dank an alle, die mich mit Sprachdateien versorgt haben und mir Feedback geben. Sofern ich die Zeit finde, versuche ich sinnvolle Neuerungen einzubauen. Die Performance zu optimieren (besonders das erstmalige Laden von rsslounge zu beschleunigen) war im aktuellen Update mein primäres Anliegen. Die Änderungsliste ist im <a title="rsslounge changelog" href="http://code.google.com/p/rsslounge/wiki/Changelog">Changelog</a> zu finden.</p>
<p>Download: <a title="rsslounge download" href="http://code.google.com/p/rsslounge/downloads/list">rsslounge 1.7</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aditu.de/2011/02/20/neue-version-rsslounge-1-7/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Zend_Translate: Fallback für Übersetzungen</title>
		<link>http://blog.aditu.de/2011/02/01/zend_translate-fallback-fur-ubersetzungen/</link>
		<comments>http://blog.aditu.de/2011/02/01/zend_translate-fallback-fur-ubersetzungen/#comments</comments>
		<pubDate>Tue, 01 Feb 2011 17:06:08 +0000</pubDate>
		<dc:creator>Tobi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[rsslounge]]></category>
		<category><![CDATA[Webentwicklung]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[Zend_Translate]]></category>

		<guid isPermaLink="false">http://blog.aditu.de/?p=690</guid>
		<description><![CDATA[Häufig kommt es vor, dass Sprachdateien nicht vollständig sind. Ich habe den Effekt bei rsslounge, da ich hier von verschiedenen Personen Sprachdateien bekomme. Da ich nicht sicherstellen kann, ob auch wirklich jeder Key der Sprachdatei übersetzt wurde (außer ich prüfe manuell die gesamte Datei), bietet es sich an, einfach als Fallback-Lösung die entsprechende englische Übersetzung [...]]]></description>
			<content:encoded><![CDATA[<p>Häufig kommt es vor, dass Sprachdateien nicht vollständig sind. Ich habe den Effekt bei <a title="rsslounge free rss feed reader" href="http://rsslounge.aditu.de">rsslounge</a>, da ich hier von verschiedenen Personen Sprachdateien bekomme. Da ich nicht sicherstellen kann, ob auch wirklich jeder Key der Sprachdatei übersetzt wurde (außer ich prüfe manuell die gesamte Datei), bietet es sich an, einfach als Fallback-Lösung die entsprechende englische Übersetzung zu verwenden.</p>
<p><a title="Zend Framework Manual" href="http://framework.zend.com/manual/de/zend.translate.html">Zend_Translate</a> bietet hier eine einfache Möglichkeit &#8220;Routen&#8221; zu erstellen. Das heißt man kann festlegen, welche Sprache alternativ verwendet werden soll. Dabei können sogar Ketten gebildet werden (z.B. wenn Französisch nicht gefunden wurde, dann in der deutschen Übersetzung suchen und wenn dort auch nichts gefunden wird, in der englischen). Wobei sich mir der Sinn von so einer Verkettung nicht ganz erschließt.</p>
<p>Das setzen einer Route ist sehr einfach. Folgendes Beispiel scanned ein übergebenes Verzeichnis nach CSV Dateien und übernimmt deren Inhalt als Übersetzung. Mit dem Key &#8220;route&#8221; wird definiert, wie die Sprachen verkettet werden sollen. In diesem Beispiel ist Englisch die Fallbacksprache für Deutsch und Französisch.</p>
<pre class="brush: php; title: ; notranslate">
$language = new Zend_Translate(
            'csv',    // Typ der Quelle: hier csv Dateien
            'locale', // Quell-Verzeichnis
            'en',     // Standard Sprache
            array(    // Optionen
                'scan' =&gt; Zend_Translate::LOCALE_DIRECTORY,
                'route'     =&gt; array( 'de' =&gt; 'en', 'fr' =&gt; 'en' )
            ));
</pre>
<p>Der sauberste Weg ist es natürlich alle Schlüssel auf zu übersetzen. Beim Aufspüren von fehlenden Übersetzungen <a href="http://blog.aditu.de/2009/03/10/zend_translate-fehlende-ubersetzungen-loggen/">hilft Zend_Translate ebenfalls</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aditu.de/2011/02/01/zend_translate-fallback-fur-ubersetzungen/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Web Tipps &#124; 1</title>
		<link>http://blog.aditu.de/2010/10/03/web-tipps-1/</link>
		<comments>http://blog.aditu.de/2010/10/03/web-tipps-1/#comments</comments>
		<pubDate>Sun, 03 Oct 2010 16:50:03 +0000</pubDate>
		<dc:creator>Tobi</dc:creator>
				<category><![CDATA[deviantArt]]></category>
		<category><![CDATA[Fotografie]]></category>
		<category><![CDATA[Internet]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Einsamer Wolf]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Mantikore Verlag]]></category>
		<category><![CDATA[Monkey Island]]></category>
		<category><![CDATA[sintel]]></category>
		<category><![CDATA[tumblr]]></category>

		<guid isPermaLink="false">http://blog.aditu.de/?p=574</guid>
		<description><![CDATA[Wer einen Blog hat, kennt das Problem: man hat zwar Themen und Interessantes, die Zeit sofort zu bloggen fehlt aber. Daher habe ich mir überlegt einfach eine kleine, neue Serie &#8220;Web Tipps&#8221; einzuführen. In dieser Beitrag-Serie sammle ich interessantes aus dem Netz. Manches, was etwas kommerziell ist und auch etwas speziellere Dinge. Ein kurzes überfliegen [...]]]></description>
			<content:encoded><![CDATA[<p>Wer einen Blog hat, kennt das Problem: man hat zwar Themen und Interessantes, die Zeit sofort zu bloggen fehlt aber. Daher habe ich mir überlegt einfach eine kleine, neue Serie &#8220;Web Tipps&#8221; einzuführen. In dieser Beitrag-Serie sammle ich interessantes aus dem Netz. Manches, was etwas kommerziell ist und auch etwas speziellere Dinge. Ein kurzes überfliegen lohnt also.</p>
<h3><a title="The Secret of Monkey Island for ipad" href="http://itunes.apple.com/us/app/the-secret-monkey-island-special/id390454624?mt=8">The Secret of Monkey Island: Special Edition, for iPad</a></h3>
<p>Guybrush Threepwood ist wieder unterwegs und zwar diesmal auf dem iPad. Einfach ein Genuss für jeden, der die Originale kennt. Die Special Edition wartet mit neu gezeichneten Grafiken auf und erlaubt ein flüssiges Wechseln zwischen der alten und neuen Fassung. Auf dem iPad ein besonderer Genuss.</p>
<p><a title="The secret of monkey island iPad" href="http://itunes.apple.com/us/app/the-secret-monkey-island-special/id390454624?mt=8"><img class="alignnone size-full wp-image-579" title="The Secret of Monkey Island for iPad" src="http://blog.aditu.de/wp-content/uploads/2010/10/mzl.hsmzpkfh.480x480-75.jpg" alt="" width="480" height="360" /></a></p>
<h3><a title="Einsamer Wolf Band 4" href="http://www.mantikore-verlag.de/index2.php">Einsamer Wolf Band 4: Die Schlucht des Schicksals</a></h3>
<p>Es ist wieder soweit: ein weiterer Band der halbjährlich erscheinenden Neuauflage des Rollenspiel Klassikers Einsamer Wolf gibt es seit wenigen Tagen zu bestellen.</p>
<p><a title="Einsamer Wolf Band 4" href="http://www.mantikore-verlag.de/index2.php"><img class="alignnone size-full wp-image-577" title="Einsamer Wolf Band 4 Cover" src="http://blog.aditu.de/wp-content/uploads/2010/10/EW04_web.jpg" alt="" width="264" height="400" /></a></p>
<h3><a title="jQuery.dform" href="http://neyeon.com/p/dform/doc/">jQuery.dform</a></h3>
<p>Dieses Projekt von <a title="Daffs Blog" href="http://daff.neyeon-digital.de/blog/">Daff</a> bietet ein jQuery Plugin, dass aus einer JSON-formatierten Beschreibung ein HTML Formular erzeugt. Besonders interessant ist das für alle, die möglichst die gesamte Logik in JavaScript halten wollen. Eine kleine Besonderheit: jQuery UI wird gleich mit unterstützt. Stelle mir das in Kombination mit einem PHP Backend sehr praktisch vor, wenn es um das Nachladen von Formularen geht.</p>
<p><a title="jQuery.dform" href="http://neyeon.com/p/dform/doc/"><img class="alignnone size-full wp-image-580" title="jquery.dform" src="http://blog.aditu.de/wp-content/uploads/2010/10/jquery.dform_.jpg" alt="" width="500" height="340" /></a></p>
<h3><a title="deviantart @tumblr" href="http://deviantart.tumblr.com/">deviantArt @tumblr</a></h3>
<p>DeviantArt ist nun auch auf <a title="tumblr" href="http://www.tumblr.com/">tumblr</a> zu finden. Dort werden herausragende Kunstwerke vorgestellt. Auf jeden Fall gelungen, hab deviantart @tumblr schon in meine rsslounge Aboliste hinzugefügt (btw: [Werbung]rsslounge unterstützt tumblr Profile[/Werbung] ).</p>
<p><a title="deviantart @tumblr" href="http://deviantart.tumblr.com/"><img class="alignnone size-full wp-image-582" title="deviantart @tumblr" src="http://blog.aditu.de/wp-content/uploads/2010/10/deviantart@tumblr.jpg" alt="" width="500" height="377" /></a></p>
<h3><a title="Sintel WebSeite" href="http://www.sintel.org/">Sintel</a></h3>
<p>Basierend auf dem OpenSource Programm Blender wurde mittlerweile der dritte Film erstellt. Einfach sehenswert, mehr will ich dazu nicht sagen.</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="560" height="340" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/eRsGyueVLvQ?fs=1&amp;hl=de_DE" /><param name="allowfullscreen" value="true" /><embed type="application/x-shockwave-flash" width="560" height="340" src="http://www.youtube.com/v/eRsGyueVLvQ?fs=1&amp;hl=de_DE" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<h3>Neue Fotos</h3>
<p>Ein paar wenige, neue Fotos gibt es auch von mir, die ich auch niemanden vorenthalten will <img src='http://blog.aditu.de/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><a title="neural rust" href="http://ssilence.deviantart.com/art/neural-rust-178973668?q=sort%3Atime+gallery%3Assilence&amp;qo=2"><img class="alignnone size-full wp-image-586" title="neural rust" src="http://blog.aditu.de/wp-content/uploads/2010/10/neural_rust_tobias_zeising.jpg" alt="" width="500" height="333" /></a></p>
<p><a title="coming home" href="http://ssilence.deviantart.com/art/coming-home-179567235?q=sort%3Atime+gallery%3Assilence&amp;qo=1"><img title="coming home" src="http://blog.aditu.de/wp-content/uploads/2010/10/coming_home_tobias_zeising.jpg" alt="" width="500" height="333" /></a></p>
<p><a title="love returns" href="http://ssilence.deviantart.com/art/love-returns-181355374?q=sort%3Atime+gallery%3Assilence&amp;qo=0"><img class="alignnone size-full wp-image-585" title="love returns" src="http://blog.aditu.de/wp-content/uploads/2010/10/love_returns_tobias_zeising.jpg" alt="" width="500" height="328" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aditu.de/2010/10/03/web-tipps-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Automatisiertes Priorisieren von RSS Feed Beiträgen mittels maschinellem Lernen</title>
		<link>http://blog.aditu.de/2010/07/30/automatisiertes-priorisieren-von-rss-feed-beitragen-mittels-maschinellem-lernen/</link>
		<comments>http://blog.aditu.de/2010/07/30/automatisiertes-priorisieren-von-rss-feed-beitragen-mittels-maschinellem-lernen/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 16:05:18 +0000</pubDate>
		<dc:creator>Tobi</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[rsslounge]]></category>
		<category><![CDATA[Information Retrieval]]></category>
		<category><![CDATA[k-nächste-Nachbarn]]></category>
		<category><![CDATA[Klassifikation]]></category>
		<category><![CDATA[maschinelles lernen]]></category>
		<category><![CDATA[RSS]]></category>
		<category><![CDATA[support vektor maschinen]]></category>
		<category><![CDATA[svm]]></category>
		<category><![CDATA[Text Klassifikation]]></category>

		<guid isPermaLink="false">http://blog.aditu.de/?p=534</guid>
		<description><![CDATA[Ich hatte ja bereits in einem früheren Beitrag erwähnt, dass ich mich daran versucht habe den RSS Reader rsslounge lernfähig zu machen. Dazu sollte der Benutzer neue Beiträge als interessant oder uninteressant klassifizieren können. Ausgehend von der Bewertung dieser bestehenden Einträgen durch den Benutzer, sollten dann neue Feed-Beiträge automatisch weiter nach oben (Interessantes) oder nach unten [...]]]></description>
			<content:encoded><![CDATA[<p>Ich hatte ja bereits in einem früheren Beitrag erwähnt, dass ich mich daran versucht habe den RSS Reader <a title="rsslounge aggregator" href="http://rsslounge.aditu.de">rsslounge</a> lernfähig zu machen. Dazu sollte der Benutzer neue Beiträge als interessant oder uninteressant klassifizieren können. Ausgehend von der Bewertung dieser bestehenden Einträgen durch den Benutzer, sollten dann neue Feed-Beiträge automatisch weiter nach oben (Interessantes) oder nach unten (Uninteressantes) einsortiert werden.</p>
<p>Hierfür habe ich verschiedene Verfahren der Test-Klassifikation aus dem Information Retrieval in Betracht gezogen und hinsichtlich ihrer Eignung bezüglich des Problems untersucht. Anschließend habe ich als Referenz die Lernfähigkeit mittels dem naiven Bayes-Klassifikators implementiert. Als zweite Lösung habe ich das k-nächste-Nachbarn Verfahren, basierend auf dem simulierten Abkühlen implementiert und untersucht, ob eine der beiden Lösungen für dieses Problem in Frage kommt. Das Ergebnis ist ist leider sehr ernüchternd.</p>
<p>Trotzdem möchte ich hierzu das Paper, das ich dazu verfasst habe, veröffentlichen. Zum einen gibt es einen guten Überblick und eine gute Einführung in die gängigen Verfahren der Text-Klassifikation, zum anderen halte ich das optimierte k-nächste-Nachbarn Verfahren für sehr leistungsfähig. Für passende Problemstellungen ist das ein praxistauglicher Lösungsweg.</p>
<p>Nachdem ich die gesamte Entwicklung von rsslounge offen gelegt habe, halte ich es für sinnvoll auch diesen Versuch (und das damit verbundene Paper) zu veröffentlichen. Vielleicht inspiriere ich jemanden, oder liefere für weitere Arbeiten eine Grundlage bzw. Informationen.</p>
<p>Das Paper als PDF zum Download (1.5MB): <a href="http://blog.aditu.de/wp-content/uploads/2010/07/Automatisiertes-Priorisieren-von-RSS-Feed-Beiträgen-mittels-maschinellem-Lernen.pdf">Automatisiertes Priorisieren von RSS Feed Beiträgen mittels maschinellem Lernen</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aditu.de/2010/07/30/automatisiertes-priorisieren-von-rss-feed-beitragen-mittels-maschinellem-lernen/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ServerBridge zwischen PHP und C/C++</title>
		<link>http://blog.aditu.de/2010/05/15/serverbridge-zwischen-php-und-cc/</link>
		<comments>http://blog.aditu.de/2010/05/15/serverbridge-zwischen-php-und-cc/#comments</comments>
		<pubDate>Sat, 15 May 2010 11:11:14 +0000</pubDate>
		<dc:creator>Tobi</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Webentwicklung]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[mongoose]]></category>
		<category><![CDATA[Zend Server]]></category>

		<guid isPermaLink="false">http://blog.aditu.de/?p=428</guid>
		<description><![CDATA[Jetzt ist es schon wieder einige Zeit her, dass ich hier etwas geschrieben habe und ich denke ich gebe mal ein Lebenszeichen von mir. Natürlich gibt es zahlreiche interessante Themen in meiner Queue zum bloggen, aber wie immer findet man nicht die Zeit oder nötige Ruhe dazu. Die Problemstellung Nun aber zum Thema: für ein [...]]]></description>
			<content:encoded><![CDATA[<p>Jetzt ist es schon wieder einige Zeit her, dass ich hier etwas geschrieben habe und ich denke ich gebe mal ein Lebenszeichen von mir. Natürlich gibt es zahlreiche interessante Themen in meiner Queue zum bloggen, aber wie immer findet man nicht die Zeit oder nötige Ruhe dazu.</p>
<h2>Die Problemstellung</h2>
<p>Nun aber zum Thema: für ein aktuelles Projekt benötige ich, von meiner PHP Webapplikation heraus, den Zugriff auf einige Hardwarekomponenten. Zudem will ich einige Fremdbibliotheken verwenden, die sehr rechenintensive Aufgaben übernehmen und auch nur in C++ zur Verfügung stehen. Die Frage ist also: wie kann ich diese Komponenten an mein PHP Programm ankoppeln?</p>
<p>Für Java gibt es eine ganz gute <a title="PHP Java Bridge" href="http://php-java-bridge.sourceforge.net/pjb/">Server Bridge</a>, die innerhalb der Java Virtual Machine einfach einen kleinen Server startet, der XML Anfragen entgegen nimmt, stellvertretend ausführt und das Ergebnis, auch wieder über eine XML Kommunikationsschnittstelle, zur Verfügung stellt. Die nötige PHP Klasse wird ebenfalls durch den Java Server direkt zur Verfügung gestellt. Eine ähnliche Bridge Lösung bringt auch der <a title="Zend Server Community Edition" href="http://www.zend.com/de/products/server-ce/">Zend Server</a> bereits out of the box mit.</p>
<p>Für C++ habe ich so eine Lösung nicht gefunden und als weiteren Ansatz überlegt, eine PHP Extension zu entwickeln. Sowohl für Linux, als auch für Windows, gibt es hier Tutorials (siehe &#8220;<a title="Extension-Entwicklung unter WAP" href="http://www.phpforum.de/forum/showthread.php?t=244096">Extension-Entwicklung unter WAP</a>&#8220;, &#8220;<a title="Wrapping C++ Classes in a PHP Extension" href="http://devzone.zend.com/article/4486-Wrapping-C-Classes-in-a-PHP-Extension">Wrapping C++ Classes in a PHP Extension</a>&#8221; oder &#8220;<a title="Extension Writing Part I: Introduction to PHP and Zend" href="http://devzone.zend.com/article/1021">Extension Writing Part I: Introduction to PHP and Zend</a>&#8220;). Allerdings ist, neben den Tutorials, der ganze Vorgang nicht gut dokumentiert und scheinbar muss das Kompilat der Extension exakt dem des verwendeten PHP Kompilats entsprechen. Insgesamt also eher eine wackelige Angelegenheit.</p>
<h2>Lösungsansatz</h2>
<p>Meine Lösung ist hingegen pragmatisch und verfolgt eine eher losere Kopplung: Meine C++ Komponenten werden in ein eigenständiges Programm ausgelagert, das selbst, über einen gewöhnlichen HTTP Server, die benötigten Dienste zur Verfügung stellt. Dabei orientiere ich mich an dem REST Architektur Prinzip und binde jeweils eine Teil-Funktionalität an eine feste URL. Die Parameter und Rückgabewerte werden mittels JSON kodiert. Von PHP Seite aus, wird der Aufruf der C++ Komponenten sauber gekapselt, so dass für das PHP Programm der Eindruck entsteht, dass eine gewöhnliche Funktion aufgerufen wird.</p>
<p>Welche Vor- und Nachteile hat das Vorgehen? Zum einen ist die in C++ implementierte Funktionalität sauber gekapselt und von der Webapplikation getrennt. Dadurch wird die Software leichter wartbar. Durch eine saubere Schnittstellendefinition, kann die C++ Serverkomponente auch unabhängig vom Wissen über die PHP Applikation gepflegt werden. Zum anderen entsteht aber ein zusätzlicher Aufwand (mit zusätzlichen Fehlerquellen). Die Schnittstelle muss definiert und implementiert werden, ein Fehlerhandling muss durchgeführt werden und eine zusätzliche Serverapplikation muss gestartet werden, was hinsichtlich der Sicherheit berücksichtigt werden muss. Dennoch halte ich die Lösung für die eleganteste, denn sie nutzt genau die Vorteile der Vernetzung und der losen Kopplung aus. So könnte die C++ Komponente bei höherer Last auch leicht auf einen eigenen Server umgezogen oder unabhängig von der Webapplikation betrieben werden.</p>
<h2>Implementierung</h2>
<p>In der Theorie hört sich natürlich immer alles ganz nett an, aber wie sieht das mit dem HTTP Server aus? Hier gibt es eine hervorragende C++ Bibliothek, mit der sich ohne großen Aufwand eine solcher HTTP Server realisieren lässt. <a title="mongoose" href="http://code.google.com/p/mongoose/">mongoose</a> heißt das Wunderding, steht unter der MIT Lizenz unter <a title="mongoose" href="http://code.google.com/p/mongoose/">Google Code</a> zur Verfügung. Es unterstützt Windows, Linux und Mac OS X, bietet eine CGI Schnittstelle, SSL Verschlüsselung, ACL, eine saubere API und ist nicht größer als 60 kB. Die Dokumentation ist zwar recht knapp, aber dank Beispiele findet man sich schnell zurecht und auch die API Beschreibung ist vollkommen ausreichend.</p>
<p>Will man einen eigenen Server starten, so muss zuerst ein neuer Context erzeugt werden:</p>
<pre class="brush: cpp; title: ; notranslate">
struct mg_context* ctx;
ctx = mg_start();
</pre>
<p>Mit <em>mg_set_options</em>, werden die Servereinstellungen geändert. Folgende zwei Zeilen deaktivieren das Directory Listing und setzten 8080 als Port.</p>
<pre class="brush: cpp; title: ; notranslate">
mg_set_option(ctx, &quot;dir_list&quot;, &quot;no&quot;);
mg_set_option(ctx, &quot;ports&quot;, &quot;8080&quot;);
</pre>
<p>Aus Sicherheitsgründen erlaube ich nur einen Zugriff vom selben Rechner aus, also erlaube nur die IP Adresse 127.0.0.1:</p>
<pre class="brush: cpp; title: ; notranslate">
mg_set_option(ctx, &quot;acl&quot;, &quot;-0.0.0.0,+127.0.0.1&quot;);
</pre>
<p>Mit <em>mg_set_uri_callback</em> kann ein Pointer auf eine eigene Funktion an eine URL gebunden werden. Diese wird aufgerufen, wenn der Client die URL aufruft, wobei die URL auch Wildcards enthalten kann.</p>
<pre class="brush: cpp; title: ; notranslate">
mg_set_uri_callback(ctx, 'dosomething', &amp;Server::dosomething, NULL);
</pre>
<p>Als dritter Parameter darf ein Pointer (<em>void*</em>) auf ein beliebiges Objekt übergeben werden. Die Callback Methode bekommt dazu alle notwendigen Parameter, wie die aktuelle Verbindung, den aktuellen Request und das zuvor übergebene Objekt (hier <em>NULL</em>) übergeben.</p>
<pre class="brush: cpp; title: ; notranslate">
void Server::capture(struct mg_connection *conn,
 const struct mg_request_info *request_info,
 void *user_data) {
char* param = mg_get_var(conn, &quot;param&quot;);
mg_printf(conn, &quot;%s&quot;, &quot;HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n&quot;);
}
</pre>
<p>Mit <em>mg_printf</em> kann dann eine Antwort an den Client gesendet werden. Hier als einfaches Beispiel einfach nur ein OK (HTTP 200). In meinem Szenario wird hier der generierte JSON Text zurück gegeben. Mit mg_get_var können übergebene Parameter (POST, GET) ausgelesen werden. Wichtig: um memory leaks zu vermeiden, müssen diese mit <em>mg_free</em> wieder freigegeben werden.</p>
<p>Natürlich ist das nur die eine Hälfte. PHP muss jetzt auch Funktionen, auf dem Server, aufrufen können. Dazu kommt der Zend_Http_Client zum Einsatz. Dieser ist im Zend Framework enthalten, mit etwas Frickelei kann er aber auch aus dem Gesamtpaket heraus gepickt werden. Da ich aber das Zend Framework für die ganze Anwendung nutze, ist das Aufrufen der URL und das Decodieren des JSON Strings in einen Action Helper ausgelagert, der gleichzeitig eine einfache Fehlerbehandlung durchführt:</p>
<pre class="brush: php; title: ; notranslate">
class JsonHttpHelper extends Zend_Controller_Action_Helper_Abstract {
   public function get($url, $params = array()) {
      try {
         $client = new Zend_Http_Client($url);
         foreach($params as $param=&gt;$value)
            $client-&gt;setParameterPost($param, $value);
            $response = $client-&gt;request('POST');
            $res = Zend_Json::decode($response-&gt;getBody());
            if($response-&gt;isSuccessful()) {
               return $res;
            } else {
               return array(&quot;error&quot; =&gt; &quot;request not successfully: &quot;.$res[&quot;error&quot;]);
            }
      } catch(Exception $e) {
         return array(&quot;error&quot; =&gt; $e-&gt;getMessage());
      }
 }
}
</pre>
<p>Bisher bin ich mit der Lösung sehr zufrieden. Besonders mongoose kann ich nur wärmstens empfehlen. Auch von der Verarbeitungsgeschwindigkeit ist das Ergebnis zufriedenstellend und kann sich sehen lassen. Um den Rahmen nicht zu sprengen, habe ich die serverseitige Generierung und Verarbeitung von JSON außen vor gelassen. Hier gibt es aber auch zahlreiche Bibliotheken, so dass die Suche nicht schwer fallen dürfte.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.aditu.de/2010/05/15/serverbridge-zwischen-php-und-cc/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

