The drawback of the above code is that you would have to call `trim()` everywhere in your code where you might set the `label`
property. If, in the future, the `label` property gets a new requirement, such as the first letter must be captialized, you would again have to modify every bit of code that assigns a value to `label`. The repetition of code leads to bugs, and is a practice you want to avoid as much as possible.
property. If, in the future, the `label` property gets a new requirement, such as the first letter must be capitalized, you would again have to modify every bit of code that assigns a value to `label`. The repetition of code leads to bugs, and is a practice you want to avoid as much as possible.
To solve this problem, Yii introduces a base class called [[yii\base\Object]] that supports defining properties
based on *getter* and *setter* class methods. If a class needs that functionality, it should extend from
...
...
@@ -28,7 +28,7 @@ namespace app\components;
useyii\base\Object;
classFooextendObject
classFooextendsObject
{
private$_label;
...
...
@@ -44,10 +44,10 @@ class Foo extend Object
}
```
(To be clear, the getter and setter methods create the property `label`, which in this case internally refer to a private attributed named `_label`.)
(To be clear, the getter and setter methods create the property `label`, which in this case internally refers to a private attribute named `_label`.)
Properties defined by getters and setters can be used like class member variables. The main difference is that
when such a property is being read, the corresponding getter method will be called; when the property is
when such property is being read, the corresponding getter method will be called; when the property is
being assigned a value, the corresponding setter method will be called. For example:
```php
...
...
@@ -58,20 +58,20 @@ $label = $object->label;
$object->label='abc';
```
A property defined by a getter without a setter is *read only*. Trying to assign a value to such a property will cause
A property defined by a getter without a setter is *read only*. Trying to assign a value to such property will cause
an [[yii\base\InvalidCallException|InvalidCallException]]. Similarly, a property defined by a setter without a getter
is *write only*, and trying to read such a property will also cause an exception. It is not common to have write-only
is *write only*, and trying to read such property will also cause an exception. It is not common to have write-only
properties.
There are several special rules for, and limitations on, the properties defined via getters and setters:
* The names of such properties are *case-insensitive*. For example, `$object->label` and `$object->Label` are the same.
This is because method names in PHP are case-insensitive.
* If the name of such a property is the same as a class member variable, the latter will take precedence.
* If the name of such property is the same as a class member variable, the latter will take precedence.
For example, if the above `Foo` class has a member variable `label`, then the assignment `$object->label = 'abc'`
will affect the *member variable* 'label'; that line would not call the `setLabel()` setter method.
* These properties do not support visibility. It makes no difference for the visibility of a property
if the defining getter or setter method is public, protected or private.
* The properties can only be defined by *non-static* getters and/or setters. Static methods will not be treated in this same manner.
* The properties can only be defined by *non-static* getters and/or setters. Static methods will not be treated in the same manner.
Returning back to the problem described at the beginning of this guide, instead of calling `trim()` everywhere a `label` value is assigned, `trim()` now only needs to be invoked within the setter `setLabel()`. And if a new requirement comes that requires the label be initially capitalized, the `setLabel()` method can quickly be modified without touching any other code. The one change will universally affect every assignment to `label`.
Returning back to the problem described at the beginning of this guide, instead of calling `trim()` everywhere a `label` value is assigned, `trim()` now only needs to be invoked within the setter `setLabel()`. And if a new requirement comes that requires the label to be initially capitalized, the `setLabel()` method can quickly be modified without touching any other code. The one change will universally affect every assignment to `label`.