2011-02-04 2 views
5

Несмотря на то, что есть некоторые дискуссии по этой проблеме, я хотел бы проверить на определенном примере, какой будет лучший подход.
Вместо того, чтобы использовать существующие решения, я создал свой собственный уровень персистентности (как и многие другие). Итак, мой подход также под вопросом.Php (eval vs call_user_func vs variable functions ...)

Для каждой таблицы в db у меня есть класс модели, который имеет соответствующие геттеры и сеттеры и некоторые обязательные методы. Я также создал только один общий класс DAO, который обрабатывает все типы объектов модели.
Так, например, чтобы сохранить любой объект модели, я создаю экземпляр класса genericDAO и метод сохранения вызова, который передаю объект модели как атрибут. Проблема заключается в том, что в среде выполнения genericDAO класс не знает объект модели whitch, который он получает, и какие методы (геттеры и сеттеры) существуют в нем, поэтому мне нужно вызвать метод обязательной модели модели, который извлекает список атрибутов в виде нескольких строковых массивов.
Например, для каждого атрибута есть массив (table_column_name, attribute_name, is_string).

Когда я вызываю функцию сохранения она выглядит следующим образом:

public function save(&$VO) { 
$paramArray = $VO->getParamArray();//get array of attributes 
$paramIdArray = $paramArray[0]; //first attribute is always id 
/*create and execute getId() and store value into $void to check if it's save or update*/ 
eval('$voId = $VO->get'.ucfirst($paramIdArray[1]).'();'); 
...

В настоящее время я использую Eval для выполнения этих методов, но, как это хорошо известно Eval очень медленно.
Я имею в виду изменения, что в методе call_user_func
что-то вроде:

$voId = call_user_func(array($VO, 'get'.ucfirst($paramIdArray[1]))); 

Но также есть и другие решения. Я, возможно, использовать что-то вроде этого

$method = 'get'.ucfirst($paramIdArray[1])); 
$voId = $VO->$method(); 
или еще

$method = 'get'.ucfirst($paramIdArray[1])); 
$voId = $VO->{$method}(); 

Что бы быть лучшим способом?

ответ

8

Прежде всего, вам не нужно передавать такие ссылки, как вы. Вы должны give this a read попытаться понять, как PHP обрабатывает ссылки на объекты.

Таким образом, public function save(&$VO) { должно стать public function save($VO) {.

Во-вторых, нет необходимости использовать eval (на самом деле, это лучше не из-за скорости, отладки и т. Д.). Вы не можете трассировать трассировку вызова eval, как вы можете использовать динамический.

В-третьих, call_user_func практически бесполезен, поскольку PHP поддерживает функции динамической переменной. Вместо call_user_func(array($obj, $method), $arg1) позвоните по номеру $obj->$foo($arg1). Функция call_user_func_array по-прежнему полезна, поскольку она поддерживает аргументы переменной длины и поддерживает передачу ссылок.

Таким образом, в конечном счете, я хотел бы предложить следующее:

$method = 'get' . ucfirst($paramIdArray[1]); 
$voId = $VO->$method(); 

Обратите внимание, что нет необходимости вызывать method_exists, так как это может быть отозвано и не существует из-за __get волшебной поддержки методы ...

+0

Я думаю, что 'call_user_func()' все еще единственный способ вызвать анонимную функцию, хранящуюся в переменной объекта: '$ o- > f = function() {}; 'попытка сделать' $ o-> f() 'приведет к тому, что' $ o не имеет метода с именем 'f'' warning. – Mchl

+0

@Mchl: '$ c = $ o-> f; $ c(); 'будет работать. Или вы можете реализовать магический метод '__call', чтобы сделать это за вас. Но вы не имеете * использовать 'call_user_func'. И в этом смысл того, что я пытался сказать. Это не делает ничего, что вы не можете сделать на родном языке ... Это может быть проще сделать и прочитать, но это не делает ничего особенного ... – ircmaxell

+0

Ах да. Забыл о '$ c = $ o-> f; $ c(); ', вы правы в этом. – Mchl

2

Я обычно использовал бы:

$method = 'get'.ucfirst($attribute); 
if(method_exists($obj, $method){ 
    $obj->$method(); 
} 

Но если не очень хорошая причина, я бы просто вернуть key => value массив из getParamArray. И работайте над этим, вместо использования геттеров ...

+0

Да, это, вероятно, быстрее, если вы избегаете использования геттеров ... пока они не создадут модификатор частного доступа :) – Aleksandar