Feb
10

RFC822-Datum im Model formatieren

In CakePHP gibts ja den TimeHelper der für alle Gelegenheiten die richtige Funktion zum Verarbeiten von Datums hat. Da ich gerade an einem Shell-Script in Verbindung mit Twitter einiges programmiere und der TimeHelper in Model nicht zur Verfügung steht, habe ich mir einfach mal eine Funktion fromString herausgezogen, mit der man die notwendigen Wandlungen recht schnell machen kann:

    function fromString($dateString, $utcOffset = 0)
    {
        $date = strtotime($dateString);
        if ($utcOffset !== 0) {
            $serverOffset = date('Z',  time());
            $gmtTime = $date - $serverOffset;
            $userTime = $gmtTime + $utcOffset * (60*60);
            return $userTime;
        }
        return $date;
    }

Das meiste ist vom TimeHelper geborgt und kann im Model als Funktion hinterlegt werden. Damit lässt sich dann ziemlich einfach ein RFC822 Datum in ein Datenbankfeld einfügen. Als in einer entsprechenden Model-Funktion sieht das dann beispielsweise so aus:

function saveit($tweet) {
...
$data['Tweet']['tweet_created_at'] = date('Y-m-d H:i:s',  $this->fromString($tweet->created_at, $utc_offset));
...
}

Falls das Ganze noch jemand brauchen kann, einfach zugreifen.

Feb
05

Timeline Helper in der Bakery erschienen

Die Timeline Javascript Bibliothek hatte ich selbst bei einem Projekt in Verbindung mit CakePHP eingesetzt für die Veranschaulichung von Terminen auf einer verschiebbaren Zeitachse. Hier der Link auf die Beispiele von Timeline, die teilweise sehr anschaulich sind.

Selbst hatte ich mir damals nicht die Mühe gemacht einen Helper zu schreiben, aber dafür gibts jetzt in der Bakery einen Timeline-Helper. Hab ich zwar noch nicht ausprobiert, sieht aber ganz ansprechend aus, so weit ich mal kurz drauf geschaut habe. Wer also Temine, Zeitbereiche und ähnliches anschaulich und interaktiv anzeigen will, sollte mal einen Blick auf den Helper werfen.

Feb
04

VCard oder RSS-Feed ?

Cake bietet mit seiner Router-Funktionalität die Chance ganz einfach neue Ausgabeformate zu definieren. Dem Router erklärt man erstmal mit

    Router::parseExtensions('rss', 'vcf');

auf welche Extensions er reagieren soll. RSS gehört dabei in Cake zu den Standardextensions, die über den RSS-Helper selbständig erzeugt werden kann. D.h. also, wenn

    http://meine.domain.de/products/index

einfach die Extension .rss an die Url angehängt wird

    http://meine.domain.de/products/index.rss

dann erkennt der Router die Erweiterung RSS in der URL und holt sich den RSS-View zur Ausgabe der Daten im RSS-Format. Normale Views finden sich in APP/views/products bezogen auf das obige Beispiel. Um nun die RSS-Ausgabe zu formatieren, erzeugt man einen zusätzlichen Unterordner APP/views/products/rss und legt dort für jeden gewünschten View, der als RSS-Feed erzeugt werden soll, eine entsprechende Datei. Also beispielsweise APP/views/products/rss/index.ctp und erzeugt mit Hilfe des RSS-Helpers die gewünschte Ausgabe.

Will man also auf die gleiche Weise statt einem RSS-Feed nun eine VCard von einem Kontakt erzeugen, dann geht man entsprechend vor. Zusätzlich benötigt man aber ein Layout für VCF-Dateien das man in APP/views/layouts/vcf/default.ctp anlegen muss. Dort hinterlegt man für die VCard die notwendigen Ausgaben, um das Format über den Browser auch richtig ausliefern zu können:

    Configure::write('debug', 0); // nur nötig, falls man im Debug-Mode arbeitet und trotzdem die Ausgaben testen will
    header(
        'Content-Type: application/directory; ' .
        'profile="vcard"; ' .
        'charset=' . $charset
    );
    header('Content-Length: ' . strlen($content_for_layout));
    header("Content-Disposition: $disposition; filename=\"$filename\"");
    echo $content_for_layout;
Jan
29

HtmlHelper und die Ausgabeformatierung

Der HtmlHelper gehört für die Ausgabeformatierung zu den Standardwerkzeugen in CakePHP, da der Links erzeugen, Bilder ausgeben und noch viel mehr kann.

Meist schreib ich inzwischen auch normalen HTML-Code mit Hilfe des Helpers, da ich mir dann keine Gedanken mehr über die Formatierung machen muss.

1
2
     $html->tag('h2', __('Meine Überschrift', true));
     $html->para('grosseSchrift', __('die Erklärung zu dem Kapitel', true));

liefert dann schon

   <h2>Meine Überschrift</h2>
   <p class="grosseSchrift">die Erklärung zu dem Kapitel</p>

Dabei nutzt der HtmlHelper intern eine Feld mit Tags, die im Quelltext vom HtmlHelper ganz am Anfang definiert werden. Die Tags kann man für eigene Zwecke auch ganz einfach anpassen.

1
     $html->tags['link'] = "<a rel="nofollow" href="%s"%s>%s</a>";

Damit werden dann Links erzeugt, die immer rel=”nofollow” enthalten, wenn man das für seine Zwecke braucht. Oder man man auch ein Neue Zeile “\n” anhängt, damit man lesbarere Quelltexte erhält ;)

Um einen Bild und eine Url getrennt mit Links zu versehen kann das dann beispielsweise so aussehen:

1
2
3
       $txt = $this->Html->link(
                 $this->Html->image($image), $link, array('class'=>'img'), false, false) . " " .
                 $this->Html->link($title, $link);

Übrigens sind jetzt in der neuen API-Dokumentation auch die Parameter und Methoden alphabetisch aufgelistet, was das Ganze noch viel benutzbarer macht. Jetzt müssen eigentlich nur noch die Funktionen direkt über die Suche zu finden sein.

Jan
26

FileUploader in CakePHP für Bilder

FileUploader sind ja die Teile mit denen man in Web2.0 und auch sonstigen Anwendungen Bilder und ähnliches hochlädt. Vorgestern hab ich mich noch mit Sebastian drüber unterhalten und er meinte, er nutzt den phpThumb Helper aus der Bakery, weil der die Bilder einfach cached. Sprich, wenn ein neues Format gebraucht wird, dann wird über die phpThumb Bibliothek das neue Bild erzeugt und im Cache zwischengespeichert.

Der Aufruf sieht damit im View eigentlich ziemlich lässig aus:

1
     $thumbnail->show($options, $tag_options);

Allerdings muss man sich dazu noch selber merken, welche Bilder vorhanden sind und wie die heißen, sprich doch ein Model bemühen oder entsprechendes.

Selber benutze ich in meiner aktuellen Anwendung das image-Behavior, das einen komplett anderen Ansatz geht.
Als Behavior wird es im Model mit $actsAs aufgesetzt und erhält die notwendigen Parameter. D.h. im Falle des Image-Behaviors wird über den Parameter fields das Attribut in der Datenbanktabelle festgestellt - hier avatar - und dann werden die Parameter eingestellt für die unterschiedlichen Thumbnails, die das Behavior beim Speichern des Datensatzes generieren soll.

1
2
3
4
5
6
7
8
9
10
    var $actsAs = array(
        'Image'=>array(
		'fields'=>array(
			'avatar'=>array(
				'thumbnail'=>array('create'=>true),
				'resize'=>array('width'=>'55', 'height'=>'55','aspect'=>true),
				'versions'=>array(
					array('prefix'=>'s','width'=>'32','height'=>'32','aspect'=>true),
					array('prefix'=>'16','width'=>'16','height'=>'16','aspect'=>true)
		)))));

In meinem Fall wird also ein thumbmail erzeugt, eine resize auf 55px Kantenlänge vorgenommen und zusätzlich noch zwei Versionen erzeugt, einmal mit dem Prefix ’s’ und einer Kantenlänge von 32, sowie einem Prefix ‘16′ mit einer entsprechenden Kantenlänge.
In der Datenbank selbst wird nur das Feld avatar gespeichert, das den Dateinamen enthält, den man angibt. Alle anderen Felder werden virtuell erzeugt. Hier ein Beispiel wie der Datensatz nach einem $this->find zurückkommt:

1
2
3
4
5
6
7
            [avatar] => Array
                (
                    [path] => thumbs/Person/812/avatar.skypeavatar.jpeg
                    [thumb] => thumbs/Person/812/thumb_avatar.skypeavatar.jpeg
                    [s] => thumbs/Person/812/s_avatar.skypeavatar.jpeg
                    [16] => thumbs/Person/812/16_avatar.skypeavatar.jpeg
                )

Wie man schön sieht bekommt man also deutlich mehr Informationen über das vom Image-Behavior verarbeitete Bild zurück und kann damit entsprechend weiterarbeiten.

In der Bakery ist gerade ein neuer Beitrag über einen FileUploader schienen. Ist aber leider gerade nicht mehr online, weil er wahrscheinlich zum Editieren/Erweitern vom Autor verändert worden ist und erst neu freigeschaltet werden muss. Sah aber auch ganz interessant aus, weil er insbesondere die Möglichkeit vorgesehen hat, dass man ins Model speichern kann, aber nicht unbedingt muss. Ich werd den Link hier noch setzen, sobald der Artikel in der Bakery wieder zur Verfügung steht.

Welche Helper, Behaviors oder anderen Methoden verwendet ihr denn, um mit hochgeladenen Bildern umzugehen?

Oben