В PHP, переменные-члены класса называются *свойства*. Эти переменные являются частью объявления класса и используются для хранения состояния объектов класса (т.е. для отличия одного экземпляра класса от другого). На практике вам часто придется производить чтение и запись свойств особым образом. Например, вам может понадобится обрезать строку при ее записи в поле `label`. Для этого вы можете использовать следующий код:
В PHP, переменные-члены класса называются *свойства*. Эти переменные являются частью объявления класса и используются для
хранения состояния объектов этого класса (т.е. именно этим отличается однин экземпляр класса от другого). На практике
вам часто придётся производить чтение и запись свойств особым образом. Например, вам может понадобится обрезать строку
при её записи в поле `label`. Для этого вы *можете* использовать следующий код:
```php
```php
$object->label=trim($label);
$object->label=trim($label);
```
```
Недостатком приведенного выше кода является то, что вам придется вызывать функцию `trim()` во всех местах, где вы присваиваете значение полю `label`. Если в будущем понадобится производить еще какие-либо действие, например возводить первую букву в верхний регистр, вам придется изменить каждый участок кода, где производится присваивание значения полю `label`. Повторение кода приводит к ошибкам и по возможности нужно избегать такой практики.
Недостатком приведённого выше кода является то, что вам придется вызывать функцию `trim()` во всех местах, где вы
присваиваете значение полю `label`. Если в будущем понадобится производить еще какие-либо действие, например приобразовать
первую букву в верхний регистр, вам придётся изменить каждый участок кода, где производится присваивание значения
полю `label`. Повторение кода приводит к ошибкам и его необходимо избегать всеми силами.
Что бы решить эту проблему, в Yii был добавлен базовый класс [[yii\base\Object]] который реализует работу со свойствами через *геттеры* и *сеттеры*. Если вашему классу нужна такая возможность, необходимо унаследовать его от класса [[yii\base\Object]].
Что бы решить эту проблему, в Yii был добавлен базовый класс [[yii\base\Object]] который реализует работу со свойствами
через *геттеры* и *сеттеры*. Если вашему классу нужна такая возможность, необходимо унаследовать его от
[[yii\base\Object]] или его потомка.
> Информация: Почти все внутренние классы Yii наследуются от [[yii\base\Object]] или его потомков.
> Информация: Почти все внутренние классы Yii наследуются от [[yii\base\Object]] или его потомков.
Это значит, что всякий раз, когда вы встречаете геттер или сеттер в классах фреймворка, вы можете обращаться к нему, как к свойству.
Это значит, что всякий раз, когда вы встречаете геттер или сеттер в классах фреймворка, вы можете обращаться к нему
как к свойству.
Геттер - это метод, чье название начинается со слова `get`; имя сеттера начинается со слова `set`. А часть названия после префикса `get` или `set` определяет имя свойства. Например, геттер `getLabel()` и/или сеттер `setLabel()` определяют свойство `label`, как показано в коде ниже:
Геттер — это метод, чьё название начинается со слова `get`. Имя сеттера начинается со слова `set`. Часть названия после
`get` или `set` определяет имя свойства. Например, геттер `getLabel()` и/или сеттер `setLabel()` определяют свойство
`label`, как показано в коде ниже:
```php
```php
namespaceapp\components;
namespaceapp\components;
...
@@ -37,9 +48,11 @@ class Foo extend Object
...
@@ -37,9 +48,11 @@ class Foo extend Object
}
}
```
```
*(Для наглядности, здесь геттер и сеттер реализуют свойство `label`, но значение хранят в закрытом свойстве `_label`).*
В коде выше геттер и сеттер реализуют свойство `label`, значение которого хранится в private свойстве `_label`.
Свойства, определенные с помощью геттеров и сеттеров можно использовать как обычные свойства класса. Главное отличие в том, что когда происходит чтение такого свойства, вызывается соответствующий геттер; а когда происходит присвоение значения такому свойству - запускается соответствующий сеттер. Например:
Свойства, определенные с помощью геттеров и сеттеров, можно использовать как обычные свойства класса. Главное отличие
в том, что когда происходит чтение такого свойства, вызывается соответствующий геттер, при присвоении значения такому
Свойство для которого объявлен только геттер без сеттера может использоваться *только для чтения*. Попытка присвоить ему значение вызовет [[yii\base\InvalidCallException|InvalidCallException]]. Точно так же, свойство для которого объявлен только сеттер без геттера может использоваться *только для записи*. Попытка получить его значение так же вызовет исключение. *Свойства предназначенные только для чтения встречаются не часто.*
Свойство, для которого объявлен только геттер без сеттера, может использоваться *только для чтения*. Попытка присвоить
ему значение вызовет [[yii\base\InvalidCallException|InvalidCallException]]. Точно так же, свойство для которого объявлен
только сеттер без геттера может использоваться *только для записи*. Попытка получить его значение так же вызовет
исключение. Свойства, предназначенные только для чтения, встречаются не часто.
При определении свойств класса при помощи геттеров и сеттеров нужно помнить о некоторых правилах и ограничениях:
При определении свойств класса при помощи геттеров и сеттеров нужно помнить о некоторых правилах и ограничениях:
* Имена таких свойств *регистронезависимы*. Таким образом, `$object->label` и `$object->Label`- одно и то же.
* Имена таких свойств *регистронезависимы*. Таким образом, `$object->label` и `$object->Label`— одно и то же.
Это обусловлено тем, что имена методов в PHP регистронезависимы.
Это обусловлено тем, что имена методов в PHP регистронезависимы.
* Если имя такого свойства уже используется переменной-членом класса, то последнее будет иметь более высокий приоритет.
* Если имя такого свойства уже используется переменной-членом класса, то последнее будет иметь более высокий приоритет.
Например, если в классе `Foo` объявлено свойство `label`, то при вызове `$object->label = 'abc'` будет напрямую изменено значение свойства `label`. А метод `setLabel()` не будет вызван.
Например, если в классе `Foo` объявлено свойство `label`, то при вызове `$object->label = 'abc'` будет напрямую изменено
* Свойства, объявленные таким образом, не поддерживают идентификаторы видимости. Это значит, что объявление геттера или сеттера как открытого, защищенного или закрытого никак не скажется на области видимости свойства.
значение свойства `label`. А метод `setLabel()` не будет вызван.
* Свойства могут быть объявлены только с помощью *нестатичных* геттеров и/или сеттеров. Статичные методы не будут обрабатываться подобным образом.
* Свойства, объявленные таким образом, не поддерживают модификаторы видимости. Это значит, что объявление геттера или
сеттера как public, protected или private никак не скажется на области видимости свойства.
Возвращаясь к проблеме, описанной в начале этого руководства, касающейся необходимости вызова функции `trim()` во всех местах, где присваивается значение свойству `label`. Функцию `trim()` необходимо вызывать только один раз - в методе `setLabel()`. Тогда при возникновении нового требования (возведение первой буквы в верхний регистр), это можно будет быстро сделать, не затрагивая остальной код. Нужно будет просто изменить метод `setLabel()`. Такое изменение будет распространяться на все присвоения значения свойству `label`.
* Свойства могут быть объявлены только с помощью *нестатичных* геттеров и/или сеттеров. Статичные методы не будут
обрабатываться подобным образом.
Возвращаясь к проблеме необходимости вызова функции `trim()` во всех местах, где присваивается значение свойству `label`,
описанной в начале этого руководства, функцию `trim()` теперь необходимо вызывать только один раз — в методе `setLabel()`.
При возникновении нового требования о возведение первой буквы в верхний регистр, можно быстро поправить метод `setLabel()`
не затрагивая остальной код. Эта правка будет распространяться на все присвоения значения свойству `label`.