Php 在调用构造函数之前有没有办法设置属性?

Php 在调用构造函数之前有没有办法设置属性?,php,constructor,code-injection,Php,Constructor,Code Injection,是的,我知道依赖项应该传递给构造函数。我不是在问编码风格或是做什么和不做什么 我的应用程序中的许多类都与数据库驱动程序类的实例相关联。为此,我使用PHP的后期静态绑定创建了一个抽象工厂类。此类的唯一成员是保存驱动程序引用的属性。看起来是这样的: abstract class Factory { static private $__instances; static private $__default_driver; protected $_driver;

是的,我知道依赖项应该传递给构造函数。我不是在问编码风格或是做什么和不做什么

我的应用程序中的许多类都与数据库驱动程序类的实例相关联。为此,我使用PHP的后期静态绑定创建了一个抽象工厂类。此类的唯一成员是保存驱动程序引用的属性。看起来是这样的:

abstract class Factory {

    static private $__instances;
    static private $__default_driver;

    protected $_driver;

    static public function getInstance ( \Database\Driver $driver = null ) {
        if ( ! isset($driver) ) {
            if ( ! isset(self::$__default_driver) ) {
                require ( \Core\Options::$database_driver[ 'path' ] );
                self::$__default_driver = new \Core\Options::$database_driver[ 'class' ]( \Core\Options::$database_options );
            }
            $driver = self::$__default_driver;
        }

        $schema = $driver->getDatabase();
        $class  = get_called_class();

        if ( ! isset(self::$__instances[ $schema ][ $class ]) ) {
            self::$__instances[ $schema ][ $class ] = new $class( $driver );
            self::$__instances[ $schema ][ $class ]->_driver = $driver;
        }

        return self::$__instances[ $schema ][ $class ];
    }
}
如您所见,当我创建派生类的实例时,我将驱动程序的实例传递给它的构造函数。然后设置属性。如果可能的话,我想通过先设置属性然后调用构造函数来扭转这种情况。这样,派生类就不需要实现构造函数,也不用担心调用父方法

我已经研究了
反射
API来实现这一点,但似乎找不到任何可行的方法。我发现的大多数依赖项注入链接实际上都使用构造函数。这需要在PHP5.3上运行

对于那些认为这是不可能的人,使用
ReflectionClass::newInstanceWithoutConstructor()

“我知道依赖项应该传递给构造函数”,这是不正确的,在依赖项由重写的构造函数继承的情况下,使用它是一个坏主意

在这些情况下,类甚至可能不使用构造函数,这意味着类持有的唯一状态是它的依赖项,并且在对象的生命周期内,方法被视为静态的,然后是无状态的


这在Symfony2中非常常见,通过DI加载的某些服务不包含传递给构造函数的参数,或者如果包含,则扩展必须兼容。

您无法设置尚不存在的对象的值,您需要实例化您的对象,然后通过将必要的参数传递给构造函数来初始化它,在构造函数内部,您必须使用这些参数来初始化对象

class Foo {
    public function __construct() {
        echo 'foo';
    }
}

$r = new ReflectionClass('Foo');
$o = $r->newInstanceWithoutConstructor();
$o->bar = 'baz';
$o->__construct();
这是可能的,因为PHP5.4

但实际上:不。只是不。不要。在实例化对象时,应该始终调用对象的构造函数。不早(显然),不晚。构造函数和对象其余部分的适当封装保证了对象始终处于一致状态。一旦开始使用
ReflectionClass
将其拆分,就无法再保证对象的状态,并且健全性和类型安全性也将消失


既然你在5.3上,你很幸运没有办法做到这一点。如果你发现自己陷入了这样的困境,那你就是做错了。已经编写了非常复杂的程序,而不需要欺骗PHP的对象模型来延迟构造函数调用。

不,在实例化对象之前,不能在对象上设置属性,因为在实例化对象之前,没有对象可以设置任何内容。老实说,如果你把自己画进一个角落,试图在事物存在之前设置它们的属性,那么也许是时候退一步,评估一下你是否应该使用不同的设计模式了。:)老实说,我不知道你在说什么。但我很好奇。要澄清的代码示例将非常有用。@deceze简言之,在没有任何参数的情况下实例化该类,调用属性,然后在实际开始使用该对象时初始化该对象的数据(这可以在内部调用)。据我所知,构造函数不创建对象,而是使用通过
new
传递的参数对其进行初始化。事实上,
\u构造
只是一种方法(魔法与否)。必须能够创建一个对象,设置一个参数,然后调用构造函数。我知道这是可能的,其他语言如C++。构造函数初始化对象。当您使用new操作符时,您告诉PHP实例化该类并调用新创建的对象的构造函数。这就是路。您可以创建对象工厂来简化实例化的使用,但是在一天结束时,您可以使用新操作符直接或间接地调用构造函数。同样,新操作符不仅调用构造函数,而且实例化类,然后调用其构造函数。这里仍然有一个构造函数。另一件事是通过反射实现的,但是在一天结束时,您使用的是构造函数。如果您不想运行构造函数,可以跳过
$o->\uu construct()
。或者您指的是没有构造函数的ReflectionClass::newInstanceWithoutConstructor
?这不是真正的构造函数,它显式地避免了构造函数。实例化对象与运行构造函数不同。