print_r () fügt DateTime-Objekten Eigenschaften hinzu

Betrachten Sie das folgende Codebeispiel:

$m_oDate = new DateTime('2013-06-12 15:54:25'); print_r($m_oDate); echo $m_oDate->date; 

Seit PHP 5.3 erzeugt dies (ähnlich) folgende Ausgabe:

 DateTime Object ( [date] => 2013-06-12 15:54:25 [timezone_type] => 3 [timezone] => Europe/Amsterdam ) 2013-06-12 15:54:25 

Jedoch der folgende Code:

 $m_oDate = new DateTime('2013-06-12 15:54:25'); echo $m_oDate->date; 

… gibt einfach einen Fehler aus:

 Notice: Undefined property: DateTime::$date in ... 

Warum fügt print_r() diese Eigenschaften dem Objekt hinzu? Beachten Sie, dass sie auf der DateTime nicht als Teil der DateTime class definiert sind.

   

    Es passiert etwas Magie, aber es ist ziemlich einfach.

    Die class DateTime hat keine öffentliche Variable ‘date’, auf die Sie zugreifen sollen. Als Nebeneffekt der functionsweise von PHP gibt es jedoch eine Variable, die beim Aufruf von print_r oder var_dump für diese class erstellt wird.

    Nach dieser Magie passiert “Datum” ist verfügbar, aber es sollte nicht sein. Sie sollten nur die function getTimestamp verwenden, damit Ihr Code zuverlässig funktioniert.

    Dies wurde in PHP als Bug # 49382 gemeldet .

    In PHP 5.3 wurde die interne functionalität hinzugefügt, um es print_r() zu ermöglichen, Details des zugrunde liegenden Zeitmarkenwerts DateTime , der von einer Instanz von DateTime wird, um das Debuggen zu unterstützen. Ein Nebeneffekt dieser Änderung besteht darin, dass diese öffentlichen Phantomeigenschaften zur Instanz hinzugefügt werden, wenn das Objekt in Text ausgegeben wird.

    Der gleiche Effekt kann erreicht werden, indem für den Zugriff auf diese Eigenschaften eine Reflektion verwendet wird. Wenn Sie auf die Eigenschaften zugreifen müssen, ist die Verwendung der Reflektion der richtige Weg, sodass Sie den Fehler nicht provozieren.

    Es sollte jedoch beachtet werden, dass Sie diese Eigenschaften nicht wirklich verwenden sollten – da sie nicht als Mitglieder des Objekts definiert sind, gibt es keine Garantie, dass sie in zukünftigen PHP-Versionen dieselben Daten enthalten (oder sogar existieren). Wenn Sie auf die Informationen zugreifen müssen, verwenden Sie stattdessen die folgenden Methoden, die als Teil der API definiert sind:

     // $obj->date $obj->format('Ymd H:i:s'); // $obj->timezone $obj->getTimezone()->getName(); // or... $obj->getTimezone()->getOffset(); // or... $obj->getTimezone()->listAbbreviations(); // returns an array, so may need // further processing to be of use 

    Hinweis: Auf die Eigenschaft timezone_type nicht über die PHP-API zugegriffen werden. Es ist ein interner Wert und in userland nicht nützlich, da es den Typ der Zeichenfolge beschreibt, die die timezone enthält, wenn das Objekt gedumpt wird – dh eine der drei Methoden zum Erhalten von Zeitzoneninformationen im obigen Codebeispiel. Der Vollständigkeit halber sind seine möglichen Werte folgendermaßen definiert :

     Wert |  Typ |  Userland entspricht
     ------ + ----------------------- + ------------------- ---------------
       1 |  Zeitverschiebung |  DateTimeZone :: getOffset ()
       2 |  TimeZone-Abkürzung |  DateTimeZone :: listAbkürzungen ()
       3 |  TimeZone-Kennung |  DateTimeZone :: getName ()
    

    Es gibt keine date Eigenschaft in DateTime . Deshalb (Undefined property: DateTime::$date). du (Undefined property: DateTime::$date).

    print_r() führt eine Introspektion auf dem Objekt durch, um seinen Inhalt anzuzeigen; Das bewirkt, dass das Objekt die Eigenschaft ::date magisch erzeugt. Dies ist jedoch nicht dokumentiert. Wenn Sie dies verwenden, kann dies Ihren Code in Zukunft beschädigen.

    Du brauchst etwas wie $m_oDate->format('md-Y'); stattdessen.

    Das Problem liegt hier :

     static HashTable *date_object_get_properties(zval *object TSRMLS_DC) { // ... zend_hash_update(props, "date", 5, &zv, sizeof(zval), NULL); // ... 

    Die function date_object_get_properties wird aufgerufen, wenn ein date_object_get_properties wird ( print_r , var_dump , var_export ). Die Hash-Tabelle wird für die Darstellung von Daten aktualisiert, leider wird dies öffentlich gemacht.

    Betrachten Sie das folgende Codebeispiel:

     $m_oDate = new DateTime('2013-06-12 15:54:25'); some_func($m_oDate); echo $m_oDate->{'ROXXOR_IS_BACK!!'}; 

    Der offensichtlichste Unterschied zu print_r ist, dass anstelle der print_r function ein anderer some_func aufgerufen wird. Die Erwartungen könnten sich unterscheiden, weil Sie print_r kennen, aber Sie print_r nicht kennen, aber das ist nur, um Ihre Sinne zu schärfen. Warten wir einen Moment, bis ich die Definition dieser function zeige.

    Der zweite Unterschied ist der Name der Eigenschaft, die echoed ist. Hier habe ich einen Namen gewählt, der wirklich außergewöhnlich ist: {'ROXXOR_IS_BACK!!'} , wieder um deine Sinne zu schärfen.

    Dieser Name ist so verrückt, dass es offensichtlich sein muss, dass er nicht Teil von DateTime wenn das obige Beispiel ausgeführt wird, ist völlig klar, dass diese roxxor -Eigenschaft existieren muss . Programmausgabe:

     PHP never lets you down. 

    Wie kommt es? Ja, Sie haben sicher schon eine Idee, wie das geht. Die function some_func() muss sie hinzugefügt haben. Sehen wir uns die Definition der functionen an:

     function some_func($m_oDate) { $m_oDate->{'ROXXOR_IS_BACK!!'} = 'PHP never lets you down.'; } 

    Ja, es ist nun deutlich sichtbar, dass diese function dem Objekt eine Eigenschaft hinzugefügt hat. Und es zeigt auch, dass dies mit jedem Objekt in PHP absolut problemlos möglich ist.

    Vergleichen Sie mit einem Array in PHP, Sie können auch neue Schlüssel hinzufügen, wenn Sie möchten.

    Dieses Beispiel wurde nicht aus dem Nichts gewählt, denn hier kommen Objekte in PHP her: Sie sind nur syntaktischer Zucker um Arrays und das muss mit der Zeit, als Objekte in PHP zurück in PHP 3 eingeführt wurden:

    Zu der Zeit, als classn in den Quellbaum von dem eingeführt wurden, was später PHP 3.0 werden sollte, wurden sie als syntaktischer Zucker für den Zugriff auf Sammlungen hinzugefügt. PHP hatte bereits die Idee von assoziativen Array-Sammlungen, und die neuen Lebewesen waren nichts anderes als eine nette neue Art, auf sie zuzugreifen. Diese neue Syntax erwies sich jedoch im Laufe der Zeit als weitaus weitreichender als ursprünglich geplant.

    Zeev Suraski über das Standardobjekt seit PHP 3 ( archivierte Kopie ) – über Warum Objekt anstelle von Array zurückgeben?

    Dies ist auch die einfache Erklärung, warum es in PHP völlig normal ist, dass functionen Member-Variablen hinzufügen können, die nicht in der class zuvor definiert wurden. Diese sind immer öffentlich.

    Wenn Sie also Annahmen über ein Objekt mit einer Eigenschaft treffen, schauen Sie sich an, woher es kommt. Es darf nicht Teil der class sein, wurde aber möglicherweise später hinzugefügt.

    Und bedenke Folgendes:

    Verwenden Sie print_r und var_dump im Produktionscode.

    Zum Spaß, so können Sie es mit Reflection funktionieren lassen:

     $m_oDate = new DateTime('NOW'); $o = new ReflectionObject($m_oDate); $p = $o->getProperty('date'); echo $p->getValue($m_oDate); 

    Quelle

    Sie sollten DateTime::format oder DateTimeImmutable::format verwenden

     $m_oDate = new DateTime('NOW'); echo $m_oDate->format("r");