Сегодня мы поговорим о языке программирования 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'
Вот собственно и все.