Сегодня мы поговорим о языке программирования PHP. Точнее мы рассмотрим такой элемент языка как геттеры и сеттеры, благодаря которым можно не только значительно облегчить работу с классами, но и реализовать более «тонкую» логику работы.
В качестве подопытного класса будем использовать «класс сотрудников» с небольшим набором полей.
class Person { private $id; //id в базе private $first_name; //имя private $last_name; //фамилия private $middle_name; //отчество private $date_of_birth; //дата рождения private $some_data = Array(); //какие-то временные данные function __construct($sql_row) //конструктор класса { $this->id = $sql_row['id']; $this->first_name = $sql_row['first_name']; $this->last_name = $sql_row['last_name']; $this->middle_name = $sql_row['middle_name']; $this->date_of_birth = $sql_row['date_of_birth']; } }
Как видно из примера, структура класса достаточно проста. Конструктор класса принимает результат работы функции mysql_fetch_assoc. На самом деле это не важно, так как конструктор нас особо не интересует…
Для работы с нашим классом нам необходимо получать доступ к его private элементам. Причем вполне логично сделать так, чтобы атрибуты: идентификатор, имя, фамилия, отчество и дата рождения — были только для чтения.
Те кто знаком с языком программирвоания C# знают, что в данном языке предусмотренно ключевое слово readonly, однако в PHP такого нет. Можно конечно создать пять геттеров в виде функций, возращающих значение, но это будет громостко. Что же делать?
Не стоит забывать, что PHP скриптовый язык программирования, а значит он достаточно гибок. Рассмотрим предопределенную функцию __get, принимающую один параметр — имя поля которое мы хотим получить. Так как это имя — строка, а значит она может быть произвольная, то необходимо делать проверку на существование данного атрибута. Имеем:
public function __get($attr) { if (isset($this->$attr)) return $this->$attr; else user_error("Атрибут ".$attr." не найден!"); }
Таким образом:
$sql_result = mysql_query(...); $sql_row = mysql_fetch_assoc($sql_result); $p = new Person($sql_row); echo $p->id; //покажет нам id сотрудника echo "<br/>"; echo $p->blablabla; //покажет нам ошибку, что поле не найдено
Однако можно пойти еще дальше и определить внутри геттера некоторые функции, связанные с атрибутами класса. Не стоит ими злоупотреблять, однако порой это очень полезно. Например можно задать вывод полного имени сотрудника:
public function __get($attr) { if ($attr == "full_name") { return $this->last_name." ".$this->first_name." ".$this->middle_name; } else if (isset($this->$attr)) return $this->$attr; else user_error("Атрибут ".$attr." не найден!"); }
Теперь, несмотря на отсутсвие атрибута full_name у класса, вызов $p->full_name будет работать.
Однако это не все. Теперь мы рассмотрим еще одну предопределенную функцию __set, которая принимает два значения: имя атрибута и его значение. Как видно из названия метода, он служит для установки значения.
Так как поля имя, фамилия и т.п. нам нужны только для чтения, в данной функции мы описывать их не будем. Однако наш класс имеет еще один атрибут some_data, который мы и будем менять. Будем использовать его для хранения любых данных, под любым именем (поэтому он и описан как массив).
public function __set($attr, $value) { $this->some_data[$attr] = $value; }
Теперь вернемся к геттеру и немного подправим его, чтобы можно было получить произвольные значения:
public function __get($attr) { if ($attr == "full_name") { return $this->last_name." ".$this->first_name." ".$this->middle_name; } else { foreach ($this->some_data as $key => $value) if ($key == $attr) return $value; if (isset($this->$attr)) return $this->$attr; else user_error("Атрибут ".$attr." не найден!"); } }
Теперь:
$sql_result = mysql_query(...); $sql_row = mysql_fetch_assoc($sql_result); $p = new Person($sql_row); echo $p->id; //покажет нам id сотрудника echo "<br/>"; echo $p->blablabla; //покажет нам ошибку, что поле не найдено $p->blablabla = "Это blablabla"; echo "<br/>"; echo $p->blablabla; //покажет нам 'Это blablabla'
Вот собственно и все.