PHP. Цепочки вызовов (Method Chaining)
PHP

Предисловие

Статья рассчитана на пользователей, хорошо знакомых с объектно-ориентированным программированием.

Сейчас я расскажу о новой полезной возможности, которая была введена с ветки 5 в качестве развития ООП в PHP (по сравнению с веткой 4). Она называется «цепочки вызовов» (Method Chaining) и выглядит следующим образом:

$object->method_a()->method_b()->method_c();

Что же здесь на самом деле происходит? Начнем с того, что одно из (многих) изменений между PHP4 и PHP5 заключается в том, что теперь методы могут возвращать объекты. Это небольшое изменение позволяет по-новому использовать ООП. Итак, для того, чтобы пользоваться цепочками вызовами у вас должна быть возможность возвращать из метода объекты. Причем не существенно что это будет за объект — текущего класса, или совершенно другого.

Обычное использование класса
Начнем с самого обыкновенного класса и его использования.

class Person
{
    private $m_szName;
    private $m_iAge;
    
    public function setName($szName)
    {
        $this->m_szName = $szName;
    }
    
    public function setAge($iAge)
    {
        $this->m_iAge = $iAge;
    }
    
    public function introduce()
    {
        printf(
            'Hello my name is %s and I am %d years old.',
            $this->m_szName,
            $this->m_iAge);
    }
}  

Теперь мы можем создать экземпляр класса Person и передать в объект имя и возраст. После чего, воспользовавшись методом introduce вывести на экран информацию о человеке:

$peter = new Person();

$peter->setName('Peter');
$peter->setAge(23);

$peter->introduce();  

В результате выполнения данного примера, на экран будет выведена строка:

Hello my name is Peter and I am 23 years old.

Использование цепочных вызовов
На самом деле, отличий в коде будет совсем немного. Мы добавим всего 2 строки. Как же это будет работать? Очень просто! Нам нужно возвращать объект класса Person из каждого метода. Наш исходный класс будет выглядеть так:

class Person
{
    private $m_szName;
    private $m_iAge;
    
    public function setName($szName)
    {
        $this->m_szName = $szName;
        return $this;               //Возвращаем объект текущего класса
    }
    
    public function setAge($iAge)
    {
        $this->m_iAge = $iAge;
        return $this;              //Возвращаем объект текущего класса
    }
    
    public function introduce()
    {
        printf(
            'Hello my name is %s and I am %d years old.',
            $this->m_szName,
            $this->m_iAge);
    }
}  

Пример использования модифицированного класса:

$peter = new Person();

$peter->setName('Peter')->setAge(23)->introduce();  

На экран будет выведено абсолютно тоже самое, что и в изначальном примере.

Как это работет
Сначала мы выполняем $peter->setName(‘Peter’). Этот метод заполнит имя и вернет $this — текущий объект. Теперь нам нужно заполнить возраст. Следующее действие ->setAger(23). Поскольку мы записали вызов в цепочку, PHP интерпретирует это как «запустить метод setAge, принадлежащий тому, что вернул предыдущий метод». В данном случае Person ($peter).

Абсолютно тоже самое происходит при вызове introduce. PHP запустит метод, обратившись к объекту возвращенному из предыдущей операции.

Записывать методы в цепочку можно в любой последовательности и с любыми повторениями:

$peter->setAge(23)
      ->setName('Peter')
      ->setName('Winifred')
      ->setAge(72)
      ->introduce();  

В данном случае на экран будет выведена строка

Hello my name is Winifred and I am 72 years old.

  • статья годная, но есть небольшие проблемы с общем стилем, либо определиться как camelCase все именовать либо underscope стиль class_name, method_name. var_name и не смешивать, очень глаза режут.

  • Mj:

    Спасибо очень доступно объяснили!

  • timur:

    return $this; //Возвращаем объект текущего класса
    по моему // Возвращаем ссылку на объект текущего класса
    или я не прав?

    • root4root aka admin:

      Строго говоря, на объекты ничего другого кроме ссылок не существует. new foo() тоже возвращает ссылку на объект. Поэтому говорить объект или ссылку — суть поста от этого меняется не очень сильно.

  • Дима:

    Оказывается так всё просто

Добавить комментарий