PHP: «Get & Set»

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

Вот собственно и все.

Запись опубликована в рубрике PHP с метками , , , , , , , , , , , . Добавьте в закладки постоянную ссылку.