2

I recently studied magic methods, __get and __set, and was wondering how to actually set and get multiple properties in the class.

I know it works perfectly with only one variable or array, but I'm not sure about accessing multiple variables.

Is there anyone who could explain this to me?

class myMagic2 {
    public $data;
    public $name;
    public $age;

    public function __set($item, $value) {
        $this->item = $value;
    }

    public function __get($item){
        return $this->item;
    }
}

Is there a way to access all variables ($data, $name, $age)?

3
  • you mean get all those public vars in a single call? php.net/get_object_vars? Commented Jul 17, 2013 at 15:33
  • $this->$item not $this->item and all your problems will go away :) also, maybe a property_exists() in your __get/__set (that is if i understand your problem of course). Commented Jul 17, 2013 at 15:33
  • @Twisted1919 you are totally right. there was a typo I coundn't find out. Thanks for helping me out Commented Nov 8, 2013 at 16:10

2 Answers 2

3

When i work at projects i always have these methods:

public function __set($name, $value) 
{
    //see if there exists a extra setter method: setName()
    $method = 'set' . ucfirst($name);
    if(!method_exists($this, $method))
    {
        //if there is no setter, receive all public/protected vars and set the correct one if found
        $vars = $this->vars;
        if(array_search("_" . $name, $vars) !== FALSE)
            $this->{"_" . $name} = $value;
    } else
        $this->$method($value); //call the setter with the value
}

public function __get($name) 
{
    //see if there is an extra getter method: getName()
    $method = 'get' . ucfirst($name);
    if(!method_exists($this, $method)) 
    {
        //if there is no getter, receive all public/protected vars and return the correct one if found
        $vars = $this->vars;
        if(array_search("_" . $name, $vars) !== FALSE)
            return $this->{"_" . $name};
    } else
        return $this->$method(); //call the getter
    return null;
}

public function getVars()
{
    if(!$this->_vars)
    {
        $reflect = new ReflectionClass($this);
        $this->_vars = array();
        foreach($reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED) as $var)
        {
            $this->_vars[] = $var->name;
        }
    }
    return $this->_vars;
}

So with them i give myself the freedom to create extra setter/getter for properties if i want to manipulate them before writing/returning. If no setter/getter exists for the property it falls back to the property itself. With the method getVars() you receive all public and protected properties from the class.

My class properties are always defined with an underscorce so you should probably change that.

Sign up to request clarification or add additional context in comments.

Comments

0

You could follow this pattern.

Note: in the example in the post the magic methods would not have been called for $obj->data, $obj->name, or $obj->age because these values where already accessible as a public property. I changed them to be protected and altered the name to hide them.

<?php
class myMagic2{
    protected $_data;
    protected $_name;
    protected $_age;

    public function __set($item, $value){
        switch($item){
            case "data":
                $this->_data = $value;
                break;
            case "name":
                $this->_name = $value;
                break;
            case "age":
                $this->_age = $value;
                break;
            default:
                throw new Exception("Property $name does not exist.");

        }

    }

    public function __get($item){
        switch($item){
            case "data":
                return $this->_data;
                break;
            case "name":
                return $this->_name;
                break;
            case "age":
                return $this->_age;
                break;
            default:
                throw new Exception("Property $name does not exist.");
                break;

        }
    }
}

Normally you would do a little more then use the magic methods as a proxy to set and get classes properties. You would so validation or filtering or in some other way augmenting the operation. If you are just going to get or set a property you might as well just make the properties public and forgo using the magic methods.

3 Comments

is there a reason why he wouldn't do something like: setter: if (property_exists($this, $name)) { $this->$name = $value; } and getter: if(property_exists($this, $name)) { return $this->$name; } ? Pure curiosity.
No reason at all ... this is just the most straight forward implementation I could think of.
@Twisted1919 This is more academic then anything. If you are just using it to proxy get and set to properties you might as well just make the properties public and drop the magic methods.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.