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.

Jan
27

Wer hat denn den Datensatz erzeugt oder geändert

CakePHP hat ja eine sehr praktischen Automatismus und speichert in die Datenbankfelder created und modified entsprechend das aktuelle Datum ab, wenn die Felder vorhanden und NULL sind. Modified wird bei jedem Update automatisch neu gesetzt. Das klappt bei jedem Model::save(), aber nicht bei Model::updateAll() hab ich übrigens festgestellt, da bei updateAll() intern SQL-Queries erzeugt werden in der Form:

1
  UPDATE modelname SET feld1 = 12 WHERE feld2 = Wert

Wäre es nicht praktisch, wenn man unterschiedliche Benutzer hat, dass auch die Information, welcher Benutzer den Datensatz erzeugt bzw. geändert hat, gespeichert wäre.
Die AuthComponent stellt ja in CakePHP eine recht handliche Möglichkeit bereit den Zugang zu einer Anwendung zu regeln. Dabei hat man dann eine Tabelle mit den Usern die unter anderem eben auch die UserId enthält.
Auth ist auch so nett und speichert in der aktuellen Session die Informationen über den eingeloggten Benutzer. Allerdings kommt man nicht so leicht an diese Informationen, wenn man versucht im Model::beforeSave() den Benutzer in den Datensatz einzutragen.

1
2
3
4
5
6
7
8
9
10
CREATE TABLE articles (
  id int UNSIGNED NOT NULL AUTO_INCREMENT,
  title varchar(255) NOT NULL,
  article varchar(255) NOT NULL,
  created datetime,
  creator_id int UNSIGNED,   # soll über LoadsysAuth gesetzt werden
  modified datetime,
  modifier_id int UNSIGNED,   # soll über LoadsysAuth gesetzt werden
  PRIMARY KEY(id)
);

Vor einiger Zeit habe ich die LoadsysAuth Komponente gefunden, die genau an dieser Stelle hilft. Denn sie kann im Model auf die Session-Informationen zugreifen und den Benutzer im Datensatz eintragen.
Das sieht dann in etwa so aus wenn man es gleich in das beforeSave() im app_model.php einträgt, kann man seine Tabelle um die Felder creator_id und modifier_id erweitern und im beforeSave() werden die Werte dann von der LoadsysAuth gesetzt.

1
2
3
4
5
6
7
8
9
10
11
12
class AppModel extends Model {
        function beforeSave() {
                $exists = $this->exists();
                if ( !$exists && $this->hasField('creator_id') && empty($this->data[$this->alias]['creator_id']) ) {
                        $this->data[$this->alias]['creator_id'] = LoadsysAuth::getUserId();
                }
                if ( $this->hasField('modifier_id') && empty($this->data[$this->alias]['modifier_id']) ) {
                        $this->data[$this->alias]['modifier_id'] = LoadsysAuth::getUserId();
                }
                return true;
        }
}

Wenn man die LoadsysAuth Komponente einsetzt, dann sollte man allerdings darauf achten, dass sämtlich Auth Aufrufe durch LoadsysAuth ersetzt werden. Die Komponente ist nämlich direkt von der Auth Komponente abgeleitet und stellt alle Funktionen von Auth zur Verfügung. Zusätzlich kann man allerdings mit Funktionen wie

1
2
LoadsysAuth::getUser(); // liefert den kompletten User Datensatz
LoadsysAuth::getUserId(); // liefert nur die Id des Users

auch im Model auf die entsprechenden Benutzerdaten zugreifen. Bei meinem letzten Projekt hat mir das enorm geholfen und einiges an extra Arbeit erspart. Dabei sind die Funktionen in LoadsysAuth als static-Funktionen implementiert und können recht einfach erweitert bzw. angepasst werden.

Hier gehts zur LoadsysAuth Komponente, wo sie auch heruntergeladen werden kann.

Oben