Laravel очень либерально использует магические методы .Когда вы делаете что-то вроде Artisan::command()
, фактическое определение public static function command()
отсутствует.Поэтому вместо этого php проверяет, определен ли метод __callStatic()
, как ловушка для неопределенных методов.Таким образом, где-то на Artisan
Фасаде вы, вероятно, найдете что-то с эффектом:
public static function __callStatic($name, array $args = [])
{
$newObj = new static();
if (method_exists($newObj, $name)) {
return $newObj->$name(...$args);
}
}
Еще одна хитрая вещь в том, что, скорее всего, объект, который вы получите, не был недавно создан, как вприведенный выше пример.Большинство из них следуют Singleton Pattern , что означает, что вы не только статически вызываете нестатический метод, но и каждый раз вызываете его для того же самого экземпляра целевого объекта.
$newObj = new static();
Похоже на
self::$preexistingObject = self::$preexistingObject ?: new static();
$newObj = self::$preexistingObject;
Большая часть этой магии происходит при загрузке ServiceProviders.Где-то в файле конфигурации Laravel было сказано, какой корневой класс ассоциируется с этим «Artisan» Facade.Он создает новый экземпляр этого класса и удерживает его, повторно используя его, в течение всего сеанса.
Наконец, чтобы более прямо ответить на ваш вопрос и уточнить ответ Иэнна, это поразило меняВпервые я обнаружил это, но нативный Php фактически поддерживает изменение того, на какой объект $this
ссылается ваша анонимная функция.Вы просто вызываете $closure->bindTo($newObject)
, как если бы Closure был сам по себе, а object и bindTo () - это метод.(Насколько я знаю, под капотом Php на самом деле может не иметь особого значения.)
С этим тоже можно сделать несколько классных вещей.Вы можете настроить свой класс на получение Closure, повторно привязать его к своей области видимости вместо области вызова, сохранить его в статическом ассоциативном массиве и получить к нему доступ позже через.Волшебный __call()
метод.В результате получается перегрузка метода ;возможность внедрить пользовательские алгоритмы в вспомогательный класс для последующего использования в декларативном контексте.
Laravel предоставляет инструмент, который может сделать именно это. Макросы , Черта, которую вы можете подключить к чему угодно.И он уже встроен в некоторые наборы инструментов, которые являются известными кандидатами на расширение, такие как Коллекции , Eloquent \ Builder и Ответы .