PHP passing parameters while creating new object, call_user_func_array for objects
I would like to dynamically create a PHP object, and parameters would be optional.
For example, instead of doing this:
$test = new Obj($param);
I would like to do something like this (create new ob i开发者_如何学JAVAs fictional):
$test = create_new_obj('Obj', $param);
Is there such function in php? Something similar to call_user_func_array, but for object instead.
As of PHP 5.6, you can now achieve this with a single line of code by using the new Argument Unpacking operator (...).
Here is a simple example.
$className='Foo';
$args=['arg1','arg2','arg3'];
$newClassInstance=new $className(...$args);
See PHP Variable-length argument lists for more information.
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
$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
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()
:
$my_foobar_obj = call_user_func_array('Foobar::factory', array($foo, $bar));
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.
[Edit note]: This is a concept known as variable variables, and there's some examples in the manual where the new command is introduced.
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
$obj = new ClassName('arg1', 'arg2', 'arg3');
echo $obj->method1()->method2();
Static call using init instead of new
echo ClassName::init('arg1', 'arg2', 'arg3')->method1()->method2();
Static call using initArray instead of new
echo ClassName::initArray(['arg1', 'arg2', 'arg3'])->method1()->method2();
Based on @chris' answer( https://stackoverflow.com/a/2550465/1806628 ), here is a usage of reflection classes:
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.
精彩评论