# Magic getters/setters in PHP … Any comments/suggestions?

So, I'm playing around with PHP, trying to write a small ORM. Having worked with Magento quite a bit lately, I've fallen in love with the automagic getters/setters that Magento, I think, inherited from Zend.

For those, who've never seen it in action, this is what I'm talking about:

$my_object->setSomeProperty('foo');  just works, as does $my_object->getSomeProperty();


which obviously yields "foo".

Since I'm trying to implement an ORM, my goal is to provide the user with the ability to use generic functions on one hand, where

$orm_object->setSomeProperty('foo')  would map to $orm_object->set('some_property', 'foo') // set() would obviously be a generic part of the ORM


by convention. On the other hand, if the user wanted to handle some situations differently, he could do so by defining a more specifically named function.

class foo extends ORM {
function setSome($arg_1,$arg_2)
{
…
}
}


The above example call

$orm_object->setSomeProperty('foo')  would now be mapped to $orm_object->setSome('property', 'foo')


Alright, let's get to the point: Do you have any feedback on my implementation?

function __call($name,$arguments) {
if(preg_match('/([a-z]+)/', $name,$matches))
{
$action =$matches[0];
if(preg_match_all('/([A-Z]+)([^A-Z]+)/', $name,$matches))
{
$matches =$matches[0];
array_unshift(&$matches,$action);
for ($i = count($matches); $i > 0;$i--)
{
$potential_func_name = implode('', array_slice($matches, 0, $i)); if (method_exists($this, $potential_func_name)) {$arguments_rest = array_slice($matches,$i);
break; // found matching function!
}
}

// handle number of arguments now!
$reflector = new ReflectionClass($this);
$num_expected_params = count($reflector->getMethod($potential_func_name)->getParameters());$num_expected_params = $num_expected_params - count($arguments);

$params = array(); for ($i = $num_expected_params;$i > 1; $i--) {$params[] = strtolower(array_shift($arguments_rest)); }$last_var = '';
$i = 0; foreach($arguments_rest as $part) {$last_var .= strtolower($part);$i++;
if ($i != count($arguments_rest)) $last_var .= '_'; }$params[] = $last_var; if (count($arguments) == 1) {
$arguments = array_shift(&$arguments);
}

$params[] =$arguments;

return(call_user_func_array(array($this,$potential_func_name), $params)); } } }  - There are probably a lot of reasons I'm unaware of as a frontend guy to use this code, but I'm wondering why you would use this instead of existing PHP magic overloading? See php.net/language.oop5.overloading.php – Rene Geuze Oct 24 '12 at 10:39 ## 1 Answer This is how I would probably implement task similar to yours: class A { public function set($property, $value) { echo sprintf('setting %s = %s',$property, $value)."\n"; } public function setFirstName($value)
{
$this->set('first_name',$value);
}

public function __call($name,$arguments)
{
if (!preg_match('/^(get|set)(.+?)$/i',$name, $matches)) { throw new BadMethodCallException(sprintf('method %s doesn\'t exits',$name));
}

list(, $method,$property) = $matches;$property = preg_replace('/([a-z\d])([A-Z])/', '\\1_\\2', $property);$method   = strtolower($method); if ('set' ==$method) {
array_unshift($arguments, strtolower($property));
}

return call_user_func_array(array($this,$method), $arguments); } }$a = new A();
$a->setFirstName('John');$a->setLastName('McLane');


Output:

setting first_name = John

setting last_name = McLane

-