Хорошие статьи по шаблонам в PHP

Духовность™

Продвинутый новичок
А вывод из всего этого таков, что проблемы эскейпинга в шаблонах нет, потому что там ничего никода не должно эскейпиться. Это делается в модели.
Модель - ЭТО ДАННЫЕ.
Эти данные могут выводиться в HTML, JSON, YAML, PDF, AMF, CSV, Excel и в командную строку. А ещё в виде азбуки морзе. А ещё в виде радиосообщения. А ещё их можно на магнитную пленку записать. Или высечь роботом на граните.
Любой формат данных, перечисленных выше - это ВИД. И как данные из модели форматировать - задача вида. Модель хранит данные как есть. Её задача - отдать данные в вид и забыть о них.

Предложение эскейпить данные в модели - абсурд. Эскейпить их по какому принципу, если данные одни, а форматов вывода - много?
 

Absinthe

жожо
Возьмем например задачу выдачу сообщения пользователе на форуме. Разрешать ли тэги в нем, решает модель. Фильтрует вредные тэги -- модель. А решать, эсекейпить ли сообщение перед выдачей будет шаблон? С какого хрена?
Данный случай - исключение, т.к. тут особая модель, задача которой напрямую связана с обслуживанием отображения. Кстати это подтверждает и кеширование обработанных данных внутри этой же модели(и это тоже исключение - модели из вида получать обычно нечего, но тут это происходит, что еще раз говорит об исключительности данной ситуации).
Естественно что из любви к правильному MVC можно сделать "как положено в идеальном случае", а не как проще, но... я предпочту как проще и производительнее. Такой вот грязный хак.

Модель - ЭТО ДАННЫЕ.
Большинство склоняется к мнению, что модель - это данные и вся логика, не связанная с http(контроллер) и отображением(отображение).
 

Absinthe

жожо
Chushkin тут дело вот в чем.
Если по умолчанию экранировать, то в случае ошибки будет лишь переэкранированная строка.
Если по умолчанию не экранировать, то в случае ошибки будет уязвимость.

Если бы люди ничего не забывали, то вопрос был бы из области предпочтений.
 

Absinthe

жожо
Chushkin железное правило не железное. Это меня огорчает.
Самое печальное, что бывает как в анекдоте:

Стирает мужик штаны и бубнит: «Вот жизнь пошла, никому нельзя доверять, абсолютно никому даже себе, вот хотел только пукнуть — и вот результат, в штаны насрал.»
 

fixxxer

К.О.
Партнер клуба
Я плохо сформулировал. Не в шаблон raw-данные, а во View.

Вот наверное как-то так, если совсем упрощать:

view.php
PHP:
<?php

class View {

    protected
        $data = array(),
        $charset = 'utf-8',
        $tmpl_path = __DIR__; // real code will need setters for this two...

    public function assign($key, $value) {
        $this->data['key'] = $value;
        return $this;
    }

    public function set(array $data) {
        $this->data = $data + $this->data;
        return $this;
    }

    public function render($template) {
        include $this->tmpl_path . '/' . $template . '.php';
        return $this;
    }

    public function __get($key) {
        return $this->escape($key);
    }

    public function escape($key) {
        // Можно выпендриться с setFormatter(new View_HtmlFormatter / View_JsFormatter ...),
        // для демки будет тупо
        return htmlspecialchars($this->raw($key), ENT_QUOTES, $this->charset);
    }

    public function raw($key) {
        return isset($this->data[$key]) ? strval($this->data[$key]) : '';
    }

}
test.tpl.php
PHP:
html>
<body>
<h1>Test</h1>
<h2>Escaped values:</h2>
<ul>
    <li><?=$this->text?></li>
    <li><?=$this->html?></li>
</ul>
<h2>Unescaped values</h2>
<xmp><?=$this->raw('text')?></xmp>
<?=$this->raw('html')?>
test.php
PHP:
<?php
require __DIR__ . '/view.php';
$View = new View;
$View->set(array(
    'text' => 'Foo "bar" blah',
    'html' => 'The text above is <b>bold</b>.',
));
$View->render('test.tpl');
Код:
$ php -d short_open_tag=1 test.php 
<html>
<body>
<h1>Test</h1>
<h2>Escaped values:</h2>
<ul>
    <li>Foo &quot;bar&quot; blah</li>
    <li>The text above is &lt;b&gt;bold&lt;/b&gt;.</li>
</ul>
<h2>Unescaped values</h2>
<xmp>Foo "bar" blah</xmp>
The text above is <b>bold</b>.
 

Духовность™

Продвинутый новичок
Если Модель/Контролер отвечает за вывод, то форматирование может быть и в нём.
Модель не может отвечать за вывод, как мотор теоретически не знает, на какую марку авто его поставят. Ему все равно.
Контроллер так же не может быть ответственен за вывод, иначе в нем возникнет логика для всех возможных форматов. Легче просто подключать определенный вид (шаблон), который знает как выводит ту или иную переменную.
 

lagoff

Новичок
Решать что делать с данными (эскейпить / неэскейпить ) должен только слой отображения.

1) В идеальном случае при установке состояния экземпляра самого View-класса. Например:
PHP:
class View {
    ...
    public function set($var, $value, $escape = true) {
    
    }
    ...
}
2) В менее идеальном - автоматически эскейпить / неэскейпить всё при установке состояния View. Добивать частные случае в шаблоне с помощью хелперов.
Т.е. если автоматом эскейпим всё , то нужным переменным в шаблоне делаем анэскейп, и наоборот.
Эскейпить или неэскейпить по-дефолту решается в зависимости от задачи или даже от экрана, который рендерится.

З.Ы. Супер-идельный случай с отдельным View-классом под каждый экран не рассматриваю.
 

AmdY

Пью пиво
Команда форума
А я не парюсь и ескейплю сразу когда кладу в базу. Лучше потом разъескейпить, чем недоэскейпить.
 

Absinthe

жожо
AmdY т.е. при работе с любыми текстовыми полями ты их разэскейпиваешь только для того, чтобы не использовать смарти/твиг?
 

AmdY

Пью пиво
Команда форума
Absinthe
не вижу связи со смарти и твигом. я делаю это для того, чтобы заэскейпить один раз, а не каждый раз при вставке в шаблон. для полей с html у меня есть в форме поле richtext или параметр html => true. У моего способа есть один большой недостаток - схема даёт сбой если по ходу дела этот параметр меняется. Но ИМХО, лучше пару раз обработать через костыль исключительную операцию, чем каждый раз выполнять лишнюю работу.
 

AmdY

Пью пиво
Команда форума
Absinthe
я храню только один, в зависимости от типа поля из которого оно пришло. допустим: заголовок новости и краткое описание всегда эскейплю, полное описание не эскеплю или применяю очистку от лишних тегов, разрешая b, i, p, br ...
Как правило неэскейпленные поля допавляются только админами, в всё что приходит от пользователей заворачивается в htmlspecialchars. Чуть что эти данные можно вернуть с помощью htmlentities.

В своё время делал фреймворк с расчётом на то, что им будут пользоваться низкоквалифицированные джуниоры, вот поднакопилось таких идей, как защититься от большинства проблем. Да и сам первое время после перехода с xslt забывал некоторые поля эскейпить, так что учился на своих шишках.
 

lagoff

Новичок
А я не парюсь и ескейплю сразу когда кладу в базу. Лучше потом разъескейпить, чем недоэскейпить.
Гыгыгы, главное анескейп не забыть сделать где-нить в админке =).

Помню, работал на одном проекте, тоже такой же финт провернуть решил. И, естественно, забыл про анэскейп в админке =)
Поначалу все было хорошо, а вот дней через пять у контент-менеджеров, которые забивали довольно большой объем контента после меня, случилась истерика - они никак не могли понять почему после редактирования контента их красивые типографские символы превращаются в &laquo; &quot; . А контента было довольно много, да и структура была не "три поля"...
В общем, все закончилось тем, что пришлось полночи чистить базу от гадостей типа &amp;amp;amp;quot;

С тех пор, я лично зарекся трансформировать таким образом контент по пути в базу.
 

AmdY

Пью пиво
Команда форума
главное не забывать о параметре htmlspecialchars $double_encode, всё остальное ерунда.
 

AmdY

Пью пиво
Команда форума
Вурдалак
конечно, он просто шикарный и вписывается в мою концепцию KISS
 

Вурдалак

Продвинутый новичок
AmdY, т.е. если пользователь захочет ввести «&amp;» (ну, вот к примеру, хочет процитировать проблему с экранированием), то он получит «&»?

Как по мне, так люди добавившие этот параметр, примерно на одном уровне с теми, кто magic quotes ввёл.
 

AmdY

Пью пиво
Команда форума
Вурдалак
ради исключительных ситуаций я не хочу жертвовать 99% нормальных случаев. Если надо разрешить ввод &amp; то нужно просто поменять тип поля на то, где не такие строгие правила. Я выше писал, что не эскейплю АБСОЛЮТНО ВСЕ поля.
 
Сверху