Шаблоны: наследование или блоки?

Фанат

oncle terrible
Команда форума
Догрызаю тему про шаблонизацию.
Большим минусом является то, что я так и не собрался попробовать ни одно из модных веяний (Твиг), но очень в этом деле надеюсь на тех, кто таки пользуется.

Сильно меня заинтересовало наследование.
И я хочу разобраться - удобнее оно вынесения отдельных блоков в отдельные шаблоны, или нет.
по сути, как я понял, наследование - это выделение блоков, но в рамках отдельного файла - так?

С блоками всё ясно - вынес подвал в отдельный блок, и инклюдишь его везде, где он нужен.

А с наследованием?
Скажем, в шаблоне index.html я выделяю некий блок, а потом хочу в шаблоне inner.html использовать этот блок.
Как поступает шаблонизатор в этом случае? Как он понимает, что блок именно из индекса? Как туда за неим лезет?
или я неправильно понимаю принцип наследования вообще?
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Скажем, в шаблоне index.html я выделяю некий блок, а потом хочу в шаблоне inner.html использовать этот блок.
Как поступает шаблонизатор в этом случае? Как он понимает, что блок именно из индекса? Как туда за неим лезет?
или я неправильно понимаю принцип наследования вообще?
В твиге это работает примерно так: В случае наследования, дочерний шаблон может изменить содержимое выбранного блока родительского шаблона, объявив в себе блок с тем же именем, что и родительский. Соответственно, предыдущее содержимое доступно через {{ parent() }}
Так можно изменять содержимое блока несколько раз спускаясь по дереву наследников. В принципе, особо ничем не отличается от обычного наследования классов в пхп.

То, что ты написал, можно сделать через http://twig.sensiolabs.org/doc/tags/use.html, но обычно не нужно. Логичней нужный блок вынести в отдельный темплейт, раз он логически независим.
 

fixxxer

К.О.
Партнер клуба

Духовность™

Продвинутый новичок
Хрень какая-то. По меньшей мере то, что я увидел по ссылке.
Я не вижу преимуществ этого
PHP:
{% block head %}
    {{ parent() }}
    <style type="text/css">
        .important { color: #336699; }
    </style>
{% endblock %}
против этого:
PHP:
<?php include('/tpl/common_header.phtml'); ?>
    <style type="text/css">
        .important { color: #336699; }
    </style>
И я вообще не вижу смысла делать наследование для шаблонов и я уверен, шаблоны нельзя рассматривать с программистским подходом как программный код. Шаблоны - это не код. Шаблон - это монолитная конструкция, которую разбивать нужно в крайне редких случаях, таких как вынесение подвала, шапки и каких-то полностью независимых от основного контента блоков. В остальном играет правило - один контроллер - один шаблон.

Меня вот человек с блюющей кошкой на аватаре обвинил в том, что у меня шаблоны плодятся. А я вот вообще не вижу смысла выносить в наследование или в отдельный файл то, что лежит в теге <head>, т.к. играет правило "один контроллер - один шаблон". И тот же тег <head> содержит в разных шаблонах совершенно разные инструкции подключения как внешних js и css файлов, так и внутренние.
 

Koc

Новичок
и тыща инклюдов подобного хидера, футера, сайдбара и прочих постоянно повторяющихся блоков.
 

ksnk

прохожий
imho, программисту проще понять принципы работы twig, глядя на порождаемый им php-код. Так получается, что каждый файл - отдельный класс php. Каждый шаблон файла - отдельный метод этого класса по полученным данным строящий строку. parent - вызов соответствующего метода parent'а. Наследование - простое наследование php и так далее.Если не совсем ясно что делает та или иная конструкция - нужно ее посмотреть в коде ;)
 

Фанат

oncle terrible
Команда форума
С "подвалом" я, кстати, фигню написал.
Во-первых, обычно его выносить никуда не надо - он и так лежит в скелете основной страницы.
Во-вторых, блоки могут быть ДВУХ типов - динамические и статические.
причем статические - фигня, о них вообще говорить, в сущности, не стоит.
а вот динамические блоки, которые со своими контроллерами - вот это задачка. И средствами одного шаблона её всё равно не решить.
 

С.

Продвинутый новичок
Объясните, что такое контроллер страницы? Что в нем написано?
 

Фанат

oncle terrible
Команда форума
Духовность™
тогда тебе придется делать много отдельных блоков. Это неудобно по двум причинам:
1. каждый блок каждый раз прописывать для каждой страницы. Скажем, у модуля новости есть три шаблона - со списком, с новостью, с тегами. И что - каждлом прописывать хидер, футер и сайдбар? Это получается чудовищное количество дублированного кода. А как же DRY?
2. тупо неудобно верстать и править верстку, когда у тебя хтмл скелета разбросан по блокам. У меня сейчас есть скелетный шаблон, и я с удоволсьтвием его правлю - у меня не висят теги, корректно работает подсветка, я вижу файл целиком, в конце концов. Это, всё-таки, дикость - открывать два файла, если хочешь добавить в скелет один див. Не находишь?

Мне кажется, я нашёл решение лучше - у скелетной страницы тоже должен быть свой контроллер!
таким образом мы убиваем и твоих и моих зайцев - у каждой страницы свой контроллер плюс мы имеем нормальный скелет.

С.
я так понимаю, что речь о Контроллере. обычном контроллере модуля.
 

Духовность™

Продвинутый новичок
контроллер страницы или action в рамках одного контроллера - это то, что реагирует на один конкретный запрос. вот как страница этого форума. Для неё есть некий механизм, который генерирует данные для шаблона, не важно это - контроллер страницы или action. Суть в том, что для этой страницы есть один шаблон, один скелет. Для страницы http://phpclub.ru/talk/ есть другой конкретный шаблон-скелет. И эти шаблоны никак не связаны друг с другом, за исключением стилей, скриптов и правил кодирования. Вот такой способ организации шаблонов - наиболее эффективный, в таком случае код не превратится в бардак.

Скажем, у модуля новости есть три шаблона - со списком, с новостью, с тегами. И что - каждлом прописывать хидер, футер и сайдбар?
В данном случае должно быть три скелета - для списка, для новости, для тегов (я правильно если понял - теги - это просто список тегов).
Хидер (менюшки и пр., все что не в <head>), футер и сайдбары как независимые элементы выносим. Таким образом, имея 3 скелета, мы можем каждую страницу при желании выполнить в совершенно разной верстке/стиле/дизайне.

Вот пример: http://krugozor.svn.sourceforge.net/viewvc/krugozor/Krugozor/Module/Advert/Template/FrontendCategoryList.phtml?revision=26
Меню и шапка подключается через
PHP:
<? include $this->getRealTemplatePath('Common/FrontendTop') ?>
Подвал через
PHP:
<? include $this->getRealTemplatePath('Common/FrontendBottom') ?>
Скелет - один для страницы. Никаких общих скелетов, это отголоски стиля {%CONTENT%}, когда в один скелет пихали весь сайт.
 

Фанат

oncle terrible
Команда форума
Ключевое слово здесь - можем. А ты подменяешь его словом "должны".
Это как с политкорректностью - женщины могут избираться в органы власти наряду с мужчинами. Значит будем натягивать равный процент женщин насильно. подмена понятий.

Так и здесью.
Никто не мешает иметь для одной из страниц отдельный скелет, если он нужен. Контроллер переопределяет основной шаблон - и готово.
Но при этом для 99% страниц отдельный скелет не требуется. Зачем им плодить одинаковые скелеты?
 

С.

Продвинутый новичок
Я понинимаю, что контролер вызывается при обращении к модую/странице. Но я не получил ответа на свой вопрос, что вы в нем пишите?
 

Духовность™

Продвинутый новичок
Но при этом для 99% страниц отдельный скелет не требуется. Зачем им плодить одинаковые скелеты?
Требуется-не требуется, это размышления. А я именно утверждаю - для каждой страницы - свой скелет.
Это избавит в дальнейшем от проблем, связанных с кардинальным изменением структуры или вывода одной из страниц, входящих в основной скелет.
А проблемы будут. И будут они примерно такого плана: вот header реального проекта который по замыслам должен был быть общим. За много лет он разросся до чудовищного состояния
PHP:
   {if $GlobalConfig.iphone}<link rel="stylesheet" href="/new_css/iphone.css" type="text/css">{/if}
   {if $GlobalConfig.ipod}<link rel="stylesheet" href="/ipod.css" type="text/css">{/if}
   {if $GlobalConfig.application}<link rel="stylesheet" href="/app.css" type="text/css">{/if}

   <link rel="stylesheet" href="http://{$GlobalDisplay.HttpHost}/newdesign/css/card.css?v=16112010" type="text/css" />
   <link rel="stylesheet" href="http://{$GlobalDisplay.HttpHost}/newdesign/css/numbers.css" type="text/css" />
    <link rel="stylesheet" href="http://{$GlobalDisplay.HttpHost}/cssandjs/catalog.css" type="text/css" />

	{if $GlobalDisplay.is_cabinet}
	<link rel="stylesheet" href="http://{$GlobalDisplay.HttpHost}/newdesign/css/cabinet.css" type="text/css" />
	<meta http-equiv="X-UA-Compatible" content="IE=edge" /> 
	{/if}
       
	{if $listing==1}
		<link rel="stylesheet" href="/css/listing{if $new_listing}_new{/if}.css" type="text/css"/>
    {/if}
    
    {if $social_image_src || $GlobalDisplay.social_image_src}
    <link rel="image_src" href="{$social_image_src|default:$GlobalDisplay.social_image_src}" />
	<meta property="og:image" content="{$social_image_src|default:$GlobalDisplay.social_image_src}" />
	<meta property="og:title" content="{$ptitle|default:$GlobalDisplay.title|escape}" />
	<meta property="og:description" content="{$meta_description|default:$GlobalDisplay.meta_description|escape}" />    
    {/if}

	{if $GlobalDisplay.coffee_konkurs && $GlobalDisplay.img_id}	
	<link rel="image_src" href="http://{$GlobalDisplay.HttpHost}/upload/coffee-konkurs/{$GlobalDisplay.img_id}.jpg" />
	<meta property="og:image" content="http://{$GlobalDisplay.HttpHost}/upload/coffee-konkurs/{$GlobalDisplay.img_id}.jpg" />  
	<meta property="og:title" content="Моя работа в конкурсе КОФЕМАГИЯ от М.Видео" />
	<meta property="og:description" content="{$GlobalDisplay.meta_description|escape}" />   
	{/if}
	
	{if $GlobalDisplay.work_info.id}	
	<link rel="image_src" href="http://{$GlobalDisplay.HttpHost}/upload/coffee-konkurs/{$GlobalDisplay.work_info.id}.jpg" />
	<meta property="og:image" content="http://{$GlobalDisplay.HttpHost}/upload/coffee-konkurs/{$GlobalDisplay.work_info.id}.jpg" />  
	<meta property="og:title" content="Мне нравится работа в конкурсе КОФЕМАГИЯ от М.Видео" />
	<meta property="og:description" content="{$GlobalDisplay.meta_description|escape}" />   
	{/if}
- это как раз тот случай, когда я утверждал, что всё, что в <head> - это индивидуальный шаблон страницы, который должен быть в одном скелете конкретного обработчика страницы.

Дальше - больше. В общих скелетах начинаются вот такие пляски:
PHP:
{if $GlobalConfig.iphone}
   <div style="height:30px;padding-top:7px;" align="left" class="TahBlack11b">
      <div style="float:left;">
         <div style="float:left;width:40px;"><a href="/"><img src="/imgs/catalog/M.gif" hspace="3" alt="М.Видео" title="М.Видео"/></a></div>
         {if $ptitle || !$index}
            <div style="float:left;width:52px;padding-top:10px;"><a href="/" style="text-decoration:none;">iPhone</a> / </div><h1>{$ptitle}</h1>
         {else}
            <h1>iPhone</h1>
         {/if}

      </div>
   </div><br/>
   {/if}
в конечном итоге скелет превращается в у*щную кашу из кучи if-ов, совершенно не поддерживаемую и воняющую.

А всего-навсего нужно было взять за правило - одна страница - один скелет. И проблем не было.
 

fixxxer

К.О.
Партнер клуба
Вот как раз в приведенном случае с if-ами поможет наследование. :)
 

С.

Продвинутый новичок
За много лет он разросся до чудовищного состояния
Потому, что подход неправильный. В общей шапке кроме всего общего надо просто вставить:
PHP:
<head>
   ...
  {{ dragons gonna be here }}
</head>
Апотом в каждой конкретной странице указывать индивидуальные добавки типа:
PHP:
  AddDragon('<link rel="stylesheet" href="/css/listing.css" type="text/css"/>');
 

Духовность™

Продвинутый новичок
fixxxer
о да! мне удовольствие лазить в base.html и искать там контент того или иного блока. Я уже представляю что получится:
PHP:
{% extends "base.html" %}

{% block title %}Index{% endblock %}
{% block head %}{{ parent() }}{% endblock %}
{% block head2 %}{{ parent() }}{% endblock %}
{% block head3 %}{{ parent() }}{% endblock %}
{% block head4 %}{{ parent() }}{% endblock %}
{% block head5 %}{{ parent() }}{% endblock %}
{% block content %}
   ....
{% endblock %}
тажа каша, вид сбоку.

AddDragon('<link rel="stylesheet" href="/css/listing.css" type="text/css"/>');
Чем это лучше чем тупо прописать тоже самое в шаблоне-скелете конкретной страницы?
 

fixxxer

К.О.
Партнер клуба
Духовность™
У тебя в коде тоже методы init1(), init2() и init3() и за каждым ты ходишь в базовый класс? ;)
 
Сверху