<?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>Blog @ TheNightCoder &#187; Featured</title>
	<atom:link href="http://blog.thenightcoder.de/category/featured/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.thenightcoder.de</link>
	<description>...because things are different at night</description>
	<lastBuildDate>Mon, 26 Sep 2011 15:52:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>CakePHP &#8211; Paginator &#8216;on the fly&#8217; filtern&#8230;</title>
		<link>http://blog.thenightcoder.de/2009/11/cakephp-paginator-on-the-fly-filtern/</link>
		<comments>http://blog.thenightcoder.de/2009/11/cakephp-paginator-on-the-fly-filtern/#comments</comments>
		<pubDate>Sat, 28 Nov 2009 19:39:48 +0000</pubDate>
		<dc:creator>TheNightCoder</dc:creator>
				<category><![CDATA[Allgemeines]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Cake]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Controller]]></category>
		<category><![CDATA[Filter]]></category>
		<category><![CDATA[Filter-Options]]></category>
		<category><![CDATA[Model]]></category>
		<category><![CDATA[Options]]></category>
		<category><![CDATA[paginate]]></category>
		<category><![CDATA[Paginator]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Session]]></category>
		<category><![CDATA[View]]></category>

		<guid isPermaLink="false">http://blog.thenightcoder.de/?p=294</guid>
		<description><![CDATA[Filteroptionen des Paginators 'on the fly' ändern
<br />
In diesem Artikel werde ich zeigen, wie man dem Paginator in Cake z.B. in einem Index-View beibringt, vom Benutzer selbst gewählte Filteroptionen zu übernehmen und zu verwenden!]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.thenightcoder.de%2F2009%2F11%2Fcakephp-paginator-on-the-fly-filtern%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.thenightcoder.de%2F2009%2F11%2Fcakephp-paginator-on-the-fly-filtern%2F&amp;source=TheNightCoder&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Schwierigkeitsgrad: <strong>leicht</strong><br />
zu implementieren in: <strong>Model, View, Controller</strong></p>
<p>Zunächst einmal sei erwähnt, dass es sicher auch andere Möglichkeiten gibt, diese Aufgabe zu lösen, doch ich denke diese Lösung ist einfach nachzuvollziehen und auch einfach selbst zu implementieren. Ihr solltet Euch mit dem Paginator ein wenig auskennen, das MVC Prinzip verstanden haben und ein wenig selber mitdenken können (aber sonst hättet Ihr auch den falschen Job, richtig?)</p>
<p>Fangen wir an mit dem Model, in das ich ein paar einfache Methoden eingebaut habe, um die entsprechenden Filteroptionen zu hinterlegen (sowas kann man selbstverständlich auch im Controller machen&#8230;). Wir gehen davon aus, dass unser zu paginierendes Model <strong>&#8216;Customer&#8217;</strong> heißt.</p>
<p><strong>im Model:</strong></p>
<pre class="brush: php; title: ; notranslate">
    public function getLimits() {
        return array(
            5 =&gt; __('5', true),
            10 =&gt; __('10', true),
            15 =&gt; __('15', true),
            20 =&gt; __('20', true),
            50 =&gt; __('50', true)
        );
    }

    public function getSortBies() {
        return array(
            'lastname' =&gt; __('Lastname', true),
            'firstname' =&gt; __('Firstname', true),
            'office' =&gt; __('Office', true),
            'email' =&gt; __('Email', true)
        );
    }

    public function getOrders() {
        return array(
            'ASC' =&gt; __('Ascending', true),
            'DESC' =&gt; __('Descending', true)
        );
    }
</pre>
<p>Bis hierhin eigentlich noch nichts spannendes. Hier werden lediglich die Arrays definiert, deren Inhalte wir nachher in den DropDowns der Filterliste wiedersehen werden. Wie gesagt, man kann das auch im Controller definieren, aber das würde dem Prinzip von &#8216;Fat Models, Skinny Controllers&#8217; widersprechen, was als Best-Practice bei Cake (und anderen MVC-Frameworks natürlich auch!) gilt&#8230;</p>
<p>Als nächstes nehmen wir uns das View vor, um dem User die entsprechenden Filtermöglichkeiten anzubieten. Hier setzt ihr einfach da wo es euch paßt folgendes ein:</p>
<p><strong>im View:</strong></p>
<pre class="brush: php; title: ; notranslate">
&lt;div class=&quot;filter_container&quot;&gt;
&lt;?php echo $form-&gt;create('Customer', array('action' =&gt; 'index'));?&gt;
	&lt;fieldset&gt;
 		&lt;legend&gt;&lt;?php __('Filter Options');?&gt;&lt;/legend&gt;
	&lt;?php
		echo $form-&gt;input('Customer.limit', array(
            'selected' =&gt; $session-&gt;read('Customer.limit')
        ));
        echo $form-&gt;input('Customer.sortby', array(
            'selected' =&gt; $session-&gt;read('Customer.sortby')
        ));
        echo $form-&gt;input('Customer.order', array(
            'selected' =&gt; $session-&gt;read('Customer.order')
        ));
	?&gt;
	&lt;/fieldset&gt;
&lt;?php echo $form-&gt;end('Submit');?&gt;
&lt;/div&gt;
</pre>
<p>An sich ist auch das hier alles wie immer bei Cake. Auffallend ist hier der zugewiesene &#8217;selected&#8217; Wert, der gesetzt wird sollte für das Model Customer der entsprechende Filterschlüssel bereits in der Session hinterlegt sein. Die Form wird an die index-action gesendet, welche dann die übergebenen Parameter auswertet und den Paginator entsprechend verändern wird. Hierzu gleich mehr im Controller-Teil.</p>
<p>Ich habe mich für den Weg über die Sessions entschieden, da ich kein Freund von unnötigen GET-Parametern bin und die Session für persönliche Einstellungen genutzt werden darf. Wer Lust hat, kann das Ganze auch als Cookie hinterlegen, oder sogar als eine Art permanent-setting in der Datenbank speichern. Der Kreativität sind dabei keine Grenzen gesetzt!</p>
<p>Ist das View erledigt, folgt noch der Controller. Hier werden wir übergebene Werte in die Session schreiben, die Variablen des Paginators zuweisen und dem View unsere im Model hinterlegten Drop-Down Arrays zur Verfügung stellen. Zunächst aber hier einmal des gesamte Code:</p>
<p><strong>im Controller:</strong></p>
<pre class="brush: php; title: ; notranslate">
public function index() {
        if(!empty($this-&gt;data['Customer']['limit'])) {
            $this-&gt;Session-&gt;write('Customer.limit', $this-&gt;data['Customer']['limit']);
        }
        if(!empty($this-&gt;data['Customer']['order'])) {
            $this-&gt;Session-&gt;write('Customer.order', $this-&gt;data['Customer']['order']);
        }
        if(!empty($this-&gt;data['Customer']['sortby'])) {
            $this-&gt;Session-&gt;write('Customer.sortby', $this-&gt;data['Customer']['sortby']);
        }
        $limit = $this-&gt;Session-&gt;read('Customer.limit');
        $order = $this-&gt;Session-&gt;read('Customer.order');
        $sortby = $this-&gt;Session-&gt;read('Customer.sortby');

        if(empty($limit)) {
            $limit = 10;
        }
        if(empty($order)) {
            $order = 'ASC';
        }
        if(empty($sortby)) {
            $sortby = 'lastname';
        }
        $this-&gt;paginate['Customer'] = array(
            'contain' =&gt; false,
            'conditions' =&gt; array(
                'Customer.deleted' =&gt; 0,
            ),
            'limit' =&gt; $limit,
            'order' =&gt; array(
                'Customer.'.$sortby =&gt; $order
            )
        );
        $limits = $this-&gt;Customer-&gt;getLimits();
        $orders = $this-&gt;Customer-&gt;getOrders();
        $sortbies = $this-&gt;Customer-&gt;getSortbies();
        $professors = $this-&gt;paginate('Customer');
        $this-&gt;set(compact('customers', 'limits', 'orders', 'sortbies'));
}
</pre>
<p>Was passiert hier also?<br />
Wir checken ob uns das Filter-Formular Daten gesendet hat, sprich ob der Benutzer Filter eingestellt und dann abgeschickt hat. Wenn es Daten gibt, dann werden sie in die Session geschrieben. Danach werden die Session-Daten wieder ausgelesen, und danach geprüft ob wirklich Daten vorhanden sind. Benutzt man die Action zum ersten Mal nach dem Login, gibt es ja noch keine Daten in der Session, also muss man dafür sorgen, dass Standardwerte übernommen werden. Das geschieht im folgenden Teil.<br />
Danach wird der Paginator customized angelegt. Dieser Weg ist besonders dann von Vorteil, wenn man in einem Controller mehrmals verschiedenen &#8220;verseiten&#8221; muss. Man hat somit einfach eine klarere und bessere Eingriffsmöglichkeit, als wenn man dies am Anfang des Controller über var $paginate tuen würde.</p>
<p>Als letztes werden die Variablen für die DropDowns aus dem Model gelesen, und dem View über $this->set() zur Verfügung gestellt.</p>
<p>Das wars auch schon. Ihr habt jetzt eine Paginierung mit Filtermöglichkeiten, die sich während der gesamten Session speichert und dem Benutzer so eine bessere Möglichkeit der Eingrenzung und Filterung bietet.</p>
<p>Da ich absichtlich das Model mittels Punktnotation in der Session abgelegt habe, kann für jedes Model in jedem Controller und in jeder Action eine eigene Filterung angeboten werden. Ganz coole Leute bringen sowas wahrscheinlich in einer gekapselten Component unter, was ich evtl. in den nächsten Wochen nachholen werde.</p>
<p>Viel Spaß beim PAGINIEREN <img src='http://blog.thenightcoder.de/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<img src="http://blog.thenightcoder.de/?ak_action=api_record_view&id=294&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.thenightcoder.de/2009/11/cakephp-paginator-on-the-fly-filtern/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wushu-Erweiterung erfolgreich deployed&#8230;</title>
		<link>http://blog.thenightcoder.de/2009/10/wushu-erweiterung-erfolgreich-deployed/</link>
		<comments>http://blog.thenightcoder.de/2009/10/wushu-erweiterung-erfolgreich-deployed/#comments</comments>
		<pubDate>Tue, 13 Oct 2009 23:04:27 +0000</pubDate>
		<dc:creator>TheNightCoder</dc:creator>
				<category><![CDATA[Allgemeines]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Barcelona]]></category>
		<category><![CDATA[CMS]]></category>
		<category><![CDATA[Deploy]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projekt]]></category>
		<category><![CDATA[Restaurant]]></category>
		<category><![CDATA[Wushu]]></category>
		<category><![CDATA[Wushu-Restaurant]]></category>

		<guid isPermaLink="false">http://blog.thenightcoder.de/?p=260</guid>
		<description><![CDATA[Das <a href="http://www.wushu-restaurant.com">Wushu-Restaurant in Barcelona</a> und das eigens dafür entworfene CMS hat dieser Tage eine Erweiterung erhalten, mit der sich nun auch Videos zum Thema Cooking Classes usw. in das Frontend einpflegen lassen. ]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.thenightcoder.de%2F2009%2F10%2Fwushu-erweiterung-erfolgreich-deployed%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.thenightcoder.de%2F2009%2F10%2Fwushu-erweiterung-erfolgreich-deployed%2F&amp;source=TheNightCoder&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>&#8230; so nach einer ganzen Weile melde ich mich endlich mal wieder hier zu Wort. Es gab sehr viel zu tun in letzter Zeit, angefangen von einer ganzen Menge Arbeit um die Finanzen wieder in einem etwas helleren Licht erstrahlen zu lassen, andererseits aber auch die Prüfungsphase Ende September, in der ich mich mit Signaltheorie, Mathematik und Algorithmen &#038; Datenstrukturen beschäftigt habe. Auf die Ergebnisse werde ich wohl noch etwas warten müssen, aber nun kann ich denke ich mit Recht behaupten es geht in die letzte Phase des Studiums. Es sind nicht mehr viele Prüfungen übrig, und auch diese werde ich in den kommenden Monaten bestehen. </p>
<p>Nun zurück zu <strong>Wushu&#8230;</strong><br />
Ich habe zwar den Hauptartikel (zum Hauptsystem) der <a href="http://www.wushu-restaurant.com">Wushu-Restaurant-Website</a> immernoch nicht verfaßt, dennoch wollte ich hier kurz zumindest die aktuelle Erweiterung ansprechen. Wie immer kam der Auftrag von <a href="http://www.digital-cube.de">Digital Cube</a> und es war wie immer angenehm und erfolgreich was die Zusammenarbeit betrifft. Neben der bekannten (jaja, Artikel folgt&#8230; ;( ) Funktionalität bekam das beliebte Restaurant mit Sitz in Barcelona nun die Möglichkeit, über das von uns entwickelte individuelle Content Management System sog. &#8220;Cooking Classes&#8221; hinzuzufügen. Dies bedeutet, dass<br />
das Restaurant eigene Videos, welche auf der Website mit dem sog. &#8220;Slideshow-Pro&#8221;-Plugin dargestellt werden, einfügen kann nebst eines selbst angelegten Textes, z.B. ein Rezept. Zusätzlich wurde ein einfaches Kategoriesystem eingebaut, welches es ermöglicht die Rezepte zu verschiedenen Themengebieten zusammen zu fassen. </p>
<p>Die Erweiterung wurde nahtlos in das bestehende Backend eingefügt und ebenso wie die anderen Inhalte werden dauch die neuen Artikel in 3 Sprachen gleichzeitig gespeichert. Inhalte können hinzugefügt, editiert und gelöscht werden, und auch der Status kann von online auf offline geschaltet werden um einen Eintrag kurzfristig aus dem Frontend zu entfernen, ohne ihn gleichzeitig komplett aus der Datenbank löschen zu müssen.</p>
<p>Alles in allem eine runde Sache, wobei auch die Geschwindigkeit des Backends durchaus zu überzeugen weiß. Hier gibt es im Grunde keine erkennbaren Ladezeiten, was die Leute bei Wushu freuen dürfte. Und für einen Entwickler gibt es kaum etwas schlimmeres als ewig lange Ladezeiten <img src='http://blog.thenightcoder.de/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  !</p>
<p>Ich wünsche dem Wushu-Team daher weiterhin viel Erfolg und Spaß mit den neuen Komponenten!</p>
<img src="http://blog.thenightcoder.de/?ak_action=api_record_view&id=260&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.thenightcoder.de/2009/10/wushu-erweiterung-erfolgreich-deployed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cake: Wenn der Absender von Emails falsch angezeigt wird&#8230;</title>
		<link>http://blog.thenightcoder.de/2009/07/cake-gets-messed-up-when-sending-emails/</link>
		<comments>http://blog.thenightcoder.de/2009/07/cake-gets-messed-up-when-sending-emails/#comments</comments>
		<pubDate>Wed, 08 Jul 2009 00:41:27 +0000</pubDate>
		<dc:creator>TheNightCoder</dc:creator>
				<category><![CDATA[Allgemeines]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Cake]]></category>
		<category><![CDATA[CakePHP]]></category>
		<category><![CDATA[Email]]></category>
		<category><![CDATA[Email Component]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[send]]></category>

		<guid isPermaLink="false">http://blog.thenightcoder.de/?p=121</guid>
		<description><![CDATA[
			
				
			
		
Durch einen Zufall entdeckte ich heute eine komische Eigenart von Email-Servern und/oder Clients, wenn es um den Absender einer Email geht. Angenommen wir möchten als Absender nicht die Email-Adresse alleine, sondern einen netten Text erscheinen lassen, dann reicht es dummerweise nicht, folgendes zu tun:

$this->Email->from = "Netter Text";

sondern man MUSS zwingend ...]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.thenightcoder.de%2F2009%2F07%2Fcake-gets-messed-up-when-sending-emails%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.thenightcoder.de%2F2009%2F07%2Fcake-gets-messed-up-when-sending-emails%2F&amp;source=TheNightCoder&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Durch einen Zufall entdeckte ich heute eine komische Eigenart von Email-Servern und/oder Clients, wenn es um den Absender einer Email geht. Angenommen wir möchten als Absender nicht die Email-Adresse alleine, sondern einen netten Text erscheinen lassen, dann reicht es dummerweise nicht, folgendes zu tun:</p>
<p><code><br />
$this->Email->from = "Netter Text";<br />
</code></p>
<p>sondern man MUSS zwingend noch eine Emailadresse angeben, und zwar in dieser Form:</p>
<p><code><br />
$this->Email->from = "Netter Text &lt;email@mail.com&gt;";<br />
</code></p>
<p>Klingt komisch, ist aber so!</p>
<img src="http://blog.thenightcoder.de/?ak_action=api_record_view&id=121&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://blog.thenightcoder.de/2009/07/cake-gets-messed-up-when-sending-emails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

