CakePHP: Monatsnamen auf Deutsch

Leider funktioniert die Angabe von

setlocale(LC_TIME,"de_DE"); #oder
setlocale(LC_TIME,"deu"); #oder
setlocale(LC_TIME,"ge");

in der ‘bootstrap.php’ nicht, um deutsche Monatsnamen in Formularfeldern mit Datumsangaben zu erhalten.
Daher der Umweg über die Lokalisierungsdatei:

Verzeichnis “deu” im Ordner “app/locale” anlegen.
Verzeichnis “LC_MESSAGES” im grade erstellen “deu” Ordner anlegen.
Datei “default.po” in diesem Ordner anlegen.

In die ‘default.po’ nun die Übersetzungen in der Form

msgid "January"
msgstr "Januar"

msgid "February"
msgstr "Februar"

...

schreiben. Fertig!

CakePHP: Plugins mit AuthComponent schützen oder ‘Wie erstelle ich ein Plugin, welches ebenfalls den UsersController der Hauptanwendung nutzt?’

Normalerweise wird durch die ‘loginAction‘-Variable der AuthComponent die Action definiert, die bei dem Versuch eine geschützte Seite aufzurufen, angezeigt werden soll.

Wenn ein Plugin in eine CakePHP-Anwendung eingebunden und ebenfalls durch die AuthComponent geschützt werden soll, dann wird der Nutzer auf eine Seite in der Form ‘http://www.domain.de/plugin_name/users/login‘ weitergeleitet. Ist letztendlich auch logisch, denn CakePHP geht davon aus, dass der UsersController Teil des Plugins ist.

Um dies zu umgehen und den “richtigen” UsersController der Hauptanwendung aufzurufen, muss der ‘loginAction‘ der AuthComponent eine weitere Variable, nämlich ‘plugin‘, übergeben werden. D.h. normalerweise in der beforeFilter()-Methode des UsersController oder des AppController muss der Aufruf folgendermaßen lauten:

 $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login', 'plugin' => null);

Anschließend nutzt CakePHP den UserController als globalen UserController.

PS: Eine ähnliche Problematik tritt bei

$html->link();

usw. auf. Auch hier muss der Parameter ‘plugin‘ übergeben werden.

YAML, CakePHP und die IE-Kommentare

Das YAML-Framework ermöglicht browserübergreifendes CSS Layout. Die entsprechenden IE Einschränkungen werden, wie so üblich, mit Kommentaren und Bedingungen realisiert. Zu beachten ist, dass die HTML-Kommentare der korrekten HTML-Konvention entsprechen, da sonst Fehler auftreten, wie z.B.

  • Anzeige von <!–[endif]–> im Browserfenster (geringeres Problem)
  • Javascript-Fehler bei CakePHP in Verbindung mit den AJAX-Helpern, Scriptaculous und Protoype. (größeres Problem)

Also immer schön an die Webstandards halten ;-)

CakePHP: Soziales Netzwerk aufbauen

Wer plant mit CakePHP eine soziale Netzwerkfunktion zu implementieren, muss ein paar kleine Tricks beachten.
Wir gehen davon aus, dass eine “users”-Tabelle existiert, in der alle Nutzer gespeichert sind. Nun legen wir eine Tabelle an, die sich “users_users” nennt mit den Spalten “id”, “user_id”, “friend_id” und weiteren die Relation beschreibenen Spalten, bpsw. “approved”.

Im Model “user” muss nun die HABTM-Relation eingetragen werden:

var $hasAndBelongsToMany = array(
        'Friend' => array (
            'className' => 'User',
            'join_table' => 'users_users',
            'foreignKey' => 'user_id',
            'associationForeignKey' => 'friend_id'
        )
    );

Im Controller “users_controller” muss in der entsprechenden Methode die durch ein Formular übergebenen Daten mittels des folgenden Befehls speichern:

$this->User->UsersUser->save($this->data);

Dafür müssen natürlich die Daten in $this->data in der richtigen Form vorliegen, so dass das Formular richtig gestaltet sein muss. Wichtig ist, dass bei der Formularerzeugung auf Bezug auf “UsersUser” genommen wird, so dass das Array in $this->data auch data['UsersUser'][..] enthält:

echo $form->create('UsersUser', array('url' => array('controller' => 'Users', 'action' => 'tippgemeinschaft')));

Über die Option “url” übergibt man noch den richtigen Controller, da sonst CakePHP versuchen würde, den Controller “users_users_controller” zu laden.

CakePHP: Datumsformatierung

Um das abgespeicherte “datetime”-Feld bspw. bei einer User-Tabelle in einer View in das deutsche Format zu bringen, genügt die folgende Zeile (vorausgesetzt, das “data”-Array ist entsprechend vorhanden:


echo date('d.m.Y',strtotime($this->data['User']['created']));

CakePHP: $this->Auth->allow() für Statische Seiten

Statische Seiten in CakePHP werden über den Pages_Controller eingebunden. Möchte man diese frei zugänglich machen (d.h. auch erreichbar, obwohl die Auth-Komponente im Einsatz ist), dann muss der Auth-Variablen “allow” die “display”-Action des Pages_Controller übergeben werden.

$this->Auth->allow('display');

CakePHP: find() mit SUM und WHERE conditions

Bin aus dem CakePHP-Kochbuch nicht ganz schlau geworden, deswegen musste ich es selbst ausprobieren. Hier also der Code, wenn man bestimmte Spalten aufaddieren möchte (SUM) und gleichzeitig eine Bedingung stellt:

$conditions = array('user_id =" => $user_id);
$this->find('first',array('conditions' => $conditions, 'fields'=>array('Model.feld','SUM(Model.feld) as NeuesFeld')))); 

CakePHP: “The requested address … was not found on this server”

Ich hatte das Problem, dass plötzlich diese Aussage von CakePHP kam und ich zuerst nicht wußte, woran es lag. Lustigerweise trat das Problem an ganz unterschiedlichen Stellen auf. Hier sind Lösungsmöglichkeiten:

  • Datenbankverbindung überprüfen
  • Cache leeren (app->tmp->cache)
  • View erstellen

Vor Allem bei dem letzten Punkt trat bei mir starke Verwunderung auf, da normalerweise ein “MissingView”-Error geworfen wird. Bei mir fehlte tatsächlich die View für die aufgerufene Action. Danach lief CakePHP wieder einwandfrei.

Der im Titel genannte Error tritt auf, wenn der Debugmodus auf 0 gestellt ist – also im Produktivbetrieb. Im Entwicklungsbetrieb erscheint der “MissingView”-Error.

CakePHP: AJAX inplaceeditor

Nutzt man die AJAX-Komponente des CakePHP-Frameworks, dann wird man unweigerlich (vermutlich) auch einmal in den Genuß kommen wollen, den inplaceeditor auszuprobieren:

echo $ajax->editor('DOM_id',$action,$options);

wobei $actions und $options jeweils ein Array mit den entsprechenden Schlüssel/Wert-Paaren sind.

Im $actions-Array wird auch die Methode des Controllers festgelegt, die bei per ansychronem Aufruf ausgeführt werden soll. In dem Controller, stehen dann die veränderten Werte in dem “params”-Array zur Verfügung:

$this->params['forms']['value'] # enthält den veränderten Wert des AJAX inplaceeditors

CakePHP: Bestimmte Tabellenfelder auslesen

Nichts wildes, im Kochbuch von CakePHP auch leicht zu finden, dennoch hin und wieder gern gebraucht: Mittels find()-Methode des Models nur bestimmte Tabellenfelder aus der Datenbank holen. Simpel:

$this->Model->find('all', array('fields' => array('Model.feldname'), 'recursive' => -1));

Das “recursive => -1″ sorgt dafür, dass eventuelle Datenmodellabhängigkeiten nicht berücksichtigt werden.

CakePHP Console unter Max OS X einrichten

Ähnlich wie in Windows muss die Console von CakePHP in den PATH mit aufgenommen werden. Dazu

1. Terminal öffnen

2. die Datei “.profile” bspw. mit nano öffnen: “nano .profile”

3. die Zeile “export PATH=$PATH:/Applications/MAMP/htdocs/cakekphp/cake/console” eingeben (wobei der Pfad natürlich von der jeweiligen Installation von CakekPHP abhängt)

4. Datei speichern mit CRTL + O

5. nano beenden mit CRTL + X

6. neue Session im Terminal starten: Entweder Terminal beenden und neustarten oder “. ./.profile” eingeben.

7. “cake” eingeben und schauen, ob der CakePHP Gruß auf der Konsole erscheint.

Vorher sollte man noch überprüfen ob PHP ebenfalls im PATH bekannt ist. Dies kann man über den Befehl “php -v” ganz einfach testen.

CakePHP: Datenbank Konfiguration

Um einfach zwischen lokaler Entwicklungsumgebung und einer Produktivumgebung wechseln zu können, kann in der Konstruktor-Methode der Klasse DATABASE_CONFIG ein einfaches if-Statement helfen. Eine kurze Beschreibung inklusive Beispiel gibt es in der Bakery von CakePHP.

Bei Mac OS X wird (anscheinend) schon IPv6 verwendet, so dass localhost nicht unter “127.0.0.1” zu erreichen ist, sondern unter “::1“. Dies sollte man bedenken, falls man die oben vorgestellte Lösung übernehmen möchte.

CakePHP: Fieldset in Formularen

Mit der “inputs()”-Methode (man beachte das “s”) können gleich mehrere Formularfelder erstellt werden. Mit der üblichen Schreibweise kann dann auch ein “legend”-Tag erstellt werden:

echo $form->inputs(array('legend' => 'Login', 'username', 'password'));

CakePHP: Überprüfung, ob ein User eingeloggt ist…

Um beispielsweise den “Login”-Link in einen “Logout”-Link wechseln zu lassen, sobald der Nutzer eingeloggt ist, braucht man von der Auth-Komponente irgendeine Rückmeldung über den Status. Eine Methode existiert dafür per se nicht. Die Methode

Auth->user()

ist jedoch eigentlich eine Wrapper-Methode für die Session

Auth.User

Daher kann man den Weg über die Session gehen und in Controllern mit der Session-Component und den Views (und damit auch im Layout – falls notwendig) mit dem Session-Helper arbeiten:

In Controllern sieht die Überprüfung daher folgendermaßen aus. Ist der Nutzer eingeloggt, liefert die Methode true

$this->Session->check('Auth.User.id');

In Views muss es so gehandhabt werden:

$session->check('Auth.User.id');

Aktuelle URL mit CakePHP auslesen

Die aktuelle URL kann man in CakePHP über mindestens zwei Wege bekommen.

1. Mit Hilfe der Router-Klasse:

Router::url("", false);

Der zweite boolsche Parameter gibt an, ob die URL relative (false) oder absolut (true) zurückgeliefert werden soll.

2. In den Views kann mittels

$this->params;

auf ein Array zurückgegriffen werden, welches ebenfalls Angaben über die URI enthält, hier beispielsweise dargestellt:

array(8) {
["pass"]=>  array(1) {[0]=>  string(7) "anfahrt" }
["named"]=>  array(0) { }
["plugin"]=>  NULL
["controller"]=>  string(5) "pages"
["action"]=>  &string(7) "display"
["form"]=>  array(0) { } 
["url"]=>  array(1) { ["url"]=>  string(13) "pages/anfahrt" }
["models"]=>  array(0) { } 
} 

Der Pages_Controller

Mit Hilfe des im Core enthalten Pages_Controller ist es möglich, die verschiedenen Helper auch für die statischen Seiten in der Anwendung einzubinden.

Wichtig ist, dass keine Änderungen im Core vorgenommen werden sollten, so dass man CakePHP auch weiterhin updaten kann.

Also einfach den Pages_Controller aus cake/libs/controller kopieren und in app/controller einfügen. Wenn CakePHP den Pages_Controller dort findet, wird auf diesen zurückgegriffen.

Nun kann man hier z.B. standardmäßig den Javascript und Ajax Helper einbinden.

/**
 * Default helper
 *
 * @var array
 * @access public
 */
	var $helpers = array('Html', 'Javascript', 'Ajax');

CakePHP wird Lithium?

Bestimmt nicht, aber der Chefentwickler von CakePHP hat sich von CakePHP getrennt und ein eigenes neues Rapid Developement Framework gestartet: Lithium. Lithium wird für PHP 5.3 entwickelt, befindet sich zur Zeit auch noch wirklich in der Entwicklungsphase. Ein kurzer (englischer) Artikel schreibt etwas mehr über Lithium. Die Lithium Projekt-Seite gibt es hier zu finden.