2011-02-04 20 views
5

A pesar de que hay algunas discusiones sobre este tema, quería comprobar en cierto ejemplo cuál sería el mejor enfoque.
En lugar de usar las soluciones existentes creé mi propia capa de persistencia (como muchos lo hacen) Así que mi enfoque también está en cuestión aquí.Php (eval vs call_user_func vs funciones variables ...)

Para cada tabla en db tengo la clase de modelo que tiene getters y setters apropiados y algunos métodos obligatorios. También creé solo una clase DAO genérica que maneja todos los tipos de objetos modelo.
Así que, por ejemplo, para guardar cualquier objeto de modelo, ejemplifico la clase genericDAO y llamo al método save que paso el modelo de objeto como atributo. El problema es que en el tiempo de ejecución la clase genericDAO no sabe qué objeto de modelo obtiene y qué métodos (getters y setters) existen en él, así que debo llamar al método de clase de modelo obligatorio que recupera la lista de atributos como una matriz de múltiples cadenas.
Por ejemplo, para cada atributo hay una matriz (table_column_name, attribute_name, is_string).

Cuando llamo a la función de ahorro se ve así:

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

Actualmente estoy usando eval para ejecutar esos métodos, pero eval como es bien sabido es muy lento.
Estoy pensando en cambiar eso en el método call_user_func
Algo así como:

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

Pero también hay otras soluciones. tal vez pueda usar algo como esto o de lo contrario

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

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

¿Cuál sería la mejor manera?

Respuesta

8

Antes que nada, no es necesario pasar referencias como las que está haciendo. Debería give this a read para tratar de entender cómo maneja PHP las referencias a objetos.

Entonces public function save(&$VO) { debería convertirse en public function save($VO) {.

En segundo lugar, no es necesario utilizar eval (de hecho, es mejor no hacerlo debido a la velocidad, la capacidad de resolución, etc.). No se puede apilar-rastrear una llamada eval como puede hacerlo una dinámica.

En tercer lugar, call_user_func es casi inútil ya que PHP admite funciones variables dinámicas. En lugar de call_user_func(array($obj, $method), $arg1), simplemente llame al $obj->$foo($arg1). La función call_user_func_array sigue siendo útil ya que admite argumentos de longitud variable y admite referencias de paso.

Por lo tanto, en última instancia, sugeriría esto:

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

Tenga en cuenta que no hay necesidad de llamar a method_exists, ya que puede ser exigible y no existir debido a __get apoyo método mágico ...

+0

Creo que 'call_user_func()' sigue siendo la única forma de llamar a una función anónima almacenada en la variable de objeto: '$ o- > f = function() {}; 'tratando de hacer' $ o-> f() 'dará como resultado' $ o no tiene un método llamado 'f'' warning. – Mchl

+0

@Mchl: '$ c = $ o-> f; $ c(); 'funcionará. O puede implementar un método mágico '__call' para hacerlo por usted. Pero no * tiene * que usar 'call_user_func'. Y ese es el punto de lo que estaba tratando de decir. No hace nada que no puedas hacer en tu lengua materna ... Puede ser más fácil de hacer y leer, pero no está haciendo nada especial ... – ircmaxell

+0

Ah sí. Olvidé de '$ c = $ o-> f; $ c(); ', tienes razón sobre eso. – Mchl

2

que normalmente usaría:

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

Pero a menos que haya una muy buena razón por la que acaba de devolver una matriz de key => valuegetParamArray. Y opere en eso en lugar de usar los getters ...

+0

Sí, probablemente sea más rápido si evito usar getters ... hasta que creen el modificador de acceso privado :) – Aleksandar