print_r()向DateTime对象添加属性

CHa*_*HaP 19 php debugging datetime php-internals

请考虑以下代码示例:

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

从PHP 5.3开始,这会产生(类似)以下输出:

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

但是以下代码:

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

......只是发出一个错误:

Notice: Undefined property: DateTime::$date in ...
Run Code Online (Sandbox Code Playgroud)

为什么要print_r()"添加"这些属性到对象?请注意,它们未DateTime手册页上定义为类的一部分.

Cly*_*obo 14

这已在PHP中报告为Bug#49382.

在PHP 5.3中,添加了内部功能以允许print_r()显示实例所持有的基础时间戳值的详细信息DateTime,以帮助进行调试.此更改的副作用是,当将对象转储到文本时,会将这些幻像公共属性添加到实例中.

通过使用反射来访问这些属性可以实现相同的效果,如果您需要访问属性,那么使用反射将是一种方法,因此您不会引发错误.

但是,应该注意的是,您不应该真正使用这些属性 - 因为它们未被定义为对象的成员,因此无法保证它们将在未来的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
Run Code Online (Sandbox Code Playgroud)

注意:timezone_type无法通过PHP API访问该属性.它是一个内部值,在userland中没用,因为它描述了timezone转储对象时保存的字符串类型- 即上面代码示例中获取时区信息的三种方法之一.为完整起见,其可能的值按以下方式定义:

Value | Type                  | Userland equivalent
------+-----------------------+----------------------------------
  1   | time offset           | DateTimeZone::getOffset()
  2   | TimeZone abbreviation | DateTimeZone::listAbbreviations()
  3   | TimeZone identifier   | DateTimeZone::getName()

  • @vascowhite:你还没有理解这个问题. (3认同)
  • 这不是错误 - 这是一个功能! (2认同)
  • 现在您可以将它用作功能:`$ x = new DateTime(); ob_start(); 的print_r($ X); ob_end_clean(); echo $ x-> date;` (2认同)

RRi*_*esh 9

没有date财产DateTime; 这就是你得到的原因(Undefined property: DateTime::$date).

print_r()对对象进行一些内省以显示其内容; 这会导致对象神奇地创建::date属性.但是没有记录,因此使用它可能会在将来破坏您的代码.

你需要这样的东西$m_oDate->format('m-d-Y');.

  • 为什么选择downvote?这绝对是真的.虽然它没有解释为什么在包含`print_r()`时不会看到错误 (2认同)
  • @Jon我看到你来自哪里,但在某种程度上它完全回答了这个问题:PHP手册中定义的`DateTime`*的界面,因此关于主题*的规范参考不包括` - >日期`财产.所以问题实际上是"当我尝试访问不属于界面的属性时,为什么会出现错误",并且当这样做时,答案就是"因为它不是界面的一部分".我确实理解它并没有完全回答问题的问题,但我会反对OP提出错误的问题;-) (2认同)

Dan*_*ack 9

有一些神奇的发生,但它很简单.

DateTime类没有您要访问的公共变量"date".但是,作为PHP工作方式的副作用,在该类上调用print_r或var_dump时会创建一个变量.

在那之后,魔法发生'日期'可用,但它不应该.您应该只使用getTimestamp函数来使代码可靠地工作.


Dan*_*Lee 5

问题在于:

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

的功能date_object_get_properties,当任何数据倾倒的情况下(称为print_r,var_dump,var_export).哈希表针对表示的数据进行了更新,不幸的是,这是公开的.