====== Общая схема организация отображения (View). Pull view Vs Push view ====== **View** занимается отображением данных. Подсистема View начиная с релиза 2007.3 вынесена из WEB_APP в отдельный пакет View. В качестве шаблонизатора в Limb3 по-умолчанию используется [[limb3:ru:packages:wact|шаблонная система WACT]]. Со view связаны 2 понятия: * **Объект $view**, который является как бы промежуточным звеном между шаблонизатором и остальной частью приложения. Объект $view создается и хранится в тулките. * **Шаблонизатор**, который получает данные, пославленные во $view и рендерит шаблон, указанный во $view. То, какой шаблонизатор используется зависит от класса объекта $view. ===== Объект $view. Класс lmbView и lmbWactView ===== **$view** - это по сути контейнер с данными, который всегда доступен через toolkit. **lmbView** - базовый абстрактный класс для реализации $view. **lmbWactView** - наследник от lmbView, в качестве шаблонизатора использует WACT. То, что по-умолчанию в Limb3 в качестве $view создается экземпляр lmbWactView определяется реализацией метода [[lmb_web_app_tools|lmbWebAppTools]] :: **getView()**. Переопределив этот метод, вы можете поменять шаблонизатор. lmbView содержит следующие методы: * **setTemplate($template_name)** - устанавливает имя шаблона * **render()** - рендерит шаблон. Абстрактный метод, который должен перекрываться в дочерних классах. Результат работы шаблонизатор возвращается в качестве результата этого метода. * **set($variable_name, $value)** - устанавливает переменную, которая будет передана в корневой контекст шаблона. * **reset()** - сбрасывает все установленные переменные (но не имя шаблона!) lmbWactView дополнительно содержит следующиме методы: * **getWactTemplate()** - возвращает объект класса %%WactTemplate%% * **setFormDatasource($form_name, $datasource)** - устанавливает источник данных для активного компонента формы в шаблоне. * **setFormErrors($form_name, $error_list)** - устанавливает список ошибок валидации для активного компонента формы в шаблоне. * **findChild($id)** - возвращает активный компонент, найденный в WACT шаблон по идентификатору $id В будущих релизах, возможно, методы setFormDatasource и setFormErrors перейдут в класс lmbView. ===== Рендеринг шаблона ===== Советуем прочитать страницу [[filter_chain|Использование цепочки фильтров для организации Front-Controller]], так как там объясняется, как и где происходит реальный рендеринг шаблона. Здесь мы немного повторимся и немного уточним: **рендеринг шаблона происходит** в фильтре lmbViewRenderingFilter, но это происходит лишь в том случае, **если $response является пустым**. $response считается пустым, если ни были вызваны следующие методы класса lmbHttpResponse: * redirect($url) * readFile($file_path) * write($file) * а также если не был установлен статус 304 или 412 Отметим также, что именно в фильтре lmbViewRenderingFilter в шаблон попадают следующие объекты: * $toolkit * $request * $session Последний факт позволяет использовать в WACT-шаблонах следующие конструкции: [...] или Имя = $name, Логин = $login [...] В lmbWebAppTools есть также метод **renderTemplate($template_path)**, который производит рендеринг view "насильно", однако переменные $toolkit, $request и $session в этом случае не передает. ===== PullView vs PushView ===== Существует 2 основных способа передачи данных в шаблоны: - **push view**, когда шаблон ведет себя пассивно и ждет, когда данные ему придут откуда-нибудь (обычно непосредственно из контроллера или из дополнительной прослойки View-helper-ов). - **pull view**, когда шаблоны самостоятельно вытягивают данные из модели (базы данных). В приложениях, построенных на Limb3, возможно использовать оба способа. По мере накопления практики мы пришли к следующему балансу между push view и pull view: * Те данные, которые отображаются исходя из текущего действия контроллера желательно передавать во view из контроллера. Если данных имеют иерархический характер (например, заказ и его позиции), тогда мы в контроллере часто удостоверяемся, что "корень" данных (например, заказ) - может быть получен исходя из Запроса, а остальные данные получаются уже в шаблоне. Если же "корень" данных получить не удается, тогда контроллер обычно или выдает страницу с ошибкой или с 404 сообщением (например при помощи метода lmbController :: forwardTo404()), можно также делать redirect на другую страницу. * Прочие данные (навигация, текущие пользователи, последние события и прочее) - пусть шаблон получает сам. Такая выработанная схема позволила нам отказаться от иерархии View - классов, когда каждому действию или контроллеру соответствует еще 1 View класс (такая архитектура наблюдается в некоторых фреймворках). ==== push view - передача данных по $view из конструктора ==== push view - это концепция, по которой отображение (View) ведет себя достаточно пассивно по отношению к данным, ожидая, что все данные, которые необходимо будет отобразить, должны придти из внешних источников, в отличие от PullView, когда шаблон может затребовать данные самостоятельно. Обычно передачей данных в шаблон занимается контроллер. push view в Limb3 обычно используется для передачи данных с форм (ошибки валидации, первоначальные данные) в шаблон, а также в некоторых других, когда использование pull view нецелесообразно. В lmbController есть следующие средства для передачи данных во $view: * **Все атрибуты класса**, кроме тех, что начинаются с нижнего подчеркивания, **передаются во $view!** * **атрибут $view** - чтобы не вызываеть каждый раз lmbToolkit :: instance()->getView(); * **setTemplate($template_path)** - аналог $this->view->setTemplate($template_path); * **useForm($form_id)** - указывает, что в данный момент этот контроллер будет работать с формой $form_id. Вызывает метод lmbWactView :: setFormErrors($form_id, $this->error_list); * **setFormDatasource($datasource, $form_id = null)** - Передает в активный компонент формы $form_id источных данных $datasource. Алиас для метода lmbWactView :: setFormDatasource($form_name, $datasource). Если ранее был вызо useForm($form_id), то в $form_id для вызова setFormDatasource() можно уже опустить. * **resetView()** - аналог вызова $this->view->reset() * **passToView($var, $value)** - аналог вызова $this->view->set($var, $value). Пример, кода использующего концепцию push view: class FeedbackController extends lmbController { function doSend() { $this->setTemplate('feedback/send_result.html'); if($this->_sendMail()) { $this->resetView(); $this->view->set('success_send', 1); // или просто $this->success_send = 1; // или $this->passToView('success_send', 1); } else $this->view->set('error_send', 1); } protected function sendMail(){[...]} } ==== pull view - получение данных прямо в шаблоне ==== pull view предусматривает, что шаблон вытянет данные самостоятельно. Самый простой способ - это использование php-вставок, в которых вызываются нужные методы для получения данных, а затем вывод этих данных при помощи более "классических" средств шаблонизатора. см. [[limb3:ru:packages:wact:php_code_in_templates|Использование php-кода в WACT-шаблонах]]. В WACT существует такое понятие как fetcher-ы и специальные теги. Fetcher-ы исторически использовались нами для реализации pull-подхода, пока WACT не был научен нормально понимать php-вставки и php-переменные. Рекомендуем почитать: * [[limb3:ru:packages:active_record:in_wact_templates|Использование fetch и active_record:fetch тегов-ов в WACT-шаблонах]] * [[limb3:ru:packages:wact:fetch_tags|Использование ACTIVE_RECORD в шаблонах WACT]] Правда, в конце концов, мы пришли к пониманию того, что теги - несколько ограниченное решение. Возможно, что ситуация с fetcher-ами изменится к релизу 2007.4