Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Php (eval vs call_user_func vs variable functions ...)

Tags:

php

Even though there's some discussions regarding this issue I wanted to check on certain example what would be the best approach.
Instead of using existing solutions I created my own persistence layer (like many do) So my approach is also in question here.

For every table in db I have model class that has appropriate getters and setters and some mandatory methods. I also created only one generic DAO class that handles all types of model objects.
So, for example to save any model object I instantiate genericDAO class and call save method that I pass model object as attribute. Problem is that in runtime genericDAO class doesn't know whitch model object it gets and what methods (getters and setters) exist in it, so I need to call mandatory model class method that retrieves list of attributes as multiple string array.
For example for every attribute there's array(table_column_name,attribute_name,is_string).

When I call save function it looks like this:

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

Currently I'm using eval to execute those methods, but as it is well known eval is very slow.
I'm thinking of changing that into call_user_func method
Something like:

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

But also there's other solutions. I can maybe use something like this

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

What would be the best way?

like image 347
Aleksandar Avatar asked Feb 04 '11 16:02

Aleksandar


Video Answer


2 Answers

First of all, there's no need to pass references like you are doing. You should give this a read to try to understand how PHP handles object references.

So public function save(&$VO) { should become public function save($VO) {.

Second, there is no need to use eval (in fact, it's better not to because of speed, debugability, etc). You can't stack-trace an eval call like you can a dynamic one.

Third, call_user_func is all but useless since PHP supports dynamic variable functions. Instead of call_user_func(array($obj, $method), $arg1), just call $obj->$foo($arg1). The call_user_func_array function is still useful since it supports variable length arguments and supports passing references.

So, ultimately, I would suggest this:

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

Note that there's no need to call method_exists, since it may be callable and not exist due to __get magic method support...

like image 114
ircmaxell Avatar answered Nov 14 '22 22:11

ircmaxell


I normally would use:

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

But unless there is a very good reason i would just return a key => value array from getParamArray. And operate on that instead of using the getters...

like image 43
prodigitalson Avatar answered Nov 14 '22 21:11

prodigitalson