Холивар кодера - шаблонизатор для пхп

Тема в разделе "Мегафлуд", создана пользователем KillDead, 9 сен 2012.

  1. KillDead

    KillDead

    Регистр.:
    11 авг 2006
    Сообщения:
    883
    Симпатии:
    540
    Когда то человека задавшегося таким вопросом я бы кинул чемнибуть тяжёлым, но вот сейчас сам задаюсь проблемами шаблонизатора для своей цмс для скрипта, который возможно в будущем будут юрзать и другие. Шаблонизатор - один из вечных холиваров.
    Итак, мой мнение, как среднего кодера не много стоит, почему? потому что обычно мнение отдельного индивидуума ограничено его мировосприятием, а особенно такого *****того как я. Я не вижу ничего сложного в конструкциях аля
    Код:
    core::$readRouter('mail:controller', new Profiler('core'))->getAction()->runApp()->endApp()
    многие вещи которые вызывают страх у обычных людей мне кажутся очень красивым решением где всё разложено по полочкам, пусть и порой длинно.
    Но, сейчас поставил задачу - сделать максимум простую и понятную цмс скрипт.
    Меня интересует в первую очередь мнение верстальщиков, дизайнеров, людей которые больше делают верстку и дизайн, нежели программируют либо вообще ничего не знают. Так что примерно такие вопросы :
    1. Если бы вам предложили сделать шаблонизатор специально для вас, чтобы вы максимально удобно и быстро верстали, какое бы вы дали ТЗ.
    2. Что вас неимоверно бесит когда вы работаете с шаблонизватором Х и чужим кодом.
    3... У меня есть некая квалификация и ещё более узкие вопросы, возможно задам их позже, чтобы не ограничивать ответы (если они будут :) ).
     
  2. chibit

    chibit Life sucks.

    Регистр.:
    4 дек 2007
    Сообщения:
    420
    Симпатии:
    285
    Самый читаемый вариант:
    Код:
    return template('user', form=form, hello='Здравствуйте, {0} {1}'.format(form.firstName.data,  form.lastName.data))
    Код:
    return template('название шаблона', ['user': 'Вася', 'Дата регистрации': '09.09.2012'])
    Обязательно нужно if/endif, for in/endfor, возможно поддержка в шаблоне вызов метода переменной. В идеале чтобы что-то подобное можно было сделать:
    Код:
    {{ form.firstName.label }}: {{ form.firstName(size=30, value=form.firstName.data if form.firstName.errors and form.firstName.data) }}
    Ну и без наследования (подключаем шаблон, который подключает еще один шаблон, который подключает еще один шаблон) сейчас уже никуда, иначе много дублирующего кода в шаблонах. Экранирование тоже нужно:
    Код:
    {{ user.name|safe }}
    Ну и еще все это должно компилироваться в оптимальный PHP код для кеширования.


    Работу с формами уже сделал?
     
  3. KillDead

    KillDead

    Регистр.:
    11 авг 2006
    Сообщения:
    883
    Симпатии:
    540
    У меня вообще идеи немного старомодны- максимально отделить шаблон от скрипта, логику и представление, в вакууме и идеале, чтобы скрипт вообще ничего не знал о шаблоне, а шаблон ничего не знал о сервере (ни какая система использована, ни переменные окружения, ни даже языка). Всё хорошо пока мы занимается простыми вещами, перебором и ифами. Но стоит нам на переферию, где логика и шаблон связаны неразрывно либо взаимоисключаемы и тут начинается поиск альтернативы, причём бескомпромиссной. Пример – активное меню. Верстальщик хочет его отметить и создаёт переменную в шаблоне построенной на логике, возможно которая не будет работать нигде кроме как на страницах с page. { @var = @config[‘pages’][‘cpage’]; if@get[‘page’] = @var} Либо кодер должен залезть в вьювер и определить эту логику. А вдруг он сделает её очень ограниченной для верстальщика, к примеру определит только в массиве с меню .


    Чтобы вызывать методу у переменной - это конечно хорошо, но я вообще разделяю шаблонизаторы на
    1. Скриптовые - смарти и нативный пхп .
    + Можно реализовать всё и просто. Нужна зебра особенная- легко. Прост в понимании и использовании.
    - Мешанина логики и кода. Это далеко не лучший вариант особенно когда видишь в коде
    { $allPages = $page->getPages(); foreach( $allPages->getActive() as $p) { if( $p !== $config['page']){ .... } } }

    И подобные тучные конструкции из какой то логики. Причём порой наблюдаем в шаблоне всякие mysql_query что вообще выбивает из колеи.

    2. xslt вида.
    Это уже не шаблонизатор - это язык шаблонов. Т.е пишем шаблон как скрипт.
    + хорошо структурирован. Нет мешанины, допустили ошибку в верстке- ничего не заработает.
    - Особо сложен в понимании.

    3. Макросные. xtemplates
    Тут минимум функции в шаблоне. Нельзя ничего. Есть всего пара функций, (xtepl даже иф не поддерживает) все переменные текстовые либо массив с текстом .
    + Логика шаблона только в шаблоне.
    - Логика шаблона уже в скрипте. Нам обязательно надо знать как верстальщик сделал шаблон и если он чтото поменяет, нам надо будет переделывать скрипт.

    Тут и делема- всё или ничего не включать в шаблон. Нужна очень жёстная структура либо достаточно простых макросов.


    ----------

    Формы.
    Раньше я бы сказал что только аля зендФорм – тут мы просто боги- и автоматом генерим валидный и верный html, включаем js и серверную валидацию, можем даже тестировать формы автоматом. Но сейчас понимаю – мы залезаем в шаблон. Представьте- верстальщик, мы хотим красивую форму с картинками и бордюрами, вы хотите увидеть структуру? Гуглите, форма генерируется на лету. Хотите изменить порядок форм? Лезте в пхп и меняйте массив с неипической вложенностью и правилами…
    У меня сейчас 2 решения:
    1. Всё таки сделать реализацию зендФорм, но так чтобы она не была очень сильно связана с шаблоном. Т.е можем сделать и генерацию макросом {zendform_login}, либо пишем сами. Тут сложность в магии – мы генерируем чтото, неизвестно нужна ли jsпроверка, да и если мы будем сами формы в шаблоне писать, зачем нам изгаляться и писать их в пхп?
    2. Сейчас просто остановился на правилах. Т.е есть у нас екшен с именем reg, создаём правило с таким же именем и пишем там правила валидации
    Код:
        public function reg() {
            $this->login->notSimpleStr('Недопустимые символы в логине')->notLen(8, 25, 'Логин лишком длинный либо слишком короткий')->chekF(function ($login) {
                        return core::$user->loginExists($login);
                    }, 'Увы, этот логин уже зарегистрирован в системе');
            $this->pass->notSimpleStr('Недопустимые символы в пароле')->notLen(8, 25, 'Пароль лишком длинный либо слишком короткий');
            $this->email->notEmail('Неверное мыло')->chekNotBadEmail('Выберите другой домен для мыла');
        }
    Мы не можем построить настоящую форму, хотя простые – да. Даже с jsвалидацией. Не говоря уж и о серверной. Мне кажется красиво и понятно всё названо – notНАЗВАНИЕ_УСЛОВИЯ(САМО УСЛОВИЕ, МЕССАЖ)
    + пара ещё доработок для удобства.
     
  4. chibit

    chibit Life sucks.

    Регистр.:
    4 дек 2007
    Сообщения:
    420
    Симпатии:
    285
    KillDead, ты не понял суть form.firstName(size=30). Эта конструкция превращается в <input size=30 />, т.е. это всего лишь генератор View.
    Код в шаблоне? WTF? Максимум должна быть возможность определить переменную с помощью шаблонизатора.
    Код:
    {% set active_page = "index" %}
    Есть и третье решение:
    Код:
    <form method="post" action="/form">
        {{ form.firstName.label }}: {{ form.firstName(size=30, value=form.firstName.data if form.firstName.errors and form.firstName.data) }}
    
        {{ form.submit(value="Нажми меня!") }}
        {{ form.csrf_token }}
    </form>
    Что превращается в:
    HTML:
    <form method="post" action="/form">
        <label for="firstName">Имя</label>: <input id="firstName" name="firstName" size="30" type="text" value="">
    
        <input id="submit" name="submit" type="submit" value="Нажми меня!">
        <input id="csrf_token" name="csrf_token" type="hidden" value="20120909135858##2f7b450f33ac21ec0cfae5a0da36020cb892a639">
    </form>
     
  5. KillDead

    KillDead

    Регистр.:
    11 авг 2006
    Сообщения:
    883
    Симпатии:
    540
    дада, это и есть недостаток скриптовых шаблонов- вначале у нас логика может быть хоть и простая, типо определяем из конфига активную страницу, а затем это преращается в то, что мы чють ли не считаем подоходный налог подключая curl и парсим банк, и всё в шаблоне...


    а, я понял, ты предлагаешь аналог типа 2- язык шаблонов, когда html элементы формируется всякими наборами. Но насчёт форм - тут же обычный шаблонизатор, только выводим форму. Или идея аналогична зендформ но форма описывается именно в шаблоне?
     
  6. chibit

    chibit Life sucks.

    Регистр.:
    4 дек 2007
    Сообщения:
    420
    Симпатии:
    285
    В других скриптовых языках либо пиши на шаблонном языке, либо выведется "как есть". Так что вопрос лишь в руках. Или в языке, если руки не из того места. Хотя я именно про это и говорил: PHP сам по себе шаблонизатор.
    Там обычный метод, который возвращает html (с id и class, если в параметрах указать). Сама форма и её тип (text, password) описываются в контроллере.
    Насчет зендформы я хз. Но идея проста: всякие input-ы с помощью методов создаем (возвращающие html, в параметрах можно указать id, class и специфичные для данного типа size, value и т.п.), остальное руками. Быстро и гибко.
     
  7. KillDead

    KillDead

    Регистр.:
    11 авг 2006
    Сообщения:
    883
    Симпатии:
    540
    А ну это же работа с формами никак не отличается с работой с дивами и прочим html. Я просто имелл виду что формы можно вывести отдельно в пхп коды. Получается обеспечение целостности, гибкости, контроля и тп.

    Мне больше всего нравится смарти без всего - аля http://twig.sensiolabs.org или аналог xlst, вернее питоновских штучек http://phptal.org/
     
  8. chibit

    chibit Life sucks.

    Регистр.:
    4 дек 2007
    Сообщения:
    420
    Симпатии:
    285
    Сами формы имеют вид:
    Код:
    class MyForm(SessionSecureForm):
        SECRET_KEY = b'EPj00jpfj8Gx1SjnyLxwBBSQfnQ9DJYe0Ym'
    
        firstName = TextField('Имя', validators=[validators.Length(max=6, message='Не больше 6!')])
        lastName = TextField('Фамилия')
        birthday = DateField('Дата рождения')
        password = PasswordField('Пароль', validators=[validators.Required(message='Введите пароль!')])
        submit = SubmitField()
    Формы (создание, валидация и т.п.) пусть будут на PHP, но View для них нужно делать в шаблонизаторе (с помощью метода-генератора или еще как-то), т.к. я уже натрахался с drupal-ом, который гененировал View форм прямо в контроллере, у него костыли типа:
    Код:
    'prefix' => '<div id='123'>',
    'suffix' => '</div>'