(PHP)为什么我的DateTime对象属性强制转换为字符串,但仅当从其他类访问时


(PHP) Why is my DateTime object property force-cast to a string, but only when accessed from a different class?

这对我来说没有任何意义——也许对这里的其他人来说有意义。

我有一个名为Event的类,它表示一个事件。它有三个属性:iddescriptiontimetime属性本身就是DateTime类型的对象。

第三个类Member具有一个名为Events的属性,该属性由Event对象的数组填充。因此,Member对象的一个简单的var_dump看起来是这样的,省略了一些与此无关的属性:

object(Member)#5 (32) {
  ["id":protected]=>
  string(3) "127"
  ["events":protected]=>
  array(1) {
    [0]=>
    object(Event)#13 (4) {
      ["id":protected]=>
      string(1) "1"
      ["description":protected]=>
      string(10) "Some text here"
      ["time":protected]=>
      object(DateTime)#14 (3) {
        ["date"]=>
        string(26) "2010-01-01 00:00:00.000000"
        ["timezone_type"]=>
        int(3)
        ["timezone"]=>
        string(17) "Europe/London"
      }
    }
  }
}

Member类中,有一个函数以表格形式列出所有事件,formatEventsAsTable(),简而言之就是这样做的:

public function formatEvents() {
    $return = <<<EOT
        <table>
            <tbody>
EOT;
    foreach ($this->events as $event) {
        $date = $event->time->format('j/n Y');
        $return .= <<<EOT
                <tr>
                    <td>$date</td>
                    <td>$event->text</td>
                </tr>
EOT;
    }
    $return .= <<<EOT
            </tbody>
        </table>
EOT;
    return $return;
}

据我所知,这应该起作用:在循环中,$event是一个Event对象(可通过循环期间的var_dump验证),其属性timeDateTime对象,因此应该具有format函数但它不起作用

出于某种原因,DateTime对象被强制转换为字符串,我得到了以下错误消息:

致命错误:未捕获错误:在/path/to/file/class.member.php:116 中的字符串上调用成员函数format()

这是我最意想不到的:var_dump $event将属性time显示为DateTime对象。但var_dump $event->time产生

string(10) "2010-01-01"

更奇怪的是:如果我把实际代码放在Event类内的foreach循环中,添加一个调用$this->time->format('j/n Y')的函数Event::formatAsTableRow(),然后简单地在Member::formatEventsAsTable()中的foreach循环中调用该函数…,那么它就可以正常工作

 

那么,为什么我可以从作为属性的类中访问DateTime对象,而不能从其他类中的函数中访问呢?为什么它在那里被强制施法(?)到字符串

我想,这里的问题是您试图从受保护的类成员的访问范围之外访问它。

不过,我不知道为什么你会得到这个特定的错误,而你应该得到Cannot access protected property of Event::time类型的错误。更重要的是,我编写了一些与您类似的代码,并得到了正确的错误(php5.4.45)。我想知道您使用的php版本。

答案是我是个白痴。

MemberEvent类都扩展了一个基类,我显然在该类中定义了一个神奇的__toString()方法,在该方法中,我专门检查DateTime对象,并将它们输出为'Y-m-d'字符串。

然而,我仍然困惑于为什么var_dump调用对象会调用它的__toString()方法。