0
votes

Assume we have this code:

class SomeClass{

    private $somePrivateField;


    public function __get($name){
        $function = "get".ucfirst($name);
        return $function;
    }

     public function __set($name,$value){
        $function = "set".ucfirst($name);
        return $function($value);
    }

    public function __call($name, $arguments) {
        //if function being called is getSomething
        //getThat private/protected field if exists and return
        //if not raise exception

        // similar for setSomething...
    }

}

This is a passage from some tutorial:

The __get() method accepts an argument that represents the name of the property being set. In the case of $obj->property, the argument will be property.

Our __get() method then converts this to getProperty, which matches the pattern we defined in the __call() method. What this means is that $obj->property will first try to set a public property with the same name, then go to __get(), then try to call the public method setProperty(), then go to __call(), and finally set the protected $_property.

So when I say somewhere in my code

$obj->property

I can understand it tried to access the public field first.. Why does it go to __get() first? Why not __set() ? Why does it go to __set() then?

Can someone please explain? Thanks...

1
The tutorial makes no sense, and neither does the code. You should try reading the documentation.Sammitch
What is wrong with the code? @SammitchKoray Tugay

1 Answers

1
votes
  • __get() will only ever return a string comprising the name of a function that probably doesn't exist.
  • __set() actually calls the function whose name it constructs, but I'm having trouble determining why because...
  • __call() seemingly has to determine if the function it's calling is actually a "setter" or "getter" function, which is the entire point of __get() and __set() in the first place.
  • $obj->property is a non-sensical fragment of code that does not actually do anything on it's own.
// assuming $obj->property is declared as private, or does not exist in the class.

$var = $obj->property; // invokes __get('property')

$obj->property = $var; // invokes __set('property', $var)

$obj->someFunction($var1, $var2, ...);
// invokes __call('someFunction', array($var1, $var2, ...)), but only if
// the specified function is private, or otherwise does not exist.

To re-write the example code so that it makes some semblance of sense:

class SomeClass{

    private $somePrivateField;

    public function __get($name){
        if( isset($this->$name) ) {
            return $this->$name;
        } else {
            Throw new Exception("Object property $name does not exist.");
        }
    }

     public function __set($name,$value){
        if( isset($this->$name) ) {
            $this->$name = $value;
        } else {
            Throw new Exception("Object property $name does not exist.");
        }
    }
}
$obj = new SomeClass();
$obj->somePrivateField = $var; // uses __set()
$var = $obj->somePrivateField; // uses __get()

Using __call() all is rarely necessary, certainly not for the given example.

Or if you would like to be able to set/get private/public properties without having to explicitly declare them first:

class SomeClass{

    private $properties = array();

    public function __get($name){
        if( isset($this->properties['name']) ) {
            return $this->properties['name'];
        } else {
            Throw new Exception("Object property $name does not exist.");
        }
    }

     public function __set($name,$value){
        $this->properties[$name] = $value;
    }

    // it's also a good idea to define __isset() and __unset() in this case as well
    public function __isset($name) {
        return isset($this->properties['name']);
    }

    public function __unset($name) {
        return unset($this->properties['name']);
    }
}