PHP und das Datetime Problem

Alle modernen PHP-Frameworks setzen bei der Verarbeitung von Datums- und Uhrzeitangaben auf die Klasse Datetime, welche PHP von haus aus mitbringt. Die Klasse ist praktisch, kapselt sie doch alle Funktionen die man für das Arbeiten mit einem Datum braucht an einer Stelle.

Sie hat aber bei der Nutzung in Frameworks bzw. deren ORM einen entscheidenden Nachteil. Ihr fehlt die magische __toString() Methode, welche dafür sorgt das sich ein Objekt der Klasse in den Datentyp string konvertieren lässt.

Datetime in Doctrine

So ist es in Doctrine2 beispielsweise bisher nicht möglich, Spalten eines Datums- oder Uhrzeittyps als Teil des Primärschlüssels zu verwenden. Dieser wird zur internen Identifizierung aus einer Verkettung der jeweiligen String-Entsprechung der beteiligten Spalten gebildet. Das funktioniert wunderbar einfach, solange alle Objekte eine __toString() Methode besitzen. Tun sie das nicht erhält man eine Exception.

Eine Lösung wäre jetzt die explizite Prüfung, ob es sich bei einer der beteiligen Spalten um einen Datetime Datentyp handelt und eine entsprechende Sonderbehandlung dieses Typs. Diesen Weg ist man gegangen, der dazugehörige Code hat es aber aus Performancegründen nie in einen produktiven Zweit des Repository geschafft.

Eine andere Lösung ist das Überschreiben, der von Doctrine verwendeten Datetime Klasse, für die entsprechenden SQL-Typen zu einer Datetime Klasse die eine generische __toString() Methode zur Verfügung stellt.

Klingt einfach, bringt aber ein Problem mit sich. Wenn man von der Klasse Datetime ableitet, kann man zwar relativ leicht die __toString() Methode ergänzen, man muss aber immer noch Objekte der Klasse Erzeugen können. Da Datetime schon vor PHP 5.3 existierte, unterstützt die Klasse keinerlei LSB Funktionalität. D.h. die statische Methode MyDatetime::createFromFormat() wird immer ein Objekt vom Typ Datetime liefern, welches man beim Aufruf der Methode im Kontext der Klasse MyDatetime gleich wieder verwerfen kann, um daraus ein neues Objekt vom richtigen Typ zu erzeugen.

Datetime in Propel

Von dem gleichen Problem mit der fehlenden __toString() Methode ist auch Propel betroffen, denn auch da werden zur Identifizierung einfach die jeweiligen String-Entsprechungen verkettet. Das Problem lässt sich aber bei Propel leichter umgehen, indem man die Nutzung der Datetime Klasse für Datums- und Uhrzeitangaben gleich komplett verbietet.

bekanntes Problem

Das Problem mit der fehlenden __toString() Methode bzw. fehlender LSB Funktionalität ist aber nicht neu. Entsprechende Tickets finden sich schon seit geraumer Zeit im Bug-Trackerr des PHP-Projekts. Es passiert aber rein gar nichts, da jeder Entwickler immer wieder Workarounds für diese fehlende Funktionalität einbaut.

  • Ticket von Benjamin Eberlei, seines Zeichens einer der Hauptentwickler von Doctrine, wegen fehlendem LSB. (https://bugs.php.net/bug.php?id=60302) Er wollte offensichtlich von Datetime ableiten und stieß dabei auf das beschriebene Problem.
    • außer einer Reaktion vom Autor der Datetime Klasse mit einem: “Nicht so einfach wie ich zuerst dachte.” Ist nichts passiert.
  • Ticket wegen fehlender __toString() Methode und Vorschlag der Definition eines Standardformats welches von der Funktion zurück gegeben werden soll. (https://bugs.php.net/bug.php?id=41187) Das Ticket gibt es bereits seit dem Jahr 2007.
    • keinerlei Reaktion

Selbst ist der Mann

Ich dachte mir “Wozu hab ich all die Jahre C gelernt?” und habe mich dem zweiten Ticket angenommen, da es das Problem an einer Wurzel beseitigt und ersteres ja nur daraus resultiert. Für mich ein voller Erfolg. Ich bin jetzt stolzer Besitzer einer PHP Version deren Datetime Klasse eine funktionierende __toString() Methode hat. Nur der Rest der Community nicht, sofern dieser nicht dazu übergeht seinen PHP-Quellcode selbst zu patchen und zu kompilieren. Der entsprechende Pull-Request auf Github verstaubt nämlich derzeit genauso wie das Ticket im PHP Bug-Tracker selbst.