PHP

Что такое __call() и __callStatic()?

Допустим у вас есть класс, описывающий методы и свойства какого-либо объекта (что, в принципе, логично). Представьте, что вы решили обратиться к несуществующему методу этого объекта. Что вы получите? Правильно — фатальную ошибку! Ниже привожу простейший код.

<?php
class OurClass{}
$Object=new OurClass;
// Получаем Fatal error: Call to undefined method OurClass::DynamicMethod()
$Object->DynamicMethod();
?>


<?php
class OurClass{}
// Получаем Fatal error: Call to undefined method OurClass::StaticMethod()
OurClass::StaticMethod();
?>

Так вот, иногда возникает необходимость либо выполнить какой-то код при отсутствии нужного нам метода, либо узнать какой метод пытались вызвать, либо использовать другое API для вызова нужного нам метода. С этой целью и существуют методы __call() и __callStatic() — они перехватывают обращение к несуществующему методу в контексте объекта и в статическом контексте, соответственно.


Перепишем наши примеры с использованием «магических методов». Примечание: Каждый из этих волшебников принимает два параметра: первый — имя метода, который мы пытаемся вызвать, второй — список, содержащий параметры вызываемого метода. Ключ — номер параметра вызываемого метода, значение — собственно сам параметр

<?php
class OurClass
{
    public function __call($name,array $params)
    {
        echo 'Вы хотели вызвать $Object->'.$name.', но его не существует, и сейчас выполняется '.__METHOD__.'()<br>'
        .PHP_EOL;
        return;
    }
    
    public static function __callStatic($name,array $params)
    {
        echo 'Вы хотели вызвать '.__CLASS__.'::'.$name.', но его не существует, и сейчас выполняется '.__METHOD__.'()';
        return;
    }
}

$Object=new OurClass;
#Вы хотели вызвать $Object->DynamicMethod, но его не существует, и сейчас выполняется OurClass::__call()
$Object->DynamicMethod();
#Вы хотели вызвать OurClass::StaticMethod, но его не существует, и сейчас выполняется OurClass::__callStatic()
OurClass::StaticMethod();
?>

Практическое применение этих двух товарищей зависит только от вашей фантазии. В качестве примера, приведу набросок-реализации техники программирования Fluent Interface (некоторые считают это паттерном проектирования, но от названия суть не меняется). Коротко говоря, fluent interface позволяет составлять цепочки вызовов объектов (с виду что-то похожее на jQuery). На хабре есть пару статей про реализацию такого рода алгоритмов. На ломаном русском переводе fluent interfaces звучат как «текучие интерфейсы»

<?php
abstract class Manager
{
    public
        $content_storage='';
    
    public function __toString()
    {
        return $this->content_storage;
    }
    
    public function __call($name,array $params)
    {
        $this->content_storage.=$this->_GetObject($name,$params).'<br>'.PHP_EOL;
        return $this;
    }
}

abstract class EntryClass
{
    public static function Launch()
    {
        return new FluentInterface;
    }
}

class FluentInterface extends Manager
{
    public function __construct()
    {
        /**
         * Что-нибудь инициализируем		 
         */
    }
    
    public static function _GetObject($n,array $params)
    {
        return $n;
    }
}

echo $FI=EntryClass::Launch()
        ->First()
        ->Second()
        ->Third();
/*
    Выведет
    First
    Second
    Third
*/
?>
Теги:
fluent interface, php, __call, __callStatic, магические методы
Добавлено: 31 Марта 2018 06:43:46 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...