Dynamic getter’s and setter’s in PHP


Anyone who has done almost any PHP that required your to make a class
of some sort probably also had to create getters and setters. If you happen
to have a lot of properties that need to have getters and setters it can become
bothersome, however using PHP’s __call magic method this can be cut down to
just a small snippet of code, here’s how.
PHP’s __call magic method allows method’s that do not exist in your class to be
called, so for instance let’s say you have the class.


<?php
	class Foo {
		public function Hello() {
			echo "Hello, world!";
		}
		
		public function __call($name, $args) {
			echo "Calling method {$name}";
		}
	}
?>

Now if you where to call Foo::Hello(); you would get “Hello, world!” printed
to your browser, however calling something like Foo::Bar(); would cause PHP
to send the method name and arguments to your __call method as your class
does not have an actual method name Bar. So how can we use this to our
advantage? Lets see.

I am creating a new project and I have this class which will have many properties,
some stored in an array some actual variables and I need to create getters and setters
for all of them, what to do. Well with the help of the __call magic method it is as easy
as this.


class Foo
{
    private $test;
    private $test2;
    private $bar;

    public function __construct()
    {
        $this->test = "";
        $this->test2 = "";
        $this->bar = array();
        $this->bar['str'] = " world!";
    }

    public function __call($name, $args)
    {
        if(preg_match("/get/i", $name))
        {
            //Set the entire method name to lowercase so we don't have to mess around with
            //anything incase camel case or C# like method names are being used.
            $name = strtolower($name);
            //Find the start and length of the get / set in the method.
            $pos = strpos($name, "get") + strlen("get");
            //Strip the get / set from the getter / setter method.
            $name = substr($name, $pos, strlen($name) - $pos);

            //Create a new reflection object from this class.
            $reflection = new ReflectionClass($this);
            $props = $reflection->getProperties(ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED);

            //Loop through all the properties that we found.
            foreach($props as $prop)
            {
                //Check if it is an array so we can search the keys in an array instead of the
                //name of the property.
                if(is_array($this-> {$prop->getName()}))
                {
                    //So it's an array, does our array contain a key with the name
                    //that we are looking for?
                    if(key_exists($name, $this-> {$prop->getName()}))
                        return $this-> {$prop->getName()} [$name];
                }
                //If it is not an array then does that name match the name we are looking for?
                else if($prop->getName() == $name)
                    return $this->$name;
            }
            return null;
        }
        //Do almost the same thing as in the get option get here but we will be setting a value
        //not retreving one.
        else if(preg_match("/set/i", $name))
        {
            $name = strtolower($name);
            $pos = strpos($name, "set") + strlen("set");
            $name = substr($name, $pos, strlen($name) - $pos);
            $value = "";

            //Make sure we actually have an argument in there.
            if(count($args) >= 1)
                $value = $args[0];

            $reflection = new ReflectionClass(__CLASS__);
            $props = $reflection->getProperties(ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED);

            foreach($props as $prop)
            {
                if(is_array($this-> {$prop->getName()}))
                {
                    if(key_exists($name, $this-> {$prop->getName()}))
                        $this-> {$prop->getName()} [$name] = $value;
                }
                else if($prop->getName() == $name)
                    $this->$name = $value;
            }
        }
    }
}

$foo = new Foo();
$foo->setTest("Hello,");
echo $foo->getTest(); //Prints "Hello,"
echo $foo->getStr(); //Prints " world!"

Advertisements

2 thoughts on “Dynamic getter’s and setter’s in PHP

  1. Thanks a lot,
    but I have a problem with that, I am trying to create a hierachy so I changed this line

    $reflection = new ReflectionClass(__CLASS__);

    to

    $reflection = new ReflectionClass($this);

    and I have this problem

    Fatal error: Cannot access private property FormGenerator::$inputClass

    in this Line

    if (is_array($this->{$prop->getName()})) {

    Can you help me please

  2. Is there a FormGenerator instance assigned to a variable, or is it the class you are trying to use the above code on?

    If you wish to email me I can try to help you get the issue resolved.
    You can email me at cborrow03 [at] gmail [dot] com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s