PHP[OOP] - 如何手动调用类构造函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1899299/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP[OOP] - How to call class constructor manually?
提问by A.N.M. Saiful Islam
Please see the code bellow:
请看下面的代码:
01. class Test {
02. public function __construct($param1, $param2, $param3) {
03. echo $param1.$param2.$param3;
04. }
05. }
06.
07. $params = array('p1','p2','p3');
08.
09. $ob = new Test;
10.
11. if(method_exists($ob,'__construct')) {
12. call_user_func_array(array($ob,'__construct'),$params);
13. }
Now, the problem is the constructoris called in line 09
现在,问题是在第 09 行调用了构造函数
But i want to call it manuallyat line 11-13
但我想在第 11-13 行手动调用它
Is it possible? If then how? Any ideaplease?
是否可以?如果那怎么办?任何想法吗?
回答by Asaph
It is not possible to prevent the constructor from being called when the object is constructed (line 9 in your code). If there is some functionality that happens in your __construct()method that you wish to postpone until after construction, you should move it to another method. A good name for that method might be init().
在构造对象时无法阻止调用构造函数(代码中的第 9 行)。如果您的__construct()方法中发生了一些您希望推迟到构造之后的功能,您应该将其移动到另一个方法中。该方法的一个好名字可能是init().
Why not just do this?
为什么不这样做呢?
class Test {
public function __construct($param1, $param2, $param3) {
echo $param1.$param2.$param3;
}
}
$ob = new Test('p1', 'p2', 'p3');
EDIT: I just thought of a hacky way you could prevent a constructor from being called (sort of). You could subclass Testand override the constructor with an empty, do-nothing constructor.
编辑:我只是想到了一种可以防止构造函数被调用的黑客方法(有点)。您可以Test使用一个空的、什么都不做的构造函数来子类化和覆盖构造函数。
class SubTest extends Test {
public function __construct() {
// don't call parent::__construct()
}
public function init($param1, $param2, $param3) {
parent::__construct($param1, $param2, $param3);
}
}
$ob = new SubTest();
$ob->init('p1', 'p2', 'p3');
This is might make sense if you're dealing with some code that you cannot change for some reason and need to work around some annoying behavior of a poorly written constructor.
如果您正在处理一些由于某种原因无法更改的代码,并且需要解决编写不当的构造函数的一些烦人行为,那么这可能是有意义的。
回答by Sarfraz
Note that if the constructor (__construct method) contains arguments passed by reference, then the function:
请注意,如果构造函数(__construct 方法)包含通过引用传递的参数,则该函数:
call_user_func_array
will fail with an error.
会因错误而失败。
I suggest you to use Reflection class instead; here is how you can do so:
我建议你改用 Reflection 类;以下是您可以这样做的方法:
// assuming that class file is already included.
$refMethod = new ReflectionMethod('class_name_here', '__construct');
$params = $refMethod->getParameters();
$re_args = array();
foreach($params as $key => $param)
{
if ($param->isPassedByReference())
{
$re_args[$key] = &$args[$key];
}
else
{
$re_args[$key] = $args[$key];
}
}
$refClass = new ReflectionClass('class_name_here');
$class_instance = $refClass->newInstanceArgs((array) $re_args);
回答by Renzo
I don't know if there are some security concerns by using the eval() method, but you could make yourself a function like this:
我不知道使用 eval() 方法是否存在一些安全问题,但是您可以使自己成为这样的函数:
function CreateObj($className,$params)
{
$strArgs = '$params['.implode('],$params[',array_keys($params)).']';
eval('$ob = new '.$className.'('.$strArgs.');');
return $ob
}
And now $ob should now be defined with its correct parameters, i haven't tested it and maybe there is a mistake in the code, but you get the idea....
现在 $ob 现在应该用正确的参数定义,我还没有测试它,也许代码中有错误,但你明白了......
回答by Dathan
If separating instantiation from initialization isn't strictly a requirement, there are two other possibilities: first, a static factory method.
如果不是严格要求将实例化与初始化分开,那么还有另外两种可能性:首先,静态工厂方法。
class Test {
public function __construct($param1, $param2, $param3) {
echo $param1.$param2.$param3;
}
public static function CreateTest($param1, $param2, $param3) {
return new Test($param1, $param2, $param3);
}
}
$params = array('p1','p2','p3');
if(method_exists($ob,'__construct')) {
call_user_func_array(array($ob,'CreateTest'),$params);
}
Or, if you're using php 5.3.0 or higher, you can use a lambda:
或者,如果您使用的是 php 5.3.0 或更高版本,则可以使用 lambda:
class Test {
public function __construct($param1, $param2, $param3) {
echo $param1.$param2.$param3;
}
}
$params = array('p1','p2','p3');
$func = function ($arg1, $arg2, $arg3) {
return new Test($arg1, $arg2, $arg3);
}
if(method_exists($ob,'__construct')) {
call_user_func_array($func, $params);
}
The initialization method described by Asaph is great if for some reason you have a need to logically separate initialization from instantiation, but if supporting your use case above is a special case, not a regular requirement, it can be inconvenient to require users to instantiate and initialize your object in two separate steps.
如果出于某种原因您需要在逻辑上将初始化与实例化分开,Asaph 描述的初始化方法很好,但是如果支持上述用例是一种特殊情况,而不是常规要求,那么要求用户实例化和在两个单独的步骤中初始化您的对象。
The factory method is nice because it gives you a method to call to get an initialized instance. The object is initialized and instantiated in the same operation, though, so if you have a need to separate the two it won't work.
工厂方法很好,因为它为您提供了一个方法来调用以获取初始化的实例。但是,该对象在同一个操作中初始化和实例化,因此如果您需要将两者分开,它将不起作用。
And lastly, I recommend the lambda if this initialization mechanism is uncommonly used, and you don't want to clutter your class definition with initialization or factory methods that will hardly ever be used.
最后,如果这种初始化机制不常用,我推荐 lambda,并且您不想用几乎不会使用的初始化或工厂方法来混淆您的类定义。
回答by justastefan
to construct your object first and then pass parameters your could try this way:
首先构造您的对象,然后传递参数,您可以尝试这种方式:
class Test {
public function __CONSTRUCT($p1="Bundy", $p2="house", $p3=10) {
$this->init($p1, $p2, $p3);
}
public function init($p1, $p2, $p3) {
//setup your object here
}
}
then it is possible to construct the object and call
那么就可以构造对象并调用
$ob->init($p1, $p2, $p3);
later.
之后。
回答by hakre
In PHP you can create objects w/o calling the constructor. But that does not work by using new but by un-serializing an object instance.
在 PHP 中,您可以在不调用构造函数的情况下创建对象。但这不能通过使用 new 而是通过取消序列化对象实例来实现。
The constructor can then be called manually.
然后可以手动调用构造函数。
Normally this is not needed. See as well: Loading an object from PHP session, does it call constructor?
通常不需要这样做。另请参阅:从 PHP 会话加载对象,是否调用构造函数?
<?php
class Test
{
public function __construct()
{
echo '__construct called.',"\n";
}
}
function old($class)
{
return unserialize
(
sprintf
(
'O:%d:"%s":0:{}',
strlen($class),
$class
)
);
}
$test = old('Test');
$test->__construct();

