Как создать класс с заданным массивом аргументов, который будет отправлен конструктору? Что-то вроде:
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 Method и ознакомьтесь с этим примером.
Из Википедии:
Шаблон фабричного метода является объектно-ориентированным шаблоном проектирования. Как и другие шаблоны создания, речь идет о проблеме создания объектов (продуктов) без указания точного класса объекта, который будет создан.
Если вы не хотите использовать выделенный Factory для этого, вы можете поместить код Volker в функцию, например
/** * 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; }