为什么从未调用ArrayIterator子类的构造函数? - php

我困惑为什么ArrayIterator的子类永远不会调用其__construct方法。考虑以下示例:

<?php

class ConstructorException extends Exception {}

class Foo extends ArrayObject {
    function __construct( $arr = array(), $flags = 0, $iterator = 'ArrayIterator' ) {
        $iterator = 'FooIterator';
        parent::__construct( $arr, $flags, $iterator );
    }
}

class FooIterator extends ArrayIterator {
    function __construct( $array = array(), $flags = 0 ) {
        throw new ConstructorException( 'HELLO WORLD' ); // I AM NEVER CALLED.
        parent::__construct( $array, $flags );
    }
}

try {
    $f = new Foo( array( 1, 2, 3 ) );
    $it = $f->getIterator();
    if ( get_class( $it ) !== 'FooIterator' ) {
        throw new Exception( 'Expected iterator to be FooIterator.' );
    }
    die( "FAIL\n" );
} catch ( ConstructorException $e ) {
    die( "PASS\n" );
} catch ( \Exception $e ) {
    die( sprintf( "ERROR: %s\n", $e->getMessage() ) );
}

在PHP 5.4和5.5中,结果均为FAIL。为什么?

参考方案

@Leggendario是正确的说法,问题出在spl_array_object_new_ex方法上。但是,如果不确定,我不确定。但是,这并不是真正的标准。

构造函数中的iteratorClass变量(或通过setIteratorClass设置)建议,只要我们从ArrayObject中检索迭代器,该类都将实例化。但是它不会进行常规的“实例化”,因为这是不可能的。

它只会初始化迭代器(分配内存等),而不调用构造函数。不调用构造函数是有道理的,因为ArrayIterator的构造函数带有两个参数($array$flags),并且您的类可能已更改其签名,甚至可能添加了更多(强制性值)。

通常,ArrayIterator(或RecursiveArrayIterator)是内部类,并且具有连接到它们的内部结构(基本上像它自己的内部属性集,您不能直接从PHP用户区获取这些属性)。 spl_array_object_new_ex将直接设置这些内部值(最著名的是ce_get_iteratorar_flags)。因此,基本上,它负责ArrayIterator构造函数的工作。

因为PHP检查给定的类是否为ArrayIterator,或者父类之一是否为一。在这种情况下,这意味着它最终可以使用这些内部值,从而直接设置它们,而无需任何构造函数。不利的一面是,您想要构建的任何东西都不会被调用。

PHP strtotime困境 - php

有人可以解释为什么这在我的服务器上输出为true吗?date_default_timezone_set('Europe/Bucharest'); var_dump( strtotime('29.03.2015 03:00', time()) === strtotime('29.03.2015 04:00�…

PHP-全局变量的性能和内存问题 - php

假设情况:我在php中运行一个复杂的站点,并且我使用了很多全局变量。我可以将变量存储在现有的全局范围内,例如$_REQUEST['userInfo'],$_REQUEST['foo']和$_REQUEST['bar']等,然后将许多不同的内容放入请求范围内(这将是适当的用法,因为这些数据指的是要求自…

php-casperjs获取内部文本 - php

我正在为casperjs使用php包装器-https://github.com/alwex/php-casperjs我正在网上自动化一些重复的工作,我需要访问一个项目的innerText,但是我尚不清楚如何从casperjs浏览器访问dom。我认为在js中我会var arr = document.querySelector('label.input…

PHP getallheaders替代 - php

我正在尝试从服务器上的apache切换到nginx。唯一的问题是我在PHP脚本中使用的getallheaders()函数,该函数不适用于Nginx。我已经尝试过用户在getallheaders函数上的php站点上提供的注释,但这并不返回所有请求标头。请告诉我如何解决这个问题。我真的想切换到Nginx。 参考方案 您仍然可以使用它,但是您必须像这里一样重新定义…

PHP Laravel从另一个驱动器读取文件 - php

我目前正在学习Laravel。我想知道是否有一种方法可以在Laravel中使用Storage::从另一个硬盘访问文件(使用Windows)。例如,我在驱动器C:上安装了带有Laravel的Xampp,但是我想访问网站目录之外的E:上的文件。我试过使用Storage::files('E:')和File::files('E:…