Переменные названия свойств объектов в PHP
На примере этого класса мы сейчас разберем то, что названия свойств можно хранить в переменной.
К примеру, пусть у нас есть переменная $prop , в которой лежит строка ‘name’ . Тогда обращение $user->$prop по сути эквивалентно обращению $user->name . Такое хитрое обращения к свойствам класса используется редко, но иногда бывает полезно.
Посмотрим на примере:
$prop; // выведет ‘john’ ?>?php>
Сделайте класс City , в котором будут следующие свойства — name , foundation ( дата основания ), population ( население ). Создайте объект этого класса.
Пусть дана переменная $props , в которой хранится массив названий свойств класса City . Переберите этот массив циклом foreach и выведите на экран значения соответствующих свойств.
Массив свойств
Пусть теперь дан вот такой класс User :
surname = $surname; $this->name = $name; $this->patronymic = $patronymic; > > ?>?php>
И пусть дан массив свойств
Попробуем теперь вывести значение свойства, которое хранится в нулевом элементе массива, то есть в $props[0] . Просто так, однако, это не будет работать:
$props[0]; // так работать не будет ?>?php>
Для того, чтобы такое сложное имя свойства заработало, его нужно взять в фигурные скобки, вот так:
; // выведет ‘Иванов’ ?>?php>
Скопируйте мой код класса User и массив $props . В моем примере на экран выводится фамилия юзера. Выведите еще и имя, и отчество.
Ассоциативный массив
Массив, кстати, может быть и ассоциативным:
‘surname’, ‘prop2’ => ‘name’, ‘prop3’ => ‘patronymic’]; echo $user->; // выведет ‘Иванов’ ?>?php>
Имя свойства из функции
Имя свойства также может быть из функции:
$user = new User(‘Иванов’, ‘Иван’, ‘Иванович’); echo $user->; // выведет ‘Иванов’ ?>?php>
Имя свойства из свойства другого объекта
Имя свойства может быть даже свойством другого объекта.
Проиллюстрируем кодом. Пусть для примера дан объект Prop , который в свойстве value будет содержать название свойства объекта User :
value = $value; > > ?>?php>
Давайте выведем фамилию юзера с помощью объекта Prop :
value>; // выведет ‘Иванов’ ?>?php>
Имя свойства из метода другого объекта
Имя свойства также может браться из метода другого объекта:
value = $value; > public function getValue() < return $this->value; > > ?>?php>
Давайте выведем фамилию юзера:
Работа со свойствами объектов на PHP
Сейчас мы с вами научимся работать с объектами и их свойствами на более практическом примере. Давайте сделаем класс User , который будет описывать юзера нашего сайта. Пусть у нашего пользователя будет два свойства: имя и возраст. Напишем код нашего класса:
Пока наш класс ничего не делает — он просто описывает, что будут иметь объекты этого класса (в нашем случае каждый объект будет иметь имя и возраст). По сути, пока мы не создадим хотя бы один объект нашего класса — ничего полезного не произойдет.
Давайте создадим объект нашего класса. При этом нужно иметь ввиду, что классы принято называть большими буквами, а объекты этих классов — маленькими:
// Создаем объект нашего класса: $user = new User; ?>?php>
Давайте теперь что-нибудь запишем в свойства нашего объекта, а потом выведем эти данные на экран:
$user = new User; // создаем объект нашего класса $user->name = ‘john’; // записываем имя в свойство name $user->age = 25; // записываем возраст в свойство age echo $user->name; // выводим записанное имя echo $user->age; // выводим записанный возраст ?>?php>
Как вы уже поняли — в свойства объекта можно что-то записывать и из свойств можно выводить их содержимое. Давайте теперь сделаем 2 объекта-юзера: ‘john’ и ‘eric’ , заполним их данными и выведем на экран сумму их возрастов:
// Первый объект $user1 = new User; // создаем первый объект $user1->name = ‘john’; // записываем имя $user1->age = 25; // записываем возраст // Второй объект $user2 = new User; // создаем второй объект $user2->name = ‘eric’; // записываем имя $user2->age = 30; // записываем возраст // Найдем сумму возрастов: echo $user1->age + $user2->age; // выведет 55 ?>?php>
Сделайте класс Employee (работник), в котором будут следующие свойства — name (имя), age (возраст), salary (зарплата).
Создайте объект класса Employee , затем установите его свойства в следующие значения — имя ‘john’ , возраст 25 , зарплата 1000 .
Создайте второй объект класса Employee , установите его свойства в следующие значения — имя ‘eric’ , возраст 26 , зарплата 2000 .
Выведите на экран сумму зарплат созданных юзеров.
Выведите на экран сумму возрастов созданных юзеров.
Свойства
Переменные, которые являются членами класса, называются «свойства». Также их называют, используя другие термины, такие как «атрибуты» или «поля», но в рамках этой документации, мы будем называть их свойствами. Они определяются с помощью ключевых слов public, protected, или private, следуя правилам правильного описания переменных. Это описание может содержать инициализацию, но инициализация должна применяться для константных значений — то есть, переменные должны быть вычислены во время компиляции и не должны зависеть от информации программы во время выполнения для их вычисления.
Смотри Область видимости для получения информации о применении public, protected, и private.
Замечание:
Для того, чтобы поддерживать обратную совместимость с PHP 4, PHP 5 по-прежнему позволяет использовать ключевое слово var при определении свойств вместо (или в дополнении к) public, protected, или private. Однако, var больше не требуется. В версиях PHP с 5.0 по 5.1.3, использование var считалось устаревшим вызывало E_STRICT предупреждение, но с PHP 5.1.3 больше не считается устаревшим и не выдает предупреждения.
Если, для определения свойства, вы используете var вместо одного из: public, protected, или private, тогда PHP 5 будет определять свойство как public.
В пределах методов класса доступ к нестатическим свойствам может быть получен с помощью -> (объектного оператора): $this->property (где property — имя свойства). Доступ к статическим свойствам может быть получен с помощью :: (двойного двоеточия): self::$property . Подробнее о различиях между статическими и нестатическими свойствами смотрите в разделе «Ключевое слово Static» для получения большей информации.
Псевдо-переменная $this доступна внутри любого метода класса, когда этот метод вызывается в пределах объекта. $this — это ссылка на вызываемый объект (обычно, объект, которому принадлежит метод, но возможно и другого объекта, если метод вызван статически из контекста второго объекта).
Пример #1 Определение свойств
class SimpleClass
// неправильное определение свойств:
public $var1 = ‘hello ‘ . ‘world’ ;
public $var2 = hello world
EOD;
public $var3 = 1 + 2 ;
public $var4 = self :: myStaticMethod ();
public $var5 = $myVar ;
?php
// правильное определение свойств:
public $var6 = myConstant ;
public $var7 = array( true , false );
// Это разрешено только в PHP 5.3.0 и более поздних версиях.
public $var8 = hello world
EOD;
>
?>
Замечание:
Существуют несколько интересных функций для обработки классов и объектов. Вы можете их увидеть тут Class/Object Functions.
В отличии от heredocs, nowdocs может быть использованы в любом статическом контексте данных, включая определение свойств.
Пример #2 Пример использования nowdoc для инициализации свойств
class foo // As of PHP 5.3.0
public $bar = bar
EOT;
>
?>?php
Замечание:
Поддержка nowdoc была добавлена в PHP 5.3.0.
Свойства ¶
В PHP, переменные-члены класса называются свойства. Эти переменные являются частью объявления класса и используются для хранения состояния объектов этого класса (т.е. именно этим отличается один экземпляр класса от другого). На практике вам часто придётся производить чтение и запись свойств особым образом. Например, вам может понадобиться обрезать строку при её записи в поле label . Для этого вы можете использовать следующий код:
$object->label = trim($label);
Недостатком приведённого выше кода является то, что вам придется вызывать функцию trim() во всех местах, где вы присваиваете значение полю label . Если в будущем понадобится производить еще какие-либо действия, например, преобразовать первую букву в верхний регистр, то вам придётся изменить каждый участок кода, где производится присваивание значения полю label . Повторение кода приводит к ошибкам и его необходимо избегать всеми силами.
Чтобы решить эту проблему, в Yii был добавлен базовый класс yii\base\BaseObject, который реализует работу со свойствами через геттеры и сеттеры. Если вашему классу нужна такая возможность, необходимо унаследовать его от yii\base\BaseObject или его потомка.
Информация: Почти все внутренние классы Yii наследуются от yii\base\BaseObject или его потомков. Это значит, что всякий раз, когда вы встречаете геттер или сеттер в классах фреймворка, вы можете обращаться к нему как к свойству.
Геттер — это метод, чьё название начинается со слова get . Имя сеттера начинается со слова set . Часть названия после get или set определяет имя свойства. Например, геттер getLabel() и/или сеттер setLabel() определяют свойство label , как показано в коде ниже:
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 .
Свойства, определенные с помощью геттеров и сеттеров, можно использовать как обычные свойства класса. Главное отличие в том, что когда происходит чтение такого свойства, вызывается соответствующий геттер, при присвоении значения такому свойству запускается соответствующий сеттер. Например:
// Идентично вызову $label = $object->getLabel(); $label = $object->label; // Идентично вызову $object->setLabel('abc'); $object->label = 'abc';
Свойство, для которого объявлен только геттер без сеттера, может использоваться только для чтения. Попытка присвоить ему значение вызовет InvalidCallException. Точно так же, свойство для которого объявлен только сеттер без геттера может использоваться только для записи. Попытка получить его значение так же вызовет исключение. Свойства, предназначенные только для чтения, встречаются не часто.
При определении свойств класса при помощи геттеров и сеттеров нужно помнить о некоторых правилах и ограничениях:
- Имена таких свойств регистронезависимы. Таким образом, $object->label и $object->Label — одно и то же. Это обусловлено тем, что имена методов в PHP регистронезависимы.
- Если имя такого свойства уже используется переменной-членом класса, то последнее будет иметь более высокий приоритет. Например, если в классе Foo объявлено свойство label , то при вызове $object->label = ‘abc’ будет напрямую изменено значение свойства label . А метод setLabel() не будет вызван.
- Свойства, объявленные таким образом, не поддерживают модификаторы видимости. Это значит, что объявление геттера или сеттера как public, protected или private никак не скажется на области видимости свойства.
- Свойства могут быть объявлены только с помощью не статичных геттеров и/или сеттеров. Статичные методы не будут обрабатываться подобным образом.
- Обычный вызов property_exists() не работает для магических свойств. Для них необходимо использовать canGetProperty() или canSetProperty().
Возвращаясь к проблеме необходимости вызова функции trim() во всех местах, где присваивается значение свойству label , описанной в начале этого руководства, функцию trim() теперь необходимо вызывать только один раз — в методе setLabel() . При возникновении нового требования о возведение первой буквы в верхний регистр, можно быстро поправить метод setLabel() не затрагивая остальной код. Эта правка будет распространяться на все присвоения значения свойству label .