Endlich finde ich mal wieder die Zeit einen kleinen Beitrag für die Kategorie Freaky Friday zu schreiben. Seit nun mehr als zwei Jahren entwickle ich wieder Vergleichsrechner für die vs vergleichen-und-sparen GmbH auf Basis des Zend Framework 2. Das ZF2 ist ein mächtiges PHP Framework, welches Mechanismen bereit stellt, die einem erst nach Jahren der Anwendung in den Schoß fallen. Heute soll es mal um die Hydrierung von Datenmodellen gehen.
Was ist eigentlich Hydrierung?
Von Hydrierung spricht man, wenn ein existentes leeres Objekt mit Daten bestückt wird. In einer rein objektorientierten Programmierung, wie sie mit PHP auch möglich ist, ergibt die Hydrierung von Objekten durchaus Sinn. Vor allem in ORM Systemen wie Doctrine ist die Hydrierung von Objekten integriert, da das automatische Befüllen von Objekten mit Daten im Umgang mit Datenbanken ihren Ursprung hat. Heutzutage ist es durchaus sinnvoll auch außerhalb von Datenbank-bezogenen Systemen mit Hydrierung zu arbeiten. Das Verarbeiten von Formulardaten wäre z.B. ein praktisches Beispiel.
Wie sieht die Hydrierung von Objekten aus?
Im Zend Framework 2 könnte die Hydrierung von Objekten wie im folgenden Codebeispiel aussehen. Stellen wir uns einfach vor, wir haben ein Datenmodell, welches die Daten eines Users darstellt. Dieses Beispiel ist natürlich stark verkürzt, um zu verdeutlichen, was Hydrierung eigentlich bedeutet. Normalerweise haben wir hier auch noch Namen, E-Mail Adressen, etc. pp.
declare(strict_types=1);
namespace Application\Entity;
class User
{
protected $birthday;
public function getBirthday() : DateTime
{
return $this->birthday;
}
public function setBirthday(DateTime $oBirthday) : User
{
$this->birthday = $oBirthday;
return $this;
}
}
Dieses Modell (Entity) hat eine Eigenschaft Birthday, die das Geburtsdatum des Users darstellt. Dazu gibt es die entsprechenden Getter und Setter Methoden, die das Geburtsdatum ausliefern. Sofern man dieses Modell in dieser Form im Zend Framework 2 z.B. beim Auslesen von Daten aus der Datenbank verwendet würde, gerät man sehr schnell in ziemliche Schwierigkeiten. Normalerweise ist ein Datum in der Datenbank als String des Typs Date in Form 1979-12-19 gespeichert. Der Hydrator des Zend Frameworks würde versuchen diesen String als Geburtsdatum zu setzen. Am Ende käme nur ein Fatal Error heraus, weil ein String nunmal kein DateTime Objekt ist. Genau für diesen Fall bietet das ZF2 Hydrator das Strategy Objekt an.
Strategy to the rescue!
Eine Hydrator Strategy ermöglicht es einzelne Werte eines Objektes bei der Hydrierung so zu konvertieren, wie man sie braucht. Natürlich ist es sinnvoll ein Datum, welches nur als Date Format / String in der Datenbank liegt, sofort als DateTime Objekt zu haben, um damit weiter zu arbeiten. Während der Hydrierung kommt die Strategy zum Einsatz und konvertiert einen Wert so, wie man ihn haben möchte. Hierzu mal ein kleines Beispiel zu unserem User Entity.
declare(strict_types=1);
namespace Application\Hydrator\Strategy;
class DateTimeStrategy extends DefaultStrategy
{
public function hydrate($value) : DateTime
{
if (!($value instanceof \DateTime)) {
$value = new \DateTime($value);
}
return $value;
}
}
In diesem Beispiel ist nur die Hydrierung der Strategy implementiert. Eine Strategy kann nämlich auch in die andere Richtung funktionieren und bei der Rückgabe des Wertes aus dem Modell heraus eine Konvertierung durchführen. In diesem Fall konvertieren wir unser Geburtsdatum beim Hydrieren in ein DateTime Objekt, sofern es noch keines sein sollte. Praktisch sieht es dann wie folgt aus:
use Zend\Hydrator\ClassMethods;
use Application\Entity\User;
use Application\Hydrator\Strategy\DateTimeStrategy;
// Daten aus z.B. einem Formular oder einer Datenbank
$aData = [
'name' => 'Marcel',
'birthday' => '1979-12-19',
];
// Hydrierung des User Modells mit einem Hydrator und der Strategy
$oUser = (new ClassMethods())
->addStrategy('birthday', new DateTimeStrategy())
->hydrate($aData, new User())
// Ausgabe des Geburtstages im Format 19.12.1979
echo $oUser->getBirthday()->format('d.m.Y');
Wir haben die Strategy jetzt an den Wert birthday gebunden. Wann auch immer dieser Wert auftritt, kommt die Strategy ins Spiel. Im Daten Array ist lediglich der String „1979-12-19“ vorhanden. In unserem User Modell haben wir dann plötzlich das DateTime Objekt, welches wir haben wollen. Praktisch, oder?
Welchen Sinn macht das?
Ja, man könnte auch direkt im User Modell arbeiten und das Geburtsdatum dort in ein DateTime Objekt umwandeln. Bei der Nutzung des Strategy Objekts bleibt das Modell aber sauber. Wir überladen es nicht mit Programmcode. Die Strategy ist zudem frei nach dem Motto von Seperation of Concerns auch wiederverwendbar. Habe ich also ein anderes Datenmodell mit einem Datumswert, kann ich die gleiche DateTimeStrategy benutzen, wie ich sie für das User Modell genutzt habe. Eine sehr saubere Lösung.
Haben wir wieder was gelernt! Ich wünsche Euch ein schönes Wochenende.
3 Gedanken zu „Freaky Friday: Zend Framework 2 und Hydrierung mit Strategie“