concept-properties.md 4.26 KB
Newer Older
Qiang Xue committed
1 2
Properties
==========
3

Larry Ullman committed
4
In PHP, class member variables are also called *properties*. These variables are part of the class definition, and are used
Larry Ullman committed
5 6
to represent the state of a class instance (i.e., to differentiate one instance of the class from another). In practice, you may often want to handle the reading or writing of properties in special ways. For example, you may want to always trim a string when it is being assigned
to a `label` property. You *could* use the following code to achieve this task:
7

Qiang Xue committed
8 9 10
```php
$object->label = trim($label);
```
11

Larry Ullman committed
12 13
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.
Carsten Brandt committed
14

Larry Ullman committed
15
To solve this problem, Yii introduces a base class called [[yii\base\Object]] that supports defining properties
Larry Ullman committed
16
based on *getter* and *setter* class methods. If a class needs that functionality, it should extend from
Larry Ullman committed
17
[[yii\base\Object]], or from a child class.
18

Larry Ullman committed
19 20
> Info: Nearly every core class in the Yii framework extends from [[yii\base\Object]] or a child class.
  This means that whenever you see a getter or setter in a core class, you can use it like a property.
21

Larry Ullman committed
22
A getter method is a method whose name starts with the word `get`; a setter method starts with `set`.
Qiang Xue committed
23 24
The name after the `get` or `set` prefix defines the name of a property. For example, a getter `getLabel()` and/or
a setter `setLabel()` defines a property named `label`, as shown in the following code:
25

Qiang Xue committed
26 27
```php
namespace app\components;
28

Qiang Xue committed
29
use yii\base\Object;
30

Qiang Xue committed
31
class Foo extend Object
32
{
Qiang Xue committed
33
    private $_label;
34

Qiang Xue committed
35 36 37
    public function getLabel()
    {
        return $this->_label;
38 39
    }

Qiang Xue committed
40
    public function setLabel($value)
41
    {
Qiang Xue committed
42
        $this->_label = trim($value);
43 44 45 46
    }
}
```

Larry Ullman committed
47 48 49 50 51
(To be clear, the getter and setter methods create the property `label`, which in this case internally refer to a private attributed 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
being assigned a value, the corresponding setter method will be called. For example:
52 53

```php
Qiang Xue committed
54 55
// equivalent to $label = $object->getLabel();
$label = $object->label;
56

Qiang Xue committed
57 58
// equivalent to $object->setLabel('abc');
$object->label = 'abc';
59 60
```

61
A property defined by a getter without a setter is *read only*. Trying to assign a value to such a property will cause
Qiang Xue committed
62
an [[yii\base\InvalidCallException|InvalidCallException]]. Similarly, a property defined by a setter without a getter
63
is *write only*, and trying to read such a property will also cause an exception. It is not common to have write-only
Qiang Xue committed
64
properties.
65

Larry Ullman committed
66
There are several special rules for, and limitations on, the properties defined via getters and setters:
67

68
* The names of such properties are *case-insensitive*. For example, `$object->label` and `$object->Label` are the same.
Larry Ullman committed
69
  This is because method names in PHP are case-insensitive.
70 71
* If the name of such a 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'`
Larry Ullman committed
72
  will affect the *member variable* 'label'; that line would not call the  `setLabel()` setter method.
Larry Ullman committed
73
* These properties do not support visibility. It makes no difference for the visibility of a property
74
  if the defining getter or setter method is public, protected or private.
Larry Ullman committed
75
* The properties can only be defined by *non-static* getters and/or setters. Static methods will not be treated in this same manner.
76

Larry Ullman committed
77
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`.