maxsite / cms

MaxSite CMS
https://max-3000.com/
GNU General Public License v3.0
144 stars 64 forks source link

HTML шаблонизатор #46

Closed maxsite closed 9 years ago

maxsite commented 9 years ago

Столкнулся с проблемой, которая пока тормозит дальнейшую разработку. У нас есть ряд файлов, которые содержат логику и представление. Например вывод комментариев или саму форму комментариев. В коде всё переплетено и php и html. По хорошему требуется отделить логику от представления. Обычно для этого используется шаблонизатор. То есть ему скармливаются подготовленные переменные, а в шаблоне вывода прописывается что-то вроде

<p class="comment-info">
    <span class="comment-num">№ <?= $comment_num ?></span> | 
    <span class="url"><?= $comments_url ?> | <?= $comusers_url ?></span>
    <?= $comment_edit ?>
    <?= $comment_approved ?> 
    <span class="date"><a href="#comment-<?= $comments_id ?>" id="comment-<?= $comments_id ?>"><?= $comments_date ?></a></span>
</p>

То есть стандартные короткие php-конструкции, которые не загромождают верстку.

Однако возникают сложности, если требуется использовать при верстке if-условия. Для затравки посмотрите файл shared/type/page/units/page-comment-form.php https://github.com/maxsite/cms/blob/dev/application/maxsite/shared/type/page/units/page-comment-form.php

Здес такая куча и такое переплетение условий, что не так и просто разобраться.

Поэтому моё предоложение: подумать о каком-то простом шаблонизаторе, который упростит синтаксис php-кода и сделает верстку проще.

Чтобы было понятно, приведу пример готового кода для шаблонизатора:

<div class="comments-textarea">

    {% if (is_login()) : %}
        <input type="hidden" name="comments_user_id" value="{{ getinfo('users_id') }}">
        <div class="comments-user">
            {{ tf('Привет') }}, 
            {{ getinfo('users_nik') }}! 
            <a href="{{ getinfo('siteurl') }}logout">{{ tf('Выйти') }}</a>
        </div>
    {% endif %}

    {% if ($comuser = is_login_comuser()) : %}

        <input type="hidden" name="comments_email" value="{{ $comuser['comusers_email'] }}">
        <input type="hidden" name="comments_password" value="{{ $comuser['comusers_password'] }}">
        <input type="hidden" name="comments_password_md" value="1">
        <input type="hidden" name="comments_reg" value="reg">

        <div class="comments-user comments-comuser">

            {% if (!$comuser['comusers_nik']) : %} 
                    {{ tf('Привет!') }}
            {% else %}
                    {{ tf('Привет,') }} <a href="{{ getinfo('siteurl') }}users/{{ $comuser['comusers_id'] }}">{{ $comuser['comusers_nik'] }}</a>!
            {% endif %}

            <a href="{{ getinfo('siteurl') }}logout">{{ tf('Выйти') }}</a>

        </div>

    {% endif %}

Здесь всё очень просто. Есть две управляющие конструкции {{ }} и {% %}

Первая эквивалент <?= ?> Вторая: <?php ?>

Всё остальное — обычный php-синтаксис. При этом в шаблоне можно использовать и его обычные конструкции.

Прошу высказаться по этому вопросу.

maxsite commented 9 years ago

Первый пример с шаблонизатором.

<p class="comment-info">
    <span class="comment-num">№ {{ $comment_num }}</span> | 
    <span class="url">{{ $comments_url }} | {{ $comusers_url }}</span>
    {{ $comment_edit }}
    {{ $comment_approved }}
    <span class="date"><a href="#comment-{{ $comments_id }}" id="comment-{{ $comments_id }}">{{ $comments_date }}</a></span>
</p>

Читабельность кода выше за счет отказа от < и > в php-коде. Угловые скобки это только html.

leonovmax commented 9 years ago

а не будет ли проще в шаблонизаторе реализовать что-то типа:

$tpl->set('{comment_num}', $comment_num);

а оформление уже будет выглядеть:

<span class="comment-num">№ {comment_num}</span>

итд...

leonovmax commented 9 years ago

а для блока использовать что-то типа:

$tpl->block( "[is_login](.*?)[/is_login]", is_login() );

оформлять блок как:

[is_login]
тут отображать то, что для is_login()
[/is_login]
cuprum commented 9 years ago

@maxsite А вот <? ?> и <?php ?> это полные эквиваленты? Тогда можно везде использовать один вариант - {{ }} (или какой нибудь другой).

@leonovmax А если нужно написать условие посложнее? Геморройно :crying_cat_face:.

maxsite commented 9 years ago

Основная проблема смеси php и html — это единые угловые скобки. Именно поэтому в шаблонизаторах исключают php-скобки.

Сам шаблонизатор должен быть очень простым. Если делать какой-то более сложный вариант со своим синтаксисом, то это сильно усложнит и его разработку. Плюс привыкать к новому синтаксису. Если мы берем php, то будут доступны все его возможности.

Вариант {{ }} удобен для набора и годится для самой часто используемой конструкции <?= ?>. Вариант {% %} будет встречаться гораздо реже и тоже визуально выделяется.

vimruler commented 9 years ago

@maxsite, предложение по такому шаблонизатору выглядит разумно и вполне юзабельно. Но проблема обычно не в технологии, а в ленивых людях :) Я правильно понимаю, что без использования шаблонизатора кастомизировать указанные фрагменты шаблона будет нельзя (точнее можно, но в очень ограниченном варианте)?

maxsite commented 9 years ago

Можно. Задача разделить логику от представления. Но в представлении (верстка) всё равно будет встречаться какая-то логика. Например вывод комментария. Там есть аноним, комюзер, юзер. У комюзера может быть указан еще и сайт. Таким образом вывод будет меняться от A до SPAN, причем может одбавляться дополнительное поле-ссылка САЙТ. В во всех этих элементах будет свой css-класс. Задавать где-то отдельно класс, а html-код ещё где-то просто не удобно. Здесь же всё будет в одном месте.

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

<?php
любой php
?>

<a href="{{ $URL }}">{{ $SITE }}</a>

Верстальщик кидает в свой шаблон файл для кастомизации и сам уже решает что ему удобней: чистый php или html-шаблонизатор.

maxsite commented 9 years ago

Добавлю. Шаблонизатор — не глобальная вещь. Он будет использоваться только в предопределенных подключаемых файлах. То есть это точечное использование.

maxsite commented 9 years ago

Покажу готовый код вывода коментария.

<?php if (!defined('BASEPATH')) exit('No direct script access allowed'); ?>

<article class="{{ $a_class }} clearfix">

    <img src="{{ $avatar }}" alt="" class="gravatar right">

    <p class="comment-info">
        <span class="comment-num">№ {{ $comment_num }}</span> | 

        <span class="url">{{ $comments_url }}

        {% if ($comusers_url) : %}
            | <a href="{{ $comusers_url }}" rel="nofollow" class="comuser-url">{{ tf('Сайт') }}</a>
        {% endif %}

        </span>

        {% if ($edit_link) : %}
            | <a href="{{ $edit_link . $comments_id }}" class="comment-edit">edit</a>
        {% endif %}

        {% if (!$comments_approved) : %}
            | <span class="comment-approved">{{ tf('Ожидает модерации') }}</span>
        {% endif %}

        | <span class="comment-date"><a href="#comment-{{ $comments_id }}" id="comment-{{ $comments_id }}">{{ mso_date_convert('d-m-Y H:i', $comments_date) }}</a></span>
    </p>

    <div class="comments_content">{{ $comments_content }}</div>

</article>
<hr>

Алгоритм работы шаблонизатора очень простой. На примере вывода тех же комментариев.

// проверили наличие файла и передали его в mso_get_tmpl()
if ($fn = mso_find_ts_file('type/page/units/page-comments-article-tmpl.php')) 
        $template = mso_get_tmpl($fn);

// теперь в $template готовый php-код для eval()

foreach()
{
    // готовим все php-переменные, которые используются в шаблоне

    // выполняем код шаблона
    eval($template);
}

В шаблоне tmlp по-умолчанию удаляются все табуляторы и двойные переносы строк. То есть оформлять можно с отступами красиво, а сам код будет компактным.

Если есть вопросы и пожелания, то давайте сразу обсудим, чтобы я мог доделать и выложить изменения.

vimruler commented 9 years ago

Если есть вопросы и пожелания, то давайте сразу обсудим, чтобы я мог доделать и выложить изменения.

Код выглядит нормально. Надо пробовать на реальных задачах чтобы что-то более конкретное сказать.

leonovmax commented 9 years ago

Да, выглядит отлично. Чем-то напоминает Twig ) Или это он и есть?

maxsite commented 9 years ago

Нет, не Twig. У нас круче. :-)

Tiahin commented 9 years ago

Поэтому моё предоложение: подумать о каком-то простом шаблонизаторе, который упростит синтаксис php-кода и сделает верстку проще.

Мое предложение - Fenom Статья о нем на Хабре

maxsite commented 9 years ago

Наш получился круче. :-)