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

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

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

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

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

Стирает мужик штаны и бубнит: «Вот жизнь пошла, никому нельзя доверять, абсолютно никому даже себе, вот хотел только пукнуть — и вот результат, в штаны насрал.»
 
Я плохо сформулировал. Не в шаблон 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>.
 
Если Модель/Контролер отвечает за вывод, то форматирование может быть и в нём.
Модель не может отвечать за вывод, как мотор теоретически не знает, на какую марку авто его поставят. Ему все равно.
Контроллер так же не может быть ответственен за вывод, иначе в нем возникнет логика для всех возможных форматов. Легче просто подключать определенный вид (шаблон), который знает как выводит ту или иную переменную.
 
Решать что делать с данными (эскейпить / неэскейпить ) должен только слой отображения.

1) В идеальном случае при установке состояния экземпляра самого View-класса. Например:
PHP:
class View {
    ...
    public function set($var, $value, $escape = true) {
    
    }
    ...
}

2) В менее идеальном - автоматически эскейпить / неэскейпить всё при установке состояния View. Добивать частные случае в шаблоне с помощью хелперов.
Т.е. если автоматом эскейпим всё , то нужным переменным в шаблоне делаем анэскейп, и наоборот.
Эскейпить или неэскейпить по-дефолту решается в зависимости от задачи или даже от экрана, который рендерится.

З.Ы. Супер-идельный случай с отдельным View-классом под каждый экран не рассматриваю.
 
А я не парюсь и ескейплю сразу когда кладу в базу. Лучше потом разъескейпить, чем недоэскейпить.
 
AmdY т.е. при работе с любыми текстовыми полями ты их разэскейпиваешь только для того, чтобы не использовать смарти/твиг?
 
Absinthe
не вижу связи со смарти и твигом. я делаю это для того, чтобы заэскейпить один раз, а не каждый раз при вставке в шаблон. для полей с html у меня есть в форме поле richtext или параметр html => true. У моего способа есть один большой недостаток - схема даёт сбой если по ходу дела этот параметр меняется. Но ИМХО, лучше пару раз обработать через костыль исключительную операцию, чем каждый раз выполнять лишнюю работу.
 
Absinthe
я храню только один, в зависимости от типа поля из которого оно пришло. допустим: заголовок новости и краткое описание всегда эскейплю, полное описание не эскеплю или применяю очистку от лишних тегов, разрешая b, i, p, br ...
Как правило неэскейпленные поля допавляются только админами, в всё что приходит от пользователей заворачивается в htmlspecialchars. Чуть что эти данные можно вернуть с помощью htmlentities.

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

Гыгыгы, главное анескейп не забыть сделать где-нить в админке =).

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

С тех пор, я лично зарекся трансформировать таким образом контент по пути в базу.
 
главное не забывать о параметре htmlspecialchars $double_encode, всё остальное ерунда.
 
Вурдалак
конечно, он просто шикарный и вписывается в мою концепцию KISS
 
AmdY, т.е. если пользователь захочет ввести «&amp;» (ну, вот к примеру, хочет процитировать проблему с экранированием), то он получит «&»?

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