mirror of
https://github.com/yiisoft/yii2.git
synced 2025-08-15 14:50:56 +08:00
87 lines
7.5 KiB
Markdown
87 lines
7.5 KiB
Markdown
Свойства
|
||
========
|
||
|
||
В PHP, переменные-члены класса называются *свойства*. Эти переменные являются частью объявления класса и используются для
|
||
хранения состояния объектов этого класса (т.е. именно этим отличается один экземпляр класса от другого). На практике
|
||
вам часто придётся производить чтение и запись свойств особым образом. Например, вам может понадобиться обрезать строку
|
||
при её записи в поле `label`. Для этого вы *можете* использовать следующий код:
|
||
|
||
```php
|
||
$object->label = trim($label);
|
||
```
|
||
|
||
Недостатком приведённого выше кода является то, что вам придется вызывать функцию `trim()` во всех местах, где вы
|
||
присваиваете значение полю `label`. Если в будущем понадобится производить еще какие-либо действие, например преобразовать первую букву в верхний регистр, вам придётся изменить каждый участок кода, где производится присваивание значения
|
||
полю `label`. Повторение кода приводит к ошибкам и его необходимо избегать всеми силами.
|
||
|
||
Что бы решить эту проблему, в Yii был добавлен базовый класс [[yii\base\BaseObject]] который реализует работу со свойствами
|
||
через *геттеры* и *сеттеры*. Если вашему классу нужна такая возможность, необходимо унаследовать его от
|
||
[[yii\base\BaseObject]] или его потомка.
|
||
|
||
> Info: Почти все внутренние классы Yii наследуются от [[yii\base\BaseObject]] или его потомков.
|
||
Это значит, что всякий раз, когда вы встречаете геттер или сеттер в классах фреймворка, вы можете обращаться к нему
|
||
как к свойству.
|
||
|
||
Геттер — это метод, чьё название начинается со слова `get`. Имя сеттера начинается со слова `set`. Часть названия после
|
||
`get` или `set` определяет имя свойства. Например, геттер `getLabel()` и/или сеттер `setLabel()` определяют свойство
|
||
`label`, как показано в коде ниже:
|
||
|
||
```php
|
||
namespace app\components;
|
||
|
||
use yii\base\BaseObject;
|
||
|
||
class Foo extends BaseObject
|
||
{
|
||
private $_label;
|
||
|
||
public function getLabel()
|
||
{
|
||
return $this->_label;
|
||
}
|
||
|
||
public function setLabel($value)
|
||
{
|
||
$this->_label = trim($value);
|
||
}
|
||
}
|
||
```
|
||
|
||
В коде выше геттер и сеттер реализуют свойство `label`, значение которого хранится в private свойстве `_label`.
|
||
|
||
Свойства, определенные с помощью геттеров и сеттеров, можно использовать как обычные свойства класса. Главное отличие
|
||
в том, что когда происходит чтение такого свойства, вызывается соответствующий геттер, при присвоении значения такому
|
||
свойству запускается соответствующий сеттер. Например:
|
||
|
||
```php
|
||
// Идентично вызову $label = $object->getLabel();
|
||
$label = $object->label;
|
||
|
||
// Идентично вызову $object->setLabel('abc');
|
||
$object->label = 'abc';
|
||
```
|
||
|
||
Свойство, для которого объявлен только геттер без сеттера, может использоваться *только для чтения*. Попытка присвоить
|
||
ему значение вызовет [[yii\base\InvalidCallException|InvalidCallException]]. Точно так же, свойство для которого объявлен
|
||
только сеттер без геттера может использоваться *только для записи*. Попытка получить его значение так же вызовет
|
||
исключение. Свойства, предназначенные только для чтения, встречаются не часто.
|
||
|
||
При определении свойств класса при помощи геттеров и сеттеров нужно помнить о некоторых правилах и ограничениях:
|
||
|
||
* Имена таких свойств *регистронезависимы*. Таким образом, `$object->label` и `$object->Label` — одно и то же.
|
||
Это обусловлено тем, что имена методов в PHP регистронезависимы.
|
||
* Если имя такого свойства уже используется переменной-членом класса, то последнее будет иметь более высокий приоритет.
|
||
Например, если в классе `Foo` объявлено свойство `label`, то при вызове `$object->label = 'abc'` будет напрямую изменено
|
||
значение свойства `label`. А метод `setLabel()` не будет вызван.
|
||
* Свойства, объявленные таким образом, не поддерживают модификаторы видимости. Это значит, что объявление геттера или
|
||
сеттера как public, protected или private никак не скажется на области видимости свойства.
|
||
* Свойства могут быть объявлены только с помощью *не статичных* геттеров и/или сеттеров. Статичные методы не будут
|
||
обрабатываться подобным образом.
|
||
* Обычный вызов `property_exists()` не работает для магических свойств. Для них необходимо использовать
|
||
[[yii\base\BaseObject::canGetProperty()|canGetProperty()]] или [[yii\base\BaseObject::canSetProperty()|canSetProperty()]].
|
||
|
||
Возвращаясь к проблеме необходимости вызова функции `trim()` во всех местах, где присваивается значение свойству `label`,
|
||
описанной в начале этого руководства, функцию `trim()` теперь необходимо вызывать только один раз — в методе `setLabel()`.
|
||
При возникновении нового требования о возведение первой буквы в верхний регистр, можно быстро поправить метод `setLabel()`
|
||
не затрагивая остальной код. Эта правка будет распространяться на все присвоения значения свойству `label`.
|