Собственно проблема перекочевала из темы http://php.ru/forum/viewtopic.php?t=7759 Там обсуждалась такая весчь: PHP: class MyClass { // конструктор function MyClass() { echo get_class($this); } } function &NewObject($class) { return new $class(); } $obj = NewObject('MyClass'); Т.е., функция NewObject() создает экземпляр класса MyClass, при создании естественно вызывается метод-конструктор если он описан в классе! Так вот проблема в следующем, частенько при создании экземпляра объекта в метод-конструктор необходимо передать некое кол-во параметров, а выше описанная функция NewObject этого делать не умеет! Переписав вышеприведенный код таким образом: PHP: class MyClass { // конструктор function MyClass($arg1, $arg2) { var_dump($arg1); var_dump($arg2); } } function &NewObject($class, $args) { $args_str = implode(',', $args); eval("return new $class($args_str);"); } $obj = NewObject('MyClass', array('text', 1)); мы получаем возможность вместе с названием класса передавать также и массив параметров в функцию NewObject - которая в свою очередь воткнет эти параметры как значения аргументов конструктора инициализируемого класса! Однако такое решение, да и еще с применением eval() меня не совсем устраивает! Подскажите пожалуйста алтернативное решение проблемы но только без использования eval()
ну и чего ты так эвала боишься? evil напоминает? а вообще, я сторонник отделения создания объекта от его инициализации параметрами: $var= new Class(); $var->InitType1( 1,2,3 ); $var2= new Class(); $var2->InitType2( array( 1,2,3 ) ); и _опциональная_ поддержка дефолтного инициализатора: $var3= new Class( 1,2,3 );
и что мне это дает??? можно конечно сделать так: PHP: class MyClass { // конструктор function MyClass($arg1, $arg2) { var_dump($arg1); var_dump($arg2); } } function &NewObject($class, $args) { return call_user_func_array(array($class, $class), $args); } $args = array('text', 1024); $obj = NewObject('MyClass', $args); но NewObject() ничего не вернет! и var_dump($obj) будет равен NULL Хотя самое интересное, что конструктор MyClass() сработает. И сработает непонятно как, ведь с одной стороны функции MyClass() несуществует, но с другой стороны как можно вызвать метод без создания экземпляра-объекта??
Сорри, немного ошибся, call_user_func_array здесь не совсем подходит. Конечно, можно было бы ее использовать, но для этого придется в каждом классе создавать статический метод, возвращающий экземпляр объекта... В общем, геморрой Если для вас важно именно устранение eval'а, то можно воспользоваться runtime-created функциями: PHP: <?php function &NewObject($class, $args) { $caller = create_function('', "return new $class(".implode(',',$args).");"); return $caller(); } ?> но учтите, что этот способ работает несколько медленнее, чем eval. Других решений этой задачи я уже не вижу.
ну передавай массив, кто мешает? но я бы не передавал параметры именно в конструктор а вызывал соотв. методы уже после инициализации экземпляра.
Мне никто а у автора топика именно такая проблема и возникла. Я поэтому и написал, что других решений нет, только eval или create_function.
enshtein $params = func_get_args(); хоть сто параметров передавай. # function &NewObject($class, $args) { # return call_user_func_array(array($class, $class), $args); # } учи матчасть. юзай __set, помотри zf
enshtein PHP: <? class MyClass { function MyClass (){ //... } function Init ($a, $b) { //... } } $ClassName = "MyClass"; $instance = new $ClassName; $instance->Init ($a, $b) ?>
Ребята, вы что-то тупите.... PHP: <?php class Core { function Core($param){ } } $class = 'Co'.'re'; $object = new $class($some_param); // идентично ниже написанному $object = new Core($some_param); KISS - Keep It Simple Stupid Вы как всегда превратили простейшую и давно решенную проблему в слона.
да мы то не тупим.... это просто ты не понял всей проблемы, да конечно в твоем примере с одним параметров все просто, можно переписав на мой пример получить следующее: PHP: class MyClass { // конструктор function MyClass($arg1) { echo $arg1; } } function &NewObject($class, $args) { return new $class($args); } $obj = NewObject('MyClass', 'параметр'); Только вот не задумывался ли ты что аргументов (параметров) для конструктора может быть не один, а произвольное кол-во! К примеру: PHP: class MyClass { // конструктор function MyClass($arg1, $arg2) { var_dump($arg1); var_dump($arg2); } } function &NewObject($class, $args) { return new $class($args); } $obj = NewObject('MyClass', 'параметр1', 'параметр2');
нет, мы тупим Да, это уже другая задача. При использовании метода инициализации объекта у тебя она так же возникнет. Подумай сам как лучше сделать.
блиннн, но PHP: $object = new $class($some_param); здесь $some_param - один параметр, а если надо передавать через функцию несколько!
блиннн... ну а как же ты это передавать то в функцию будешь??? а??? вот жишь я приводил пример: PHP: class MyClass { // конструктор function MyClass($arg1, $arg2=0, $ar3=0) { var_dump($arg1); var_dump($arg2); var_dump($arg3); } } function &NewObject($class) { return new $class(>>>>>>ЗДЕСЬ МОЖЕТ БЫТЬ ПРОИЗВОЛЬНОЕ КОЛ-ВО ПАРАМЕТРОВ А МОЖЕТ И ВООБЩЕ НЕ БЫТЬ! ВОПРОС КАК СЮДА ПЕРЕДАТЬ ИХ ЧЕРЕЗ ФУНКЦИЮ NewObject??????<<<<<<); } $obj = NewObject('MyClass', 'параметр1'); $obj1 = NewObject('MyClass', 'параметр1', 'параметр2'); $obj2 = NewObject('MyClass', 'параметр1', 'параметр2', 'параметр3');
Вариант 1: Передавать массив. PHP: <? $className = 'CMyClass'; $params = array (); $params[0] = 1; $params[1] = 2; $params['DB'] = &$ExpGlobal['DB']; //=) $Obj = NewObject ($className, $params); function &NewObject ($className, $params) { return new $className ($params); } class CMyClass { var $data = array (); var $db; function CMyClass(&$params) { $this->data[0] = $params[0]; $this->data[1] = $params[1]; $this->db = &$params['DB']; } } ?> Вариант 2: Использовать метод инициализации. Но тут с таким же успехом можно инициализацию заменить на $class(...) PHP: <? class Instance { function Init (){ } } class CMyClass extends Instance { function get_result (){ //.... } } class CMyClass2 extends Instance { var $a; var $b; function Init ($a, $b){ $this->a = $a; $this->b = $b; } } function &NewObject ($className){ $arg_list = func_get_args(); $obj = new $class; switch ($className) //точно так же можно сделать new $class. Плюс в том что не надо тянуть лишний метод { case 'CMyClass': $obj->Init(); break; case 'CMyClass2': $obj->Init($arg_list[1], $arg_list[2]); break; } return $obj; } $a = NewObject('MyClass'); $b = NewObject('MyClass2', 1, 2); ?> Вариант 3: ... предлагайте
да видно я всеже остановлюсь на преусловатом eval'e отчего бежал к тому и прибежал PHP: class MyClass { // конструктор function MyClass($arg1, $arg2) { var_dump($arg1); var_dump($arg2); } } function &NewObject($class, $args) { $args_str = implode(',', $args); eval("return new $class($args_str);"); } $obj = NewObject('MyClass', array('text', 1));