Как я могу создать класс с данным массивом аргументов, которые будут отправлены конструктору? Что-то вроде:
class a {
var $args = false;
function a() {$this->args = func_get_args();}
}
$a = call_user_func_array('new a',array(1,2,3));
print_r($a->args);
Идеально это должно работать, без модификации к классу, и в PHP4 и в PHP5. Какие-либо идеи?
ReflectionClass: newInstance () (или newInstanceArgs ()) давайте сделаем это.
например,
class Foo {
public function __construct() {
$p = func_get_args();
echo 'Foo::__construct(', join(',', $p), ') invoked';
}
}
$rc = new ReflectionClass('Foo');
$foo = $rc->newInstanceArgs( array(1,2,3,4,5) );
edit: без ReflectionClass и, вероятно, совместимый с php4 (извините, нет php4 в рука прямо сейчас)
class Foo {
public function __construct() {
$p = func_get_args();
echo 'Foo::__construct(', join(',', $p), ') invoked';
}
}
$class = 'Foo';
$rc = new $class(1,2,3,4);
сравнение скорости: Поскольку скорость отражения уже упоминалась, вот небольшой (синтетический) тест
define('ITERATIONS', 100000);
class Foo {
protected $something;
public function __construct() {
$p = func_get_args();
$this->something = 'Foo::__construct('.join(',', $p).')';
}
}
$rcStatic=new ReflectionClass('Foo');
$fns = array(
'direct new'=>function() { $obj = new Foo(1,2,3,4); },
'indirect new'=>function() { $class='Foo'; $obj = new $class(1,2,3,4); },
'reflection'=>function() { $rc=new ReflectionClass('Foo'); $obj = $rc->newInstanceArgs( array(1,2,3,4) ); },
'reflection cached'=>function() use ($rcStatic) { $obj = $rcStatic->newInstanceArgs( array(1,2,3,4) ); },
);
sleep(1);
foreach($fns as $name=>$f) {
$start = microtime(true);
for($i=0; $i<ITERATIONS; $i++) {
$f();
}
$end = microtime(true);
echo $name, ': ', $end-$start, "\n";
sleep(1);
}
, который распечатывается на моем (не таком быстром) блокноте
direct new: 0.71329689025879
indirect new: 0.75944685935974
reflection: 1.3510940074921
reflection cached: 1.0181720256805
Разве это не плохо, не так ли?
Взгляните на шаблон фабричного метода и посмотрите этот пример
Из Википедии:
Шаблон фабричного метода - это объектно-ориентированный шаблон проектирования. подобно другие творческие модели, это касается с проблемой создания объектов (продукты) без указания точный класс объекта, который будет создан.
Если вы не хотите использовать для этого выделенную Factory, вы все равно можете обернуть код Волкера в функцию, например
/**
* Creates a new object instance
*
* This method creates a new object instance from from the passed $className
* and $arguments. The second param $arguments is optional.
*
* @param String $className class to instantiate
* @param Array $arguments arguments required by $className's constructor
* @return Mixed instance of $className
*/
function createInstance($className, array $arguments = array())
{
if(class_exists($className)) {
return call_user_func_array(array(
new ReflectionClass($className), 'newInstance'),
$arguments);
}
return false;
}