I recently went to an interview and my code I supplied had magic functions to get and set variables. My code was as follows:
public function __get($name){
try {
return $this->$name;
} catch (Exception $e) {
throw new Exception('Trying to get a variable "'.$name.'" that does not exist.');
}
}
In the interview the guy asked me about the visibility on my variables, I had private ones set but these were now accessible by using magic functions. Essentially I failed the interview on this point, so I wanted to understand more. I was following a tutorial from PHP Master and found a different __get, I have tried to break it but it seems to work, but in a strange way.
I call __get('test') to get my variable _test but if it is set to private it calls itself again and tells me that it cannot access __test. I do not really understand why it calls itself again.
public function __get($name)
{
$field = '_' . strtolower($name);
if (!property_exists($this, $field)){
throw new \InvalidArgumentException(
"Getting the field '$field' is not valid for this entity"
);
}
$accessor = 'get' . ucfirst(strtolower($name));
return (method_exists($this, $accessor) && is_callable(array($this, $accessor))) ?
$this->$accessor() : $this->$field;
}
Can anyone give me some pointers on proper use of __get and __set when using visibility in a class and why this function would call itself again.
I have read the other posts here but I am still struggling with this concept.
I just bumped into this question and there is a little thing that may be worth clarifying:
The code is not calling itself again but trying to execute a custom getter if there is one defined. Let me break down the method execution:
As already explained in the other answers and here, the __get() magic method is called when you are trying to access a property that is not declared or not visible in the calling scope.
Here it just checks that a property with an underscore pre-appended exists in the class definition. If it doesn’t, an exception is thrown.
Here it creates the name of the getter to call if it exists. Thus, if you try to access a property named
emailand there is a private member called_emailthe$accessorvariable will now hold the'getEmail'string.The final part is a bit cryiptic, since many things are happening in one line:
method_exists($this, $accessor). Checks if the receiver ($this) has a method with$accessorname (in our example,getEmail).is_callable(array($this, $accessor)). Checks that the getter can be called.$this->$accessor()). If not, the property contents are returned ($this->$field).As an example consider this class definition:
and then run:
You should see:
HTH