Pull to refresh

приемы работы с шаблонизатором

Reading time3 min
Views1.3K

Вложенный шаблон должен задать title


чаще всего встречал такую проблему: в середине страницы выводится блок, этот блок задает Title, но реально Title уже выведен в head как быть?

решение (Спасибо AlexHamp)

отказываемся от идеи футера и хедера, и переходим к идее вложенных блоков. Остается проблема прегенерации вложенных блоков, она решается так: сначала мы генерируем содержимое вложенных блоков и в них задаем title, а потом выводим в основном шаблоне страницы.

шаблон страницы:
{assign var="pageTitle" value="Мой сайт"}
{if !empty($innerTemplate)}
	{include file=$innerTemplate assign="innerContent"}
{else}
	{assign var="innerContent" value="нет вложеного шаблона"}
{/if}

<HTML>
<HEAD>
    <TITLE>{$pageTitle}</TITLE>
</HEAD>
<BODY>
{$innerContent}
</BODY>
</HTML>

теперь внутренний шаблон:
{assign var="pageTitle" value="Мой сайт: Новости"}
<h1>Новости</h1>
...далее вывод новостей...


Если мы работаем с шаблонизатором типа Квики, с общим пространством имен, то этого вполне достаточно, если же мы работаем со смарти, то нужно сделать в скрипте следующие:
$pageTitle='';
$smarty->assign_by_ref('pageTitle', $pageTitle);

Теперь изменения во внутреннем шаблоне будут происходить с $pageTitle из скрипта, вывод будет осуществляться ее же.

Таким образом мы смогли перенести задачу генерации заголовков во внутренний шаблон.

Генерация данных в шаблоне?


Догадываюсь, что вы подумали: «щас нам покажут спагети код, и мы закидаем этого парня помидорами!». Но спешу вас остановить! речь пойдет о решении задачи связывания отображения и модели с примемлемым разделением оных. Часто нужно повсеместно внедрить на сайте какой-либо блок, возможно, информер, возьму для примера блок, который выводится рядом с ником пользователя (всеми сообщениями, коментами и всеми всеми!)и оторбажает немножко информации о нем (допустим просто время регистрации, и юзерпик). Конечно, некоторые гуру скажут: используй генерацию этих данных прямо в модели! в каждом месте, где ты генерируешь эти логины пользователей, генерируй и сопутствующую информацию! Я с вами соглашусь, а даже дополню, если вы не можете этого сделать — значит архитектура проекта начинает дурно пахнуть, но нам часто нужно работать в не идеальных условиях, и иногда нужно решение, которое не будет заставлять нас рыться, например, в чужом коде, или в «черном ящике». Как писать расширение? первое что приходи в голову — это написать функцию и зарегистрировать ее в смарти потом вызывать, на пример так: {getUserRegDate userlogin=$login} если нам нужно много сопуствующей информации, то решение будет громоздким.

я предлагаю сделать так:
объявить класс, который будет осуществлять доступ к информации, в него включить всю логику по тому как информация извлекается.
class UserInfo(){
    public $regDate;
    public $iniciateStatus=false;
    public iniciate($login){
        if (читаем данные для логина){
           берем данные и записываем их в наш контейнер,
           $this->regDate=...
           $this->iniciateStatus=true;
        }else
             $this->iniciateStatus=false;
    }
}

и подключить его
$smarty->assign(new UserInfo(), $userInfo);

теперь как этим пользоваться в шаблоне?
{if $userInfo->iniciate($login)}
    зарегистрирован {$userInfo->regDate|date_format}
{/if}


теперь следует все это инкапсулировать в подшаблон-блок и вызывать так:
{include file=userInfoBlock login=$login}

В итоге мы получаем достаточно изящное решение проблемы запроса данных в шаблоне из модели, минимально смешивания их.
Это нужно, например, когда мы в процессе работы самого шаблона узнаем, что нам нужны какие-то еще данные от модели. И, как показала моя практика, не всегда это говорит о плохой архитектуре системы.


UPD
Если не нравится без контрольный доступ, то можно его ограничить:
в iniciate делаем assign данных а в шаблоне пишем проще уже:
{if $userInfo->iniciate($login)}
зарегистрирован {$userRegDate|date_format}
{/if}


правда так вы можете получить конфликт имен.
Tags:
Hubs:
+5
Comments68

Articles