2011-02-04 19 views
5

Pomimo dyskusji na ten temat, chciałbym sprawdzić na pewnym przykładzie, jakie byłoby najlepsze podejście.
Zamiast używać istniejących rozwiązań, stworzyłem własną warstwę utrwalania (tak jak wiele innych). Moje podejście jest tu również kwestią sporną.Php (eval vs call_user_func vs funkcje zmienne ...)

Dla każdej tabeli w db mam model klasy, która ma odpowiednie pobierające i ustawiające i niektóre obowiązkowe metody. Stworzyłem także tylko jedną ogólną klasę DAO, która obsługuje wszystkie typy obiektów modelu.
Tak więc, na przykład, aby zapisać dowolny obiekt modelu, tworzę instancję klasy genericDAO i metodę zapisu wywołania, którą przekazuję obiekt modelu jako atrybut. Problem polega na tym, że w klasie wykonawczej klasa genericDAO nie rozpoznaje otrzymanego obiektu modelu whitch i jakie istnieją w nim metody (pobierające i ustawiające), więc muszę wywołać metodę obowiązkowej metody klasy, która pobiera listę atrybutów jako wiele tablic ciągów.
Na przykład dla każdego atrybutu istnieje tablica (nazwa_główna_tabeli, nazwa_atrybutu, is_string).

Kiedy zadzwonić zapisać funkcję wygląda to tak:

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]).'();'); 
...

Obecnie używam eval na wykonanie tych metod, ale jak to jest dobrze znane eval jest bardzo powolna.
myślę, że zmiany w sposobie call_user_func
coś takiego:

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

Ale też nie ma innych rozwiązań. Mogę może użyć czegoś takiego

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

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

Jaki byłby najlepszy sposób?

Odpowiedz

8

Po pierwsze, nie ma potrzeby przekazywania referencji, jak robisz. Powinieneś give this a read spróbować zrozumieć, jak PHP obsługuje odniesienia do obiektów.

Tak więc public function save(&$VO) { powinien stać się public function save($VO) {.

Po drugie, nie ma potrzeby korzystania z eval (w rzeczywistości, lepiej nie ze względu na szybkość, możliwość debugowania itp.). Nie można śledzić połączenia w stosie, tak jak to możliwe, dynamicznego.

Po trzecie, call_user_func jest praktycznie bezużyteczne, ponieważ PHP obsługuje dynamiczne funkcje zmiennych. Zamiast call_user_func(array($obj, $method), $arg1), wystarczy zadzwonić pod numer $obj->$foo($arg1). Funkcja call_user_func_array jest nadal użyteczna, ponieważ obsługuje argumenty o zmiennej długości i obsługuje przekazywanie referencji.

Więc ostatecznie, ja proponuję to:

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

Zauważ, że nie ma potrzeby, aby zadzwonić method_exists, ponieważ może to być wymagalne i nie istnieje ze względu na wsparcie magiczne metody __get ...

+0

Myślę, że 'call_user_func()' jest wciąż jedynym sposobem wywołania anonimowej funkcji przechowywanej w zmiennej obiektowej: '$ o- > f = function() {}; 'próba zrobienia' $ o-> f() 'spowoduje, że' $ o nie zawiera metody o nazwie 'f'' ostrzeżenie. – Mchl

+0

@Mchl: '$ c = $ o-> f; $ c(); 'będzie działać. Możesz też zaimplementować magiczną metodę '__call', aby zrobić to za Ciebie. Ale nie * masz * używać 'call_user_func'. I o to chodzi w tym, co próbowałem powiedzieć. Nie robi nic, czego nie możesz zrobić w ojczystym języku ... To może być łatwiejsze do zrobienia i przeczytania, ale nie robi nic specjalnego ... – ircmaxell

+0

Ah tak. Zapomniałem o $ c = $ o-> f; $ c(); 'Masz rację. – Mchl

2

I normalnie używać:

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

Ale chyba nie jest to bardzo dobry powód, chciałbym tylko zwrócić key => value tablicę z getParamArray. I działaj na tym, zamiast korzystać z pobierających ...

+0

Tak, prawdopodobnie jest to szybsze, jeśli unika się używania getterów ... dopóki nie utworzą prywatnego modyfikatora dostępu :) – Aleksandar