On Zend Quick Start Guide here http://framework.zend.com/manual/en/learning.quickstart.create-model.html we can see:
class Application_Model_Guestbook
{
protected $_comment;
protected $_created;
protected $_email;
protected $_id;
public function __set($name, $value);
public function __get($name);
public function setComment($text);
public function getComment();
...
I normally create my getters and setters without any magic method. I've seen this on the quick guide, and I don't understand why may we need this.
Can anyone help me out?
Thanks a lot
You (usually) never call __set
or __get
directly. $foo->bar
will call $foo->__get('bar')
automatically if bar
is not visible and __get
exists.
In the tutorial you've linked to, the getter and setter get set up to automatically call the appropriate individual get/set functions. So $foo->comment = 'bar'
will indirectly call $foo->setComment('bar')
. This isn't necessary... it's only a convenience.
In other cases, __get
can be useful to create what looks like a read-only variable.
If you "make your own" getters and setters, you'll be making two functions for each property: getPropname()
and setPropname
. By using PHP's "magic method" setter/getter, you don't write individual methods for each property. You can set/get properties as if they were public. Within the overload functions, you add the logic specific to each property. Example:
public function __set($name, $value) {
switch ($name) {
case 'comments':
// do stuff to set comments
break;
case 'parent_user':
// do stuff to set parent user
break;
}
}
public function __get($name) {
switch ($name) {
case 'comments':
// do stuff to get comments
break;
case 'parent_user':
// do stuff to get parent user
break;
}
}
Now I can access comments by using $obj->comments
to either set or get.
To achieve the above functionality without using the overloads, I would have had to write 4 different methods instead. This is really more about code organization, both in terms of the actual file and in terms of creating a standardized interface for objects within a project.
I personally prefer to do as you do and write separate methods for each property that I need a complex getter/setter. To me, it is more clearly organized, and there is a clear separation between "simple" properties of an object and those properties which have greater complexity or one-to-many relationships.
The __get
and __set
magic methods exist for TWO reasons:
So that you don't have to spend time creating vanilla accessor methods for all of your properties.
To allow you to implement property overloading.
If you have properties that need special treatment, then the magic methods are not for you. However, if your properties simply contain data and there are no dependencies then there's no reason NOT to use the magic methods.
Further on the tutorial it gets you to modify the __get()
and __set()
methods so you'll see why they're there.
Having magic handling like that can allow you to do some neat stuff like even making "read only" properties and can prevent you from bloating your class with a messy load of getter/setters.
You'll run into problems when you've used __set
and want to override the setter functionality in a child class. You'll have to copy the entire code in __set
and change only the specific part instead of just simply overwrite one specific setter function -> redundant code
This problem can be avoided by calling the specific setter
in __set
(thanks to cHao for the tip).
Example:
class Foo1 {
protected $normal;
protected $special;
public function setSpecial($special) {
if ($special == isReallySpecial()) {
$this->special = $special;
}
}
public function __set($key, $value) {
switch ($key) {
case 'normal':
$this->normal = $value;
break;
case 'special':
$this->setSpecial($value);
}
}
}
class Foo2 extends Foo1 {
public function setSpecial($special) {
if ($special == isNotReallySpecial()) {
$this->special = $special;
}
}
}