Подтвердить что ты не робот

Print_r() добавляет свойства к объектам DateTime

Рассмотрим следующий пример кода:

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

Начиная с PHP 5.3, это производит (что-то вроде) следующий вывод:

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

Однако следующий код:

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

... просто испускает ошибку:

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

Почему print_r() "добавить" эти свойства к объекту? Обратите внимание, что они не определены как часть класса DateTime на странице .

4b9b3361

Ответ 1

Существует какая-то магия, но она довольно проста.

Класс DateTime не имеет общедоступной переменной 'date', к которой вы хотите получить доступ. Однако, как побочный эффект работы PHP, существует переменная, созданная при вызове print_r или var_dump в этом классе.

После этого волшебства появляется "дата", но этого не должно быть. Вы должны просто использовать функцию getTimestamp, чтобы ваш код работал надежно.

Ответ 2

Это было как ошибка # 49382 в PHP.

В PHP 5.3 добавлена ​​внутренняя функциональность, чтобы позволить print_r() отображать сведения о базовом значении временной метки, хранящейся в экземпляре DateTime, чтобы помочь в отладке. Побочным эффектом этого изменения является то, что когда объект сбрасывается в текст, эти phantom общедоступные свойства добавляются в экземпляр.

Тот же эффект может быть достигнут с помощью reflection для доступа к этим свойствам, и если вам нужно получить доступ к свойствам, то использование отражения будет быть способ пойти, поэтому вы не вызываете ошибку.

Однако следует отметить, что вы не должны действительно использовать эти свойства - поскольку они не определены как члены объекта, нет гарантии, что они будут продолжать переносить одни и те же данные (или даже существуют) в будущем PHP версии. Если вам нужно получить доступ к информации, используйте следующие методы, определенные как часть API, вместо этого:

// $obj->date
$obj->format('Y-m-d 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

Примечание. Свойство timezone_type недоступно через PHP API. Это внутреннее значение и не полезно в пользовательской области, поскольку оно описывает тип строки, которая timezone выполняется при удалении объекта, т.е. Один из трех способов получения информации о часовом поясе в примере кода выше. Для полноты его возможные значения определены следующим образом:

<Предварительно > Значение | Тип | Эквивалент ------ + ----------------------- + ------------------- --------------- 1 | смещение по времени | DateTimeZone:: getOffset()2 | Сокращение времениZone | DateTimeZone:: listAbbreviations()3 | Идентификатор TimeZone | DateTimeZone:: getName()

Ответ 3

Нет свойства date в DateTime; почему вы получаете (Undefined property: DateTime::$date).

print_r() выполняет интроспекцию объекта для отображения его содержимого; это заставляет объект магически создавать свойство ::date. Это не документировано, поэтому использование этого может привести к повреждению вашего кода в будущем.

Вместо этого вам нужно что-то вроде $m_oDate->format('m-d-Y');.

Ответ 4

Проблема лежит здесь:

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

Функция date_object_get_properties вызывается, когда производится сброс данных (print_r, var_dump, var_export). Хэш-таблица обновляется для данных, которые, к сожалению, становятся общедоступными.

Ответ 5

Рассмотрим следующий пример кода:

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

Наиболее очевидным отличием от вашего является то, что вместо функции print_r вызывается другая some_func. Ожидания могут отличаться, потому что вы знаете print_r, но вы не знаете some_func, но это только для того, чтобы обострить ваши чувства. Подождите немного, пока я не покажу определение этой функции.

Второе отличие - это имя свойства, которое получает эхо. Здесь я выбрал имя, которое действительно исключительное: {'ROXXOR_IS_BACK!!'}, чтобы снова заострить ваши чувства.

Это имя, что безумное, что должно быть очевидно, не является частью DateTime, хотя при выполнении вышеприведенного примера совершенно ясно, что это свойство roxxor должно существовать. Выход программы:

PHP never lets you down.

Так почему? Да, вы наверняка уже знаете, как это работает. Функция some_func() должна была добавить ее. Поэтому давайте рассмотрим определение функций:

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

Да, теперь ясно видно, что эта функция добавила свойство к объекту. И это также показывает, что это вполне возможно с любым объектом в PHP.

Сравните с массивом в PHP, вы также можете добавить новые ключи, если хотите.

Этот пример не был выбран из ничего, потому что именно здесь возникают объекты в PHP: они всего лишь синтаксический сахар вокруг массивов, и это связано с тем, что объекты в PHP были введены на PHP 3:

В классы времени, которые были введены в исходное дерево того, что должно было стать PHP 3.0, они были добавлены в качестве синтаксического сахара для доступа к коллекциям. У PHP уже было понятие ассоциативных коллекций массивов, и новые твари были не чем иным, как опрятным новым способом доступа к ним. Однако, как показало время, этот новый синтаксис оказал гораздо более глубокое влияние на PHP, чем первоначально предполагалось.

- Zeev Suraski о стандартном объекте с PHP 3 (архивная копия) - через Зачем возвращать объект вместо массива?

Это также простое объяснение, почему он полностью распространен в PHP, функции могут добавлять переменные-члены, которые ранее не были определены в классе. Это всегда публично.

Итак, когда вы делаете предположения о каком-либо объекте, обладающем свойством или нет, посмотрите, откуда он. Он не должен быть частью класса, но может быть добавлен позже.

И помните следующее:

Не используйте print_r и var_dump в производственном коде.

Ответ 6

Для удовольствия от этого вы можете заставить его работать, используя Reflection:

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

Источник

Ответ 7

Вы должны использовать DateTime::format или DateTimeImmutable::format, в зависимости от ситуации

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