Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Как передать в конструктор массив параметров?


Автор: Чучмек 20.8.2013, 23:16
Как передать в конструктор  класса массив параметров?
Наподобие call_user_func_array.
Не охота через eval извращаться. 

Автор: ksnk 21.8.2013, 01:14
Цитата(Чучмек @  20.8.2013,  23:16 Найти цитируемый пост)
Как передать в конструктор  класса массив параметров?

А это не ответ на вопрос?  smile

Добавлено через 1 минуту и 20 секунд
В смысле - передавай ассоциативный массив и будет щасте, не?

Автор: Чучмек 21.8.2013, 01:31
Невкусно.

Автор: Arantir 21.8.2013, 02:03
И откуда у людей вечно берутся подобные проблемы? =)

Цитата(Чучмек @  20.8.2013,  22:16 Найти цитируемый пост)
Наподобие call_user_func_array.

Хм... Может это call_user_func_array?  smile 

Цитата(Чучмек @  21.8.2013,  00:31 Найти цитируемый пост)
Невкусно.
О, мсье знает толк в извращениях  © Из анекдота

http://www.php.net/manual/en/book.reflection.php

ReflectionFunction::__construct ( mixed $name )
ReflectionFunction::invokeArgs ( array $args )

Но reflection - это усегда минус в перфоменсе...

Автор: Чучмек 21.8.2013, 03:08
Arantir, спасибо. 
Код

class myClass
  {
  var $args;
  public function __construct()
    {
    $this->args = func_get_args();
    }
  public function show()
    {
    var_dump($this->args);
    }
  }

$m = array(1,2,3);  
$myClassR = new ReflectionClass('myClass');
$myObj = $myClassR->newInstanceArgs($m);

$myObj->show();


Автор: ksnk 21.8.2013, 07:02
Код

class myClass
  {
  var $args;
  public function __construct($args)
    {
    $this->args =$args;
    }
  public function show()
    {
    var_dump($this->args);
    }
  }
$m = array(1,2,3);  
$myObj= new myClass($m);
$myObj->show();


C рефлекцией точно-точно вкуснее. Очевидно же!  smile 

Класс же явно самодельный, почему бы его не откорректировать?

Автор: Чучмек 21.8.2013, 16:55
Цитата(ksnk @  21.8.2013,  07:02 Найти цитируемый пост)
C рефлекцией точно-точно вкуснее. Очевидно же!  smile 

Что я на этом теряю?

Цитата(ksnk @  21.8.2013,  07:02 Найти цитируемый пост)
Класс же явно самодельный, почему бы его не откорректировать?

Может и так. 

Автор: ksnk 21.8.2013, 17:43
Цитата(Чучмек @  21.8.2013,  16:55 Найти цитируемый пост)
Что я на этом теряю?

Эффективность. Просто выполни достаточное количество инициализаций в первом случае и во втором. Оплучится проигрыш во времени исполнения, хотя и не  катастрофический, но на большом количестве повторений - заметный.

Юзабилити. Для работы с таким классом ОБЯЗАТЕЛЬНО нужно будет использовать рефлекшн, а это отпугивает нормальных разработчиков  smile 

Автор: Sanchezzz 21.8.2013, 18:11
Иногда без рефлекшина и не обойтись) 

Автор: ksnk 21.8.2013, 21:32
Sanchezzz, Когда, например? Я могу себе представить только тестирование, документирование, диагностика отладочных и ошибочных сообщений. http://forum.vingrad.ru/forum/topic-370606.html я пытался прикрутить рефлекшн для конструирования админки приложения, imho, удачно. Вот только причесать немного код.
То есть чисто служебные надобности. 

Автор: Sanchezzz 21.8.2013, 22:36
Я читал этот топик)
Например для получения пути вызванного класса отнаследованного от Modules

Код

class Module extends ExtendBaseClass { 

    public
        // Путь к переложению или путь к модулю. 
        $basePath,      
        // Добавочные пути к baseApp 
        $pathController = '/controllers',    
        $pathModule     = '/modules',
        // Имя модуля
        $name;          
    
    public function __construct($config = array()){
        $this->setBasePath($config['basePath']);
    }
    
    /*
    * Функция инициализации для модуля, вызывается при первом подключении к модулю. 
    */
    public function init(){
    
    }
    
    /**
     * Получить basePath
     * basePath используется для запуска контролеров и модулей
     **/
    public function getBasePath(){
        $path = $this->basePath;
        if(empty($path)) 
            throw new CException('В конфигурации переложения не указан параметр basePath');
        return $path;
    }
    
    /**
     * Установить basePath
     **/
    public function setBasePath($path){
        $this->basePath = $path;
    }
    
    /**
     * Запустить указанный контролер 
     * @param $name    Имя контролера
     * @param $action  Имя запускаемого метода 
     * @param $params  Параметры для контролера
     * @see 
     * Можно запустить контроллер из корня для этого в имени контроллера, нужно указать //
     * Каждый / - это уровень директории назад 
    **/
    public function runController($name , $action = 'index' , $params = null ){    
        $result = false;
        $oldBasePath     = $this->getBasePath();
        $name_controller = trim($name,'/');
        $sub_path = str_replace($name_controller , '',  implode('../', explode('/', $name)));
        $baseAppPath  = $this->getBasePath() ."/" . $sub_path ;
        $this->setBasePath($baseAppPath);
        $path  =  $baseAppPath . trim( $this->pathController ,'/' )
            . "/". $name_controller .".php";
            
        if(is_readable($path)){

            include_once $path;            
            $class = $name_controller."_controller";
            if(class_exists($class,false)){            
                $controller = new $class;
                $operation =  (!empty($this->name) ? $this->name . '::' : '')
                              . implode('->',array( $name , $action ));
                              
                $controller->setOperation( $operation );
                $controller->param = $params;
                // Выполнили до
                $controller->before();
                if(method_exists( $controller  , 'action'.$action)){ 
                    $controller->{'action'.$action}();
                }else $result = false;
                // Выполнили после    
                $controller->after();    
                $result = true;    
            }
        }
        $this->setBasePath($oldBasePath);
        return $result;
    }
    
     /*
     * Запуск модуля
     * @param  $name  имя модуля
     * @param  $controller  Контроллер который запускать
     * @param  $action      Метод который нужно запустить
     * @param  $params      Параметры     
     **/
    public function runModule($name , $controller = 'default_main' , $action = 'index', $params = array() ){
        $baseAppPath     = $this->getBasePath();
        // Путь к модулю
        $path = $baseAppPath."/".trim( $this->pathModule ,'/' )."/".$name."/".$name.".php";
        // Список модулей в конфиге 
        $arrModules = Config::get('modules');
        if(is_readable($path) && in_array($name, $arrModules)){
            include_once $path;
            $class = $name."_module";    
            if(class_exists($class,false)){
                // Зададим путь к модулю
                $ref = new ReflectionClass($class);    
                $path = pathinfo( $ref->getFileName(), PATHINFO_DIRNAME);
                $module = new $class( array( 
                    'basePath'=> $path, 
                ));
                
                $module->init();
                // Регистрируем путь для моделей
                Autoload::addPath($path . DIRECTORY_SEPARATOR . "models" );
                // Запуск контролера в модуле
                if(!empty($controller)){
                    $module->name = $name;
                    return $module->runController($controller , $action, $params);
                }        
                return true;
            }    
        }
        return false;
    }
}

Модуль 
Код

classs News extends Module {} 
 
Можно было например заставить пользователя прописать  в  модуле News  в методе init  вот такую штуку 
Код

$this->basePath = dirname(__FILE__);

Но лишние телодвижения, я не люблю делать

Автор: ksnk 22.8.2013, 00:03
Как то странно  smile сначала вычисляется путь к модулю, инклюдится сам модуль
Код

// Путь к модулю
$path = $baseAppPath."/".trim( $this->pathModule ,'/' )."/".$name."/".$name.".php";
...
include_once $path;


А потом этот же путь, с приписанным к нему каталогом добавляем путь поиска автолода? 
Код

Autoload::addPath($path . DIRECTORY_SEPARATOR . "models" );

При чем тут рефлекшн? Все пути вычисляются статически. Не?

Автор: Sanchezzz 22.8.2013, 10:02
Ага чет я даже и сам не заметил, что можно по логике и без reflection решить, извиняюсь за смуту.  smile 








Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)