PHP在创建新对象时传递参数,对象调用call_user_func_array

时间:2022-02-11 21:31:27

I would like to dynamically create a PHP object, and parameters would be optional.

我想动态创建一个PHP对象,参数是可选的。

For example, instead of doing this:

例如,而不是这样做:

$test = new Obj($param);

I would like to do something like this (create new ob is fictional):

我想做这样的事情(创建新的ob是虚构的):

$test = create_new_obj('Obj', $param);

Is there such function in php? Something similar to call_user_func_array, but for object instead.

php中有这样的功能吗?类似于call_user_func_array的东西,但代替对象。

6 个解决方案

#1


20  

As of PHP 5.6, you can now achieve this with a single line of code by using the new Argument Unpacking operator (...).

从PHP 5.6开始,您现在可以使用新的Argument Unpacking运算符(...)通过一行代码实现此目的。

Here is a simple example.

这是一个简单的例子。

$className='Foo';
$args=['arg1','arg2','arg3'];

$newClassInstance=new $className(...$args);

See PHP Variable-length argument lists for more information.

有关更多信息,请参阅PHP可变长度参数列表。

#2


16  

Since some constructors may take a variable number of arguments, the following method should be used to accommodate it.

由于某些构造函数可能采用可变数量的参数,因此应使用以下方法来适应它。

$r = new ReflectionClass($strClassName);
$myInstance = $r->newInstanceArgs($arrayOfConstructorArgs);

For example, if your Car constructor took 3 args

例如,如果你的Car构造函数需要3个args

$carObj = new Car($color, $engine, $wheels);

Then

然后

$strClassName = 'Car';
$arrayOfConstructorArgs = array($color, $engine, $wheels);
$r = new ReflectionClass($strClassName);
$carObj = $r->newInstanceArgs($arrayOfConstructorArgs);

http://php.net/manual/en/class.reflectionclass.php
http://php.net/manual/en/reflectionclass.newinstanceargs.php

http://php.net/manual/en/class.reflectionclass.php http://php.net/manual/en/reflectionclass.newinstanceargs.php

#3


7  

In such cases i use factory-methods. they can be easily defined in abstract classes:

在这种情况下,我使用工厂方法。它们可以在抽象类中轻松定义:

class Foobar {

    public function __construct($foo, $bar) 
    {
        // do something
    }

    static public function factory($foo, $bar) 
    {
        return new self($foo, $bar);
    }
}

with this you can use call_user_func_array():

有了这个你可以使用call_user_func_array():

$my_foobar_obj = call_user_func_array('Foobar::factory', array($foo, $bar));

#4


5  

You can dynamically create an object as long as you know the class name:

只要知道类名,就可以动态创建对象:

$objName = 'myClass';
$test = new $objName($param);

You could easily define a __construct() function to take default arguments as well if that was a requirement of your construction logic.

如果这是构造逻辑的要求,您可以轻松定义__construct()函数以获取默认参数。

[Edit note]: This is a concept known as variable variables, and there's some examples in the manual where the new command is introduced.

[编辑说明]:这是一个称为变量变量的概念,手册中有一些引入新命令的例子。

#5


4  

Here is a clean version of what you wanted:

这是你想要的干净版本:

class ClassName {
    public static function init(){       
        return (new ReflectionClass(get_called_class()))->newInstanceArgs(func_get_args());        
    }

    public static function initArray($array=[]){       
        return (new ReflectionClass(get_called_class()))->newInstanceArgs($array);        
    }

    public function __construct($arg1, $arg2, $arg3){
        ///construction code
    } 
}

Normal ugly method of creating a new object instance using new

使用new创建新对象实例的常规丑陋方法

$obj = new ClassName('arg1', 'arg2', 'arg3');
echo $obj->method1()->method2();

Static call using init instead of new

使用init而不是new的静态调用

echo ClassName::init('arg1', 'arg2', 'arg3')->method1()->method2();

Static call using initArray instead of new

使用initArray而不是new的静态调用

echo ClassName::initArray(['arg1', 'arg2', 'arg3'])->method1()->method2();

#6


0  

Based on @chris' answer( https://*.com/a/2550465/1806628 ), here is a usage of reflection classes:

根据@chris的回答(https://*.com/a/2550465/1806628),这里是反射类的用法:

abstract class A{
    // the constructor writes out the given parameters
    public function __construct(){
        var_dump(func_get_args());
    }

    public function copy(){
        // find our current class' name, __CLASS__ would return A
        $thisClass = get_class($this);
        $tmp = new ReflectionClass($thisClass);
        // pass all the parameters recieved to the new object
        $copy = $tmp->newInstanceArgs(func_get_args());

        return $copy;
    }
}

class B extends A{}

// create a new B object, with no parameters
$b = new B();

// create another b, but with other parameters
$c = $b->copy('the parameter of the copied B');

This is useful, if you want to make an object copy function in an ancestor class and don't know, whether child classes need parameters in the future, or not.

如果要在祖先类中创建对象复制函数并且不知道子类是否需要将来的参数,这很有用。

#1


20  

As of PHP 5.6, you can now achieve this with a single line of code by using the new Argument Unpacking operator (...).

从PHP 5.6开始,您现在可以使用新的Argument Unpacking运算符(...)通过一行代码实现此目的。

Here is a simple example.

这是一个简单的例子。

$className='Foo';
$args=['arg1','arg2','arg3'];

$newClassInstance=new $className(...$args);

See PHP Variable-length argument lists for more information.

有关更多信息,请参阅PHP可变长度参数列表。

#2


16  

Since some constructors may take a variable number of arguments, the following method should be used to accommodate it.

由于某些构造函数可能采用可变数量的参数,因此应使用以下方法来适应它。

$r = new ReflectionClass($strClassName);
$myInstance = $r->newInstanceArgs($arrayOfConstructorArgs);

For example, if your Car constructor took 3 args

例如,如果你的Car构造函数需要3个args

$carObj = new Car($color, $engine, $wheels);

Then

然后

$strClassName = 'Car';
$arrayOfConstructorArgs = array($color, $engine, $wheels);
$r = new ReflectionClass($strClassName);
$carObj = $r->newInstanceArgs($arrayOfConstructorArgs);

http://php.net/manual/en/class.reflectionclass.php
http://php.net/manual/en/reflectionclass.newinstanceargs.php

http://php.net/manual/en/class.reflectionclass.php http://php.net/manual/en/reflectionclass.newinstanceargs.php

#3


7  

In such cases i use factory-methods. they can be easily defined in abstract classes:

在这种情况下,我使用工厂方法。它们可以在抽象类中轻松定义:

class Foobar {

    public function __construct($foo, $bar) 
    {
        // do something
    }

    static public function factory($foo, $bar) 
    {
        return new self($foo, $bar);
    }
}

with this you can use call_user_func_array():

有了这个你可以使用call_user_func_array():

$my_foobar_obj = call_user_func_array('Foobar::factory', array($foo, $bar));

#4


5  

You can dynamically create an object as long as you know the class name:

只要知道类名,就可以动态创建对象:

$objName = 'myClass';
$test = new $objName($param);

You could easily define a __construct() function to take default arguments as well if that was a requirement of your construction logic.

如果这是构造逻辑的要求,您可以轻松定义__construct()函数以获取默认参数。

[Edit note]: This is a concept known as variable variables, and there's some examples in the manual where the new command is introduced.

[编辑说明]:这是一个称为变量变量的概念,手册中有一些引入新命令的例子。

#5


4  

Here is a clean version of what you wanted:

这是你想要的干净版本:

class ClassName {
    public static function init(){       
        return (new ReflectionClass(get_called_class()))->newInstanceArgs(func_get_args());        
    }

    public static function initArray($array=[]){       
        return (new ReflectionClass(get_called_class()))->newInstanceArgs($array);        
    }

    public function __construct($arg1, $arg2, $arg3){
        ///construction code
    } 
}

Normal ugly method of creating a new object instance using new

使用new创建新对象实例的常规丑陋方法

$obj = new ClassName('arg1', 'arg2', 'arg3');
echo $obj->method1()->method2();

Static call using init instead of new

使用init而不是new的静态调用

echo ClassName::init('arg1', 'arg2', 'arg3')->method1()->method2();

Static call using initArray instead of new

使用initArray而不是new的静态调用

echo ClassName::initArray(['arg1', 'arg2', 'arg3'])->method1()->method2();

#6


0  

Based on @chris' answer( https://*.com/a/2550465/1806628 ), here is a usage of reflection classes:

根据@chris的回答(https://*.com/a/2550465/1806628),这里是反射类的用法:

abstract class A{
    // the constructor writes out the given parameters
    public function __construct(){
        var_dump(func_get_args());
    }

    public function copy(){
        // find our current class' name, __CLASS__ would return A
        $thisClass = get_class($this);
        $tmp = new ReflectionClass($thisClass);
        // pass all the parameters recieved to the new object
        $copy = $tmp->newInstanceArgs(func_get_args());

        return $copy;
    }
}

class B extends A{}

// create a new B object, with no parameters
$b = new B();

// create another b, but with other parameters
$c = $b->copy('the parameter of the copied B');

This is useful, if you want to make an object copy function in an ancestor class and don't know, whether child classes need parameters in the future, or not.

如果要在祖先类中创建对象复制函数并且不知道子类是否需要将来的参数,这很有用。