Кто подскажет, куда копать в поисках инфы?? Напишу на примере,так будет понятнее. Имеется класс View где-то в ядре с публичными интерфейсами PHP: public function show($template) и PHP: public function with($variables) . Т.е show грубо говоря возвращает(подключает) какое-либо представление, а with передает туда переменные. Т.е вызовы вида PHP: View::show('main')->with(['var' => 'value']) . Вопрос: существуют ли способы, чтобы сначала выполнялся код в методе with, а уже потом show, который производит шаблон и передает туда переменные из with? Без сохранения состояния метода with(), а на лету. Может какие-то технологии, про которые я еще не слышал?
чтоб писать красивые публичные интерфейсы(методы) для классов... в приведенном мной примере сначала выполнится код метода show(), которые во своей сути возвращает какой-либо файл с представлением..соответственно следующий за ним метод with() будет бесполезен, т.к. представление уже вернулось.... В ларавеле это как то реализовано, или там эти методы и данный класс просто формируют все данные, а шаблоны возвращает уже какой-то другой класс
Не смотрел их код, полагаю, View::show() возвращает класс View с установленном свойством $template, а не распаршенный шаблон, и метод View::with() возвращает уже распаршенный шаблон. И вообще, не вижу смысла в методе View::with(), когда скоуп можно передать сразу в View::show() вторым необязательным параметром, ибо незачем плодить лишние сущности.
Да. Но если нам нужно вызвать шаблон без переменных, то мы использует только View::show() без with(). В общем я пришел к выводу, что просто нужен еще один метод, который и возвращает шаблон, и использован где-то в другом месте кода(скрыт подальше от глаз) после того как мы уже добавили данные с помощью View::show()->with() или просто View::show(). Можно конечно. Но мне просто было интересно как в ларавеле обрабатываются такие цепочки. Думал что существует может какая-то возможность "заглянуть в будущее", т.е чтоб при вызовах View::show()->with() я в методе show мог сразу узнать что мне передано в метод with, т.е обработать вызов сзада наперёд грубо говоря...Но это из мира фантастики...
ну вот зачем ты так! если выкинуть это искусственное ограничение, то всё делается без проблем. есть класс с несколькими методами, изменяющими его состояние, т.е. присваивающие значения приватным переменным объекта. каждый метод возвращает $this, поэтому их можно составлять цепочкой в разной последовательности. потом, когда нам понадобится получить результат, например строковое представление шаблона, мы вызовем явный или неявный "конечный" метод, который вернёт уже не $this этого объекта , а нужные данные, сгенерированные на основе его внутренних переменных. для шаблонизатора таким методом может быть _toString(). покажу упрощенно без реализации фасада, т.к. это отдельный класс: PHP: // вызовы методов можно менять местами, а with можно вызвать несколько раз с разными данными, они будут накапливаться // в конце концов echo неявно обратится за строкой к _toString() echo (new View)->show('main')->with(compact('product', 'user')); class View { private $template; private $data = []; public function show($template) { $this->template = $template; return $this; } public function with($data) { $this->data = array_merge($this->data, $data); return $this; } public function __toString() { return $this->render($this->template, $this->data); } // ... } в случае Laravel, контроллер должен вернуть объект соответствующий контракту ViewContract. поэтому в самом контроллере мы не видим вызова render() или чего-то вроде того. этот объект будет использован для рендеринга уже где-то в недрах фреймворка. точно так же работает реализация eloquent / query builder. есть "конечные" методы вроде get() и first(), и есть "присваивающие" методы вроде where() и orderBy(). пока не вызван конечный метод, можно в цепочке вызывать присваиватели в любой очередности. только конечный метод вызовет конструктор запроса SQL на основе сохранённых параметров.
я думаю что в недрах фреймворка происходит что-то такое PHP: // нам нужен объект типа Response, а контроллер может вернуть разные данные // - готовый Response (например RedirectResponse) // - строку // - объект, соответствующий контракту ViewContract $result = $controller->$action(...$params); if ($result instanceof Response) { return $result; } // для объектов приведение к строке вызовет магический метод _toString() return new Response((string) $result);
Хорошо описал. Да, действительно, эти методы нужны по сути для установки данных и должны возвращать ничто иное как текущий объект($this), т.к мы их юзаем в цепочке. А потом где то уже мы просто вызываем явно или неявно метод, который служит для возврата собранных данных. Вроде все просто, но что-то не подумал об этом, а начал надумывать какую-то фигню, чтоб идти по кратчайшему пути) Спасибо за инфу!