CakePHP: lastlogin eines Nutzers speichern

Um den letzten erfolgreichen Login eines Nutzers in einem Feld ‘lastlogin‘ zu speichern, muss in der login()-Methode des UsersController folgender Code eingefügt werden:

if ($this->Auth->user()) { 
 $this->User->id = $this->Auth->user('id'); 
 $this->User->saveField('lastlogin', date("Y-m-d H:i:s")); 
 $this->redirect('/controller/action'); 
}

Damit das ganze auch aufgerufen wird, muss im app_controller noch das autoRedirect ausgestellt werden. Dies erklärt auch die redirect()-Methode in der oben dargestellten login()-Methode.

Im app_controller muss also noch folgendes stehen (oder im beforeFilter() des UsersController)

$this->Auth->autoRedirect = false;

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.

Autovervollständigung mit Eclipse PDT

Die Entwicklungsumgebung Eclipse PDT (für PHP) bietet eine Autovervollständigung während des Programmierens an. Standardmäßig (zumindest bei der Mac-Version) ist die automatische Vervollständigung nicht eingeschaltet, sondern der Programmierer muss “Strg+Leertaste” drücken, um die möglichen Variablen angezeigt zu bekommen.

Da das mitunter lästig ist, kann man auch die vollautomatische Vervollständigung einstellen. Einfach unter “Einstellungen => PHP => Editor => Code Assist” den Haken bei “Enable auto activation” setzen. Optional kann noch die Zeitverzögerung eingestellt werden.

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');

Scriptaculous Effekte – und dann kein Javascript aktiviert…

Webseiten sollten – wenn möglich – für alle Nutzer zugänglich sein: Stichwort Barrierefreiheit. Es gibt Richtlinien für Webentwickler für die Barrierefreiheit, die in einer deutschen Übersetzung beim W3C zu finden sind.

Ein wichtiger Punkt ist natürlich, dass auch Inhalt der Webseite erreichbar sind, wenn z.B. Javascript nicht vom Browser unterstützt oder gar deaktiviert ist. Was also tun, wenn man (aus Design- und eventuell auch Übersichtlichkeitsgründen) scriptaculous-Effekte einsetzt?

Die Antwort ist – wie meistens so oft – ganz simpel:

Aufsliden...

Anstatt eines einfachen Ankers (#) den wirklichen Link im <a>-Tag angeben. Wenn Javascript aktiviert ist, wird der EventHandler “onclick” genutzt, sonst wird das angegebene “href” Attribut als Link verfolgt.