25 Laravel Tips and Tricks

http://code.tutsplus.com/tutorials/25-laravel-tips-and-tricks--pre-92818
  • Перевод
Было время, достаточно недавно, когда PHP и его сообщество ненавидели. Главная шутка была про то, насколько ужасен PHP.

Да, к сожалению, сообщество и экосистема просто были ниже сообществ других современных языков по уровню. Казалось, что предназначение PHP было прожить большинство времени в форме беспорядочных тем для WordPress.

Но позже, на удивление, вещи начали меняться — и достаточно быстро. Как будто пока ведьма помешивала горшочек, из ниоткуда начали появляться новаторские проекты. Наверно, самый заметный проект был Composer: наиболее полный менеджер зависимостей для PHP (как Bundler для Ruby или NPM для Node.js). В прошлом PHP разработчики были вынуждены совладать с PEAR (что было страшным сном, на самом деле), сейчас, благодаря Composer, они могут просто обновить JSON файл, и немедленно подтянуть все нужные зависимости. Здесь — профайлер, там — фреймворк для тестирования. Это занимает секунды.

В переполненном мире PHP фреймворков, как раз, когда CodeIgniter начал выдыхаться, фреймворк Laravel Тэйлора Отвелла возник из пепла, чтобы стать любимцем общества. С таким простым и элегантным синтаксисом, создавать приложения с Laravel и PHP было абсолютной забавой! Далее, c четвертой версией фреймворка, полностью использовавшим Composer, наконец-то показалось, что для сообщества все вещи встают на места.

image

Хотите миграций (контроль версий базы данных)? Сделано! Как насчёт мощной реализации Active Record? Конечно, Eloquent сделает всё за вас. Как насчёт возможности тестировать? Безусловно! Маршрутизация (роутинг)? Непременно! Что насчёт хорошо протестированного HTTP слоя? Благодаря Composer, Laravel использует много превосходных Symfony компонентов. Когда доходит до дела, есть все шансы, что Laravel уже это может вам предложить!

image

Раньше PHP был похож на игру Дженга — в одном кубике от того, чтобы развалиться — вдруг, благодаря Laravel и Composer, загорелся свет в конце тоннеля. Так что уберем все намёки, и давайте пороемся во всем, что фреймворк может предложить!

1. Красноречивые запросы*


Laravel предлагает одну из самых мощных реализаций Active Record в мире PHP. Скажем, у вас есть таблица orders вместе с Eloquent моделью Order.
class Order extends Eloquent {}

Мы с легкостью можем выполнить любое количество запросов в базу данных, используя простой и элегантый код PHP. Не надо разбрасываться беспорядочно SQL. Давайте получим все заказы.
Order::all();

Готово! Или, может, эти заказы должны быть отсортированы по дате. Легко:
$orders = Order::orderBy('release_date', 'desc')->get();

А что, если вместо получения записи, нам надо сохранить новый заказ в базу. Мы, конечно, можем это сделать.
$order = new Order;
$order->title = 'Xbox One';
$order->save();

Готово! С Laravel, задачи, которые раньше были громоздкими для выполнения, теперь до смеха просты.

* — Eloquent — название реализации Active Record в Laravel, а также в переводе с английского красноречивый.

2. Гибкая маршрутизация (роутинг)


Laravel уникален тем, что может быть использован разными способами. Предпочитаете более простой и похожий на Sinatra роутинг? Laravel легко может это сделать, используя анонимные функции
Route::get('orders', function()
{
    return View::make('orders.index')
        ->with('orders', Order::all());
});

Это может быть полезным для маленьких проектов и API, но есть большие шансы, что вам понадобятся контроллеры для большинства ваших проектов. Окей, Laravel это тоже умеет.
Route::get('orders', 'OrdersController@index');

Готово! Заметили, как Laravel растет по мере ваших потребностей? Уровень приспособления — вот, что делает фреймворк таким популярным сегодня.

3. Отношения без проблем


Что мы делаем в объектах, когда нужно определить отношения? Например, задача точно принадлежит пользователю. Как это указать в Laravel? Предположив, что нужные таблицы в базе данных созданы, мы только должны обратиться к связанным Eloquent моделям.
class Task extends Eloquent {
    public function user()
    {
        return $this->belongsTo('User');
    }
}

class User extends Eloquent {
    public function tasks()
    {
        return $this->hasMany('Task');
    }
}

Всё готово! Давайте получим все задачи пользователя с id = 1. Для этого нам понадобится всего 2 строчки кода.
$user = User::find(1);
$tasks = $user->tasks;

Впрочем, так как мы указали отношение с обеих сторон, если мы захотим получить пользователя, за которым закреплена данная задача, это также легко сделать.
$task = Task::find(1);
$user = $task->user;


4. Связь формы с моделью


Очень часто, будет полезным связать форму с моделью. Очевидный пример — когда Вы хотите изменить какую-то запись в базе. Связав форму с моделью, мы можем моментально заполнить поля формы данными из базы.
{{ Form::model($order) }}
    <div>
        {{ Form::label('title', 'Title:') }}
        {{ Form::text('title') }}
    </div>
 
    <div>
        {{ Form::label('description', 'Description:') }}
        {{ Form::textarea('description') }}
    </div>
{{ Form::close() }}

Так как форма связана с объектом модели Order, в полях будет отображаться данные из таблицы. Вот так просто!

5. Кеш запросов в базу


Слишком много запросов в базу, и достаточно быстро Ваше приложение может стать, как черная патока. К счастью, Laravel предоставляет простой механизм кеширования этих запросов, используя всего один вызов метода.

Давайте получим все вопросы из базы данных, но при этом закешируем запрос, так как вряд ли эта таблица будет часто изменяться.
$questions = Question::remember(60)->get();

Вот и всё! Теперь, в течение следующего часа, этот запрос будет храниться в кеше, и база будет нетронутой.

6. Композиторы шаблонов


Вы столкнётесь с ситуациями, когда несколько шаблонов потребуют некоторую переменную или кусок данных. Хороший пример этого — навигационное меню, которое отображает список тегов.
Чтобы контроллеры были с минимальным кодом, Laravel предлагает композиторы шаблонов (вьюшек), чтобы управлять такими вещами.
View::composer('layouts.nav', function($view)
{
    $view->with('tags', ['tag1', 'tag2']);
});

Использовав этот кусок кода, в любой момент, когда подгружен файл layouts/nav.blade.php, у него (у файла) будет доступ к переменной $tags.

7. Простая авторизация


Laravel использует очень простой подход к авторизации. Просто передайте массив данных, которые Вы, скорее всего, получили из формы логина, в Auth::attempt(). Если предоставленный массив соответствует тому, что сохранено в таблице users, пользователь моментально будет авторизован.
$user = [
    'email' => 'email',
    'password' => 'password'
];
 
if (Auth::attempt($user))
{
    // пользователь авторизован
}

Что если надо произвести выход при переходе, например на /logout URI?
Route::get('logout', function()
{
    Auth::logout();
     
    return Redirect::home();
});


8. Ресурсы


Работать RESTfully в Laravel также очень легко! Чтобы объявить контроллер ресурс, просто вызовите Route::resource() следующим образом.
Route::resource('orders', 'OrdersController');

Этот код зарегистрирует 8 роутов.

  • GET /orders
  • GET /orders/:order
  • GET /orders/create
  • GET /orders/:order/edit
  • POST /orders
  • PUT /orders/:order
  • PATCH /orders/:order
  • DELETE /orders/:order


Далее, OrdersController может быть сгенерирован из командной строки:

php artisan controller:make OrdersController

В этом контроллере, каждый метод будет соответствовать одному из роутов, описанных выше. Например, /orders вызовет метод index, /orders/create — метод create и так далее.

Теперь у нас есть необходимая сила, чтобы с легкостью строить RESTful приложения и API.

9. Шаблонизатор Blade


Да, PHP по натуре язык шаблонов, но он не стал слишком хорошим. Впрочем, ничего страшного. Laravel предлагает свой движок Blade, чтобы восполнить пробел. Просто назовите ваши шаблоны с расширением .blade.php, и они соответствующим образом будут парситься. Теперь мы можем делать следующее:
@if ($orders->count())
    <ul>
        @foreach($orders as $order)
            <li>{{ $order->title }}</li>
        @endforeach
    </ul>
@endif


10. Средства для тестирования


Так как Laravel использует Composer, мы тотчас имеет поддержку PHPUnit “из коробки”. Установите фреймворк и запустите phpunit из командной строки, чтобы протестировать.

В дополнение к этому Laravel предлагает некоторое количество хелперов для некоторых общих типов функциональных тестов

Давайте проверим, что домашняя страница возвращает код ответа 200.
public function test_home_page()
{
    $this->call('GET', '/');
    $this->assertResponseOk();
}

Или, может, мы хотим проверить, что, когда контактная форма отправлена на сервер, пользователь перенаправлен на домашнюю страницу с сообщением.
public function test_contact_page_redirects_user_to_home_page()
{
    $postData = [
        'name' => 'Joe Example',
        'email' => 'email-address',
        'message' => 'I love your website'
    ];
 
    $this->call('POST', '/contact', $postData);
 
    $this->assertRedirectedToRoute('home', null, ['flash_message']);
}


11. Компонент “Дистанционное управление”


Частью Laravel 4.1, который был выпущен в ноябре 2013, стала возможность написать консольную команду для Artisan, чтобы по SSH подключаться к серверу и выполнять любые действия. Просто используйте SSH фасад:
SSH::into('production')->run([
    'cd /var/www',
    'git pull origin master'
]);

В метод run() передайте массив команд, а Laravel займётся всем остальным! Теперь, так как есть смысл выполнять команды в качестве Artisan команд, вам всего лишь нужно выполнить php artisan command:make DeployCommand и в метод fire() написать нужный код для выполнения деплоя.

12. События


Laravel предлагает элегантную реализацию шаблона Observer, которую вы можете использовать где угодно в Вашем приложении. Подписывайтесь на нативные события, такие, как illuminate.query, или запускайте и слушайте свои собственные.

Продуманное использование событий даст вам много возможностей.
Event::listen('user.signUp', function()
{
    // выполните то, что надо,
    // когда пользователь регистрируется
});

Как и большинство вещей в Laravel, если вы предпочитаете указывать название класса, а не анонимную функцию, вы можете спокойно это сделать. Laravel разрулит всё, используя IoC контейнер.
Event::listen('user.signUp', 'UserEventHandler');


13. Покажите маршруты


image

Приложение растёт, и может стать тяжело посмотреть, какие роуты описаны. Особенно, если Вы не уделяли должного внимания файлу routes.php (например, излишния описания роутов).

Laravel предлагает удобную команду routes, которая покажет все зарегистрированные роуты, наряду с методами контроллеров, которые эти роуты вызывают.
php artisan routes


14. Очереди


Подумайте о событии, когда пользователь регистрируется в Вашем приложении. Скорее всего, произойдет некоторое количество побочных событий. База данных должна быть обновлена, должен увеличиться счёт, письмо приветствия должно быть отправлено, и так далее. К сожалению, такие действия имеют тенденцию занимать много времени.

Зачем заставлять пользователей ждать, пока произойдут эти события, если мы можем отправить выполняться эти события в бекграунде?
Queue::push('SignUpService', compact('user'));

Наверно, самое замечательное, это то, что Laravel превосходно работает с Iron.io “push” очередями. Это значит, что даже не имея опыта работы с воркерами или демонами, мы всё равно можем использовать очереди. Просто опишите роут с помощью команды php artisan queue:subscribe, и Iron.io будет отправлять данные на этот урл каждый раз, когда задача отправлена в очередь. А этот роут в свою очередь выполнит нужные действия.
image

15. Простая валидация


Когда нужна валидация, Laravel снова приходит нам на помощь! Используя класс Validator как нельзя просто. Просто передайте объект для валидации вместе с правилами в метод make, а Laravel сделает всё остальное.
$order = [
    'title' => 'Wii U',
    'description' => 'Game console from Nintendo'
];
 
$rules = [
    'title' => 'required',
    'description' => 'required'
];
 
$validator = Validator::make($order, $rules);
 
if ($validator->fails())
{
    var_dump($validator->messages()); // validation errors array
}



16. Tinker


image

Особенно, если вы используете Laravel в первый раз, может быть полезным повозиться с ядром. Команда tinker поможет с этим.

Tinker использует популярный компонент Boris.

$ php artisan tinker

> $order = Order::find(1);
> var_dump($order->toArray());
> array(...)


17. Миграции


Думайте о миграциях, как о контроле версий базы данных. В любой момент, вы можете “откатить” миграции, вернуть их, обновить, и так далее. Наверно, сила миграций таится в том, чтобы запушить приложение в продакшн и просто выполнить команду php artisan migrate, чтобы сконструировать базу данных.

Чтобы приготовить схема для новой таблицы users, мы можем выполнить:
php artisan migrate:make create_users_table

Команда сгененерирует файл миграции, который вы наполните так, как вам нужно. Как будете готовы, команда php artisan migrate создаст таблицу. Вот и всё! Нужно откатить изменения? Легко! php artisan migrate:rollback.

Вот пример таблица для таблицы ЧаВО.
public function up()
{
    Schema::create('faqs', function(Blueprint $table) {
        $table->integer('id', true);
        $table->text('question');
        $table->text('answer');
        $table->timestamps();
    });
}
 
public function down()
{
    Schema::drop('faqs');
}

Обратите внимание, что метод drop() выполняет обратные действия метода up(). Это то, что позволяет “откатить” миграцию. Не правда ли, что это намного легче, чем мучаться с чистым SQL?

18. Генераторы


Laravel предлагает некоторое количество генераторов. Но также есть пакет, который называется “Laravel 4 Generators”, и он зашел еще дальше. Он может генерировать ресурсы, файлы для наполнения базы, pivot таблицы и миграции.

В предыдущем пункте мы вынуждены были сами писать схему. Но используя пакет генераторов, мы можем выполнить команду:

php artisan generate:migration create_users_table --fields="username:string, password:string"


А генератор сделает всё остальное. С этой командой вы сможет подоготовить и создать новую таблицу в базе.
Laravel 4 Generators может быть установлен через Composer.

19. Консольные команды


Уже было описано некоторое количество случаев, когда полезно будет написать кастомные команды. Их можно использовать при построении приложений, генерации файлов, деплое приложений и все остального.

Так как это распространенная задача, Laravel делает процесс создания команд наиболее простым.
php artisan command:make MyCustomCommand

Это команда сгенерирует нужный шаблон для Вашей кастомной команды. Далее, в только что созданном файле app/commands/MyCustomCommand.php, заполните название и описание.
protected $name = 'command:name';
protected $description = 'Command description.';

И, в методе fire() выполните нужные действия. После этого останется только зарегистрировать команду для Artisan, в файле app/start/artisan.php.
Artisan::add(new MyCustomCommand);

Хотите верьте, хотите нет, но это всё! Теперь вы можете вызывать эту команду из терминала.

20. Тестируйте фасады


Laravel много использует шаблон Фасад. Это даёт возможность использовать “статический” синтаксис, который, без сомнений, Вам понравится (Route::get(), Config::get(), и так далее), и при этом позволяет полностью тестировать их.

Так как “лежащий в основе” класс разруливается через IoC контейнер, мы легко можем подменить “нижние” классы с нашими тестовыми. Это позволяет нам делать следующее:
Validator::shouldReceive('make')->once();

Да, мы вызываем shouldReceive прямо из фасада. “За кулисами”, Laravel использует фреймворк Mockery. Это значит, что Вы абсолютно спокойно можете использовать фасады, и при этом тестировать абсолютно все куски кода.

21. Хелперы форм


Так как построение форм часто бывает громоздкой задачей, в дело вступает построитель форм в Laravel, чтобы облегчить этот процесс, а также использовать некоторые “особенности стиля”, связанные с конструированием форм. Вот несколько примеров:
{{ Form::open() }}
    {{ Form::text('name') }}
    {{ Form::textarea('bio') }}
    {{ Form::selectYear('dob', date('Y') - 80, date('Y')) }}
{{ Form::close() }}

Что насчёт задачи запоминания введенных данных при прошлой отправке формы? Laravel это делает автоматически!

22. IoC контейнер (Inverse of control)


В ядре Laravel находится мощнейший IoC контейнер, который является инструментом, помогающим в управлении зависимостями класса. Стоит заметить, что у него есть мощь автоматически определять нужные классы без предварительных настроек.

Просто сделайте typehint ваших зависимостей в конструкторе, и при инициализации Laravel, используя PHP Reflection API, грамотно прочитает ваши подсказки и постарается вставить эти классы за вас.
public function __construct(MyDependency $thing)
{
    $this->thing = $thing;
}

Пока вы запрашиваете класс из IoC контейнера, разрешение зависимости произойдет автоматически.
$myClass = App::make('MyClass');

Важно заметить, что контроллеры всегда запрашиваются из IoC контейнера. Поэтому вы можете свободно делать typehint для зависимостей ваших контроллеров, а Laravel постарается внедрить их.

23. Окружения


Одно окружение может подойти для маленьких проектов. Для других проектов, несколько окружений — жизненно важно! Разработка, тестирование, продакшн. Всё это жизненно важно и каждое окружение требует своих настроек.

Возможно ваше тестовое окружение использует базу данных в памяти для тестирование. Может ваше dev окружение использует другие ключи API. А продакшн окружение использует свои настройки подключения к базе.

К счастью, Laravel снова облегчает нашу работу. Взгляните на файл bootstrap/start.php.

Там находится простая демонстрация настройки local окружения, которое базируется на hostname компьютера.
$env = $app->detectEnvironment(array(

	'local' => array('your-machine-name'),

));

В общем, это будет работать. Но предпочтительнее использовать переменные окружения для таких вещей. Не беспокойтесь, это легко сделать в Laravel! Просто передайте функцию в метод detectEnvironment.
$env = $app->detectEnvironment(function()
{
    return getenv('ENV_NAME') ?: 'local';
});

Теперь, если переменная окружения не задана (а для продакшна Вы её установите), окружение будет иметь значение local.

24. Простая настройка


Laravel опять таки использует очень простой подход к конфигурированию. Создайте в папке app/config папку с названием окружения, и любые файлы конфигурации в этой папке будут иметь приоритет над другими, при условии, что вы находитесь в этом окружении. Например, можно задать другой API ключ для dev окружения.
<?php // app/config/development/billing.php
 
return [
    'api_key' => 'your-development-mode-api-key'
];

Конфигурация полностью автоматическая. Просто вызовите метод Config::get(‘billing.api_key’) и Laravel сам определит из какого именно файла, считать это значение.

25. Обучаемость


Когда дело доходит до обучения, Laravel сообщество бесконечно хорошее, несмотря на маленький возраст. В течение чуть более года, были опубликованы полдюжины разных книг, связанные с разработкой на Laravel.
Поделиться публикацией
Похожие публикации
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 190
  • –1
    «Когда дело доходит до обучения, Laravel сообщество, несмотря на маленький возраст, бесконечно хорошее».
    «В течение чуть более года, полдюжины разных книг, связанных с разработкой на Laravel, были опубликованы».

    Издеваетесь?
    • +4
      Перечитал, осознал, что звучит не очень. Переписал. Спасибо!
      • +5
        Пожалуйста, давайте грамматику в личку.
        • +1
          Сложно было им в личку написать, чтобы грамматику в личке обсуждали?
          • +3
            Нет, не сложно.
            Просто ветка обсуждения уже стартовала, это раз. И к сведенью остальных, что бы не спамили ЛС-ками я написал публично, это два.
            • +1
              Скажем прямо, для этого текста никакой лички не хватит.
              «Переписанный» вариант оказался чуть ли не хуже изначального.
              Тут, правда, не в грамматике дело — переводчик попросту не знает языка, на который взялся переводить.
              Это-то и ужасно.
      • +4
        Да, PHP по натуре язык шаблонов, но он не стал слишком хорошим. Впрочем, ничего страшного. Laravel предлагает свой движок Blade, чтобы восполнить пробел. Просто назовите ваши шаблоны с расширением .blade.php, и они соответствующим образом будут парситься. Теперь мы можем делать следующее:
        @if ($orders->count())
            <ul>
                @foreach($orders as $order)
                    <li>{{ $order->title }}</li>
                @endforeach
            </ul>
        @endif
        


        Да ладно, не стал хорошим? Чего недостаточно в пхп, что есть в шаблонизаторах? Кроме отсутствия нормальной подсветки синтаксиса, разве? Вот любят же люди все усложнять на пустом месте…
        <?php if ($orders->count()): ?>
            <ul>
                <?php foreach($orders as $order): ?>
                    <li><?= $order->title ?></li>
                <?php endforeach; ?>
            </ul>
        <?php endif; ?>
        
        • +2
          Никто вам не запрещает в Laravel писать таким образом. Blade или Native — это дело вкуса!
          • +2
            Возьмем twig, у него приятный синтаксис, куча синтаксического сахара, а код ниже будет эквивалентен:
            <ul>
            {% for order in orders %}
                <li>{{order.title}}</li>
            {% else %}
            <li class="no-records">No records</li>
            {% endfor %}
            <ul>
            


            <ul>
            <?php if ($orders->count()): ?>
                    <?php foreach($orders as $order): ?>
                        <li><?= htmlentities($order->title) ?></li>
                    <?php endforeach; ?>
            <?php else: ?>
            <li class="no-records">No records</li>
            <?php endif; ?>
            </ul>
            


            А что говорить о том что он очень легко расширяется, добавить свои синтаксические конструкции очень просто, что делает его идеальным для интеграции в различные инструменты. И при том после компиляции шаблонов он все еще сохраняет скорость plain php.
            • +3
              У Twig покамест к тому же еще и поддержка IDE нормальная в отличие от Blade.
              • +1
                Для Sublime Text точно есть плагин. Для PHPStorm, вроде, тоже когда-то видел. Что еще надо?
                • 0
                  дайте, пожалуйста, ссылку на PHPStorm плагин, я не нашёл.
                  • +2
                    Если не ошибаюсь, то вот. Но я лично его не пробовал еще.
                    github.com/outofcontrol/Blade.tmbundle
                    • 0
                      Пробовал его. Возможно, надо его поковырять, но у меня он дает только подсветку. Даже фигурные скобки не дополняет в отличие от того же Twig. Ну, и PHP не распознает.
                      • 0
                        Дык, это модуль под textmate, то есть, там реализована только подсветка синтаксиса. Но в шторме с этим бандлом все еще хуже — отваливается нормальная подсветка html и отваливается emmet.
                      • 0
                        В том смысле, что автодополнения нету.
                  • +1
                    это дело времени
                  • +1
                    В Blade тоже можно добавлять свои конструкции. Плюс в {{ }} можно использовать php.
                  • +2
                    Отсутствие автоэкранирования — уже достаточная причина, чтобы поставить на PHP как на шаблонизаторе крест.
                    • +1
                      В Laravel можно написать {{{ }}} и данные будут экранироваться.
                      • +10
                        нужно больше фигурных скобок!
                        • +2
                          Ну вот кстати это тоже неправильно. Автоэкранирование должно быть в дефолтном операторе, а всё остальное — опция.
                          то есть, всё должно быть наоборот — в Laravel пишем {{{ }}} по дефолту, а можно написать {{ }}, если надо вывести данные как есть. А вообще определять вывод количеством скобочек — это мина замедленного действия
                          Эта ерунда с подсчетом скобочек еще аукнется многочисленными XSS-ами.
                          • 0
                            Так в документации и написано:
                            Пишем {{{ $name }}}, но если не хотите, чтобы срабатывало экранирование пишите {{ $name }}
                            • +2
                              мне больше нравится twig в этом плане:
                              {{name | raw}}
                              • 0
                                Вот да — так совершенно отдельное усилие требуется для вывода «как есть». А скобочки считать — это фигня какая-то.
                            • 0
                              Как в Handlebars, да. У Тейлора была отличная возможность сделать будущие проекты безопаснее (хотя бы по части XSS), но он почему-то решил продолжить эту традицию и сделал все наоборот. Никак для «обратной совместимости» с v3…
                              • 0
                                Мне кажется как раз с обратной совместимостью Тейлор не заморачивался (и это хорошо).
                                v4 во многом отличается от v3 (взять хотя бы полный переход на composer) в лучшею сторону.
                                • 0
                                  Все верно, именно поэтому я взял «обратную совместимость» в кавычки — решение с Blade совершенно не понятно. Можно объяснить только тем, что Тейлор не видит с XSS каких-либо проблем, как до 4.2 не видел проблем с «зашифрованной» кукой laravel_remember.
                            • 0
                              А где тут автоэкранирование? Автоэкранирование — это когда работает без всяких скобок.
                              • 0
                                скобки — оператор вывода. А уже при выводе должно быть автоэкранирование. В twig-е есть синтаксическая конструкция для эскейпа блоков.
                            • +1
                              Может быть экранированные данные требуется выводить чаще, чем неэкранированные. Могу даже предположить, что иногда автоэкранирование это удобно.

                              Тем не менее я бы считал автоэкранирование злом, если бы оно было по умолчанию PHP. Не должен шаблонизатор за меня решать надо или не надо экранировать.
                              • +1
                                Должен-должен.
                                Это как в SQL — по умолчанию все передаваемые данные обрабатываются как строки. Любые исключения надо оговаривать специально. Иначе проблем не избежать
                                • 0
                                  Хорошо иметь удобную возможность экранировать. Как это реализовано — дело другое. В классе View фреймворка, через функцию типа _e, как ниже в комментариях или еще как-то.

                                  Но <?= или echo/print не должны экранировать ничего.
                                  • +1
                                    Если должен, то как шаблонизатор узнает, каким именно образом надо экранировать строку? В контексте HTML-текста, HTML-атрибута или, к примеру, значения переменной в Javascript экранирование должно быть разным.
                                    • 0
                                      Вот — это очень дельный комментарий.
                                      В отличие от SQL, в котором неверное форматирование не приведет к проблемам в безопасности, а, в худшем случае — просто к ошибке приложения, в HTML не так всё просто.

                                      Я так думаю, что для дефолтного искейпинга надо применять более расширенный набор символов, чем тот, который используется в htmlspecialchars().
                                      • +1
                                        В таком случае «расширенным» экранированием будет «биться» весь вывод в контексте, отличном от конетекста по умолчанию. Я думаю, это не выход.

                                        Представьте, что HTML-текст по умолчанию экранируется через mysql_escape_string(). Или наоборот :-).
                                        • 0
                                          Выхд-выход.
                                          Это то, о чем я говорил выше. Безопасность важнее функциональности.
                                          Всё правильно — выше описана, в сущности, идеальная модель разработки:
                                          — по умолчанию всё форматируем наиболее безопасным способом
                                          — для отличного контекста специально выставляем соответствующий контексту фильтр
                                          — если разработчик зевнул и не выставил, то вывод бьётся
                                          — не беда — когда разработчик это замечает, то просто добавляет соответствующий фильтр
                                          • 0
                                            Да, что-то в этом есть. Интересно было бы посмотреть на фильтр, который бы делал строку безопасной для любого из возможных контекстов, но при этом сохранял вывод максимально близким к оригиналу.
                                            • 0
                                              Ну вот, к сожалению, в HTML я не очень силён, моя идея происходит от обработки параметров в SQL, где это работает 100%.

                                              Но вообще, если говорить о выводе в HTML, то если любые спецсимволы конвертировать в HTML-сущности, то проблемы близости к оригиналу быть не должно, вроде бы.
                                              • 0
                                                В том-то и беда, что HTML-шаблонах бывает не только HTML, но и Javascript. И к нему никакие HTML-сущности неприменимы. К примеру, для js-строки нужно экранировать символ перевода строки, а для HTML-строки — открывающую угловую скобку. Если по умолчанию мы будем делать и то, и то, то по умолчанию будут «биться» и js-строки (заменой < на "), и многострочные HTML-строки (заменой перевод строки на "\n").

                                                В любом случае придётся указывать контекст — сразу же или до первого бага.
                                                • 0
                                                  Парсер сожрал HTML-мнемонику для открывающей угловой скобки. Ну вы поняли.
                                                  • 0
                                                    Ну я ж об этом и говорю — надо. Надо указывать контекст.
                                                    Но нам важно, чтобы даже и без указания контекста, выводимая переменная если уж не принесла пользы — то хотя бы не навредила. Я об этом выше и говорил. С тем, что надо указывать контекст, никто не спорит.
                                                    • +1
                                                      Почему бы тогда не сделать указание контекста обязательным, если заведомо известно, что безопасное экранирование побьёт вывод? То есть, ситуация «без указания контекста» не имеет смысла в принципе.
                                                      • 0
                                                        Вообще, мысль интересная.
                                                        Но работать не будет.
                                                        Разработчики будут по умолчанию лепить контекст «HTML» и пропускать JS-инъекции.
                                                        • +1
                                                          если заведомо известно, что безопасное экранирование побьёт вывод?

                                                          Совсем даже не известно. Единственный случай, когда пострадает вывод — это описанный вами вывод в JS. Часто вы генерите JS в шаблоне? Если да — у вас ошибка в архитектуре. Если нет — автоэкрарование [HTML] для вас логичный выход. Для оного достаточно экранировать всего три символа, если совсем лень
                                                          < & "
                                                          • 0
                                                            Часто вы генерите JS в шаблоне? Если да — у вас ошибка в архитектуре.

                                                            Многие CMS позволяют вставлять JS в материалы/шаблоны в админке, что вы видите в этом плохого? Это позволяет не обращаться каждый раз к разработчику проекта для элементарных скриптовых вещей, а JS все еще является и скриптовым языком. И любой мало-мальски разбирающийся админ может сделать кнопочку с onclick. Именно поэтому:
                                                            Для оного достаточно экранировать всего три символа, если совсем лень
                                                            < & "

                                                            Не все так однозначно.
                                                            Во-первых, HTML документация не обязывает нас использовать именно кавычки. Появляются еще и апострофы, которые могут быть и частью аттрибута. Хотя вы наверное опять скажете что-то про архитектуру или code-style.
                                                            Во-вторых, аттрибуты событий, аттрибут style.
                                                            В-третьих, экранировать в input value что-то кроме кавычек тоже может быть не нужно.
                                                            В-четвертых, a href опять же как бы не вышло двойное экранирование амперсанда (urlencode и html).
                                                            • +1
                                                              Многие CMS позволяют вставлять JS в материалы/шаблоны в админке, что вы видите в этом плохого?

                                                              В этом — ничего, и это именно тот случай, когда нужно использовать сырой вывод. Но это один из немногих use case в сравнении с другими — вывод отдельный компонентов страницы (заголовок, имя, телефон и т.д и т.п).

                                                              Что будет, если вы напишете JS-код в WYSIWYG-редакторе (WordPress например)? Правильно, он будет выведен как текст. Точно так же вы указываете шаблонизатору, что вы знаете что делаете и что это сырой HTML, который вы прямо интерполируете в тело страницы.

                                                              Во-первых, HTML документация не обязывает нас использовать именно кавычки.

                                                              Не обязывает, зато 100% предотвращает XSS во всякого рода . Экономия — 5 байт на каждую кавычку, что несерьёзно.

                                                              Появляются еще и апострофы, которые могут быть и частью аттрибута.

                                                              … и они тоже должны быть экранированы.

                                                              Во-вторых, аттрибуты событий, аттрибут style.

                                                              … в которых они также экранируются, так как являются обычными атрибутами тега.

                                                              В-четвертых, a href опять же как бы не вышло двойное экранирование амперсанда (urlencode и html).

                                                              URL-encoding и HTML никоим образом не пересекаются. Если амперсанд — часть значения переменной (типа ?field=value) — он будет заменён на %26. Если часть URL (?smth&smth) — будет заменён на & что есть верное поведение:
                                                              <a href="?a&amp;b">
                                                              


                                                              Возьмите W3C validator, вбейте туда:
                                                              <!DOCTYPE html>
                                                              <html><body>
                                                              <a href="a.html?b&c">
                                                              </body></html>
                                                              


                                                              И получите:
                                                               & did not start a character reference. (& probably should have been escaped as &.)
                                                              
                                  • 0
                                    У нейтив ПХП есть один очень серёьзный недостаток — невозможно сделать нормальный авто-искейпинг.
                                    А это, пожалуй, в шаблонизаторе главное.

                                    «приятный синтаксис», «экономия целых двух символов на оператор» — это всё ерунда. А вот собственный оператор вывода, которым можно управлять — это очень, очень важно.

                                    Ведь на самом деле в нейтив должно быть что-то вроде
                                    <li><?=_e($order->title) ?></li>
                                    

                                    — а с таким довеском идея как-то уже меркнет.

                                    В какой-то мере можно рассматривать {{ $order->title }} как аналог плейсхолдера в SQL. А <?=$order->title ?>, соответственно — как прямую интерполяцию, со всеми вытекающими.
                                    • 0
                                      Это очень просто решается:
                                      function _e($content ='') {
                                       ... эскейпинг, транслейт и все все все.
                                      }
                                      
                                      • +1
                                        Ну вот это «очень легко решается» и проблема.
                                        Кто-то стал решать, но не зная технологии, насовал в _e() кучу бесполензного мусора.
                                        Кто-то вообще не знал, что что-то решать надо.
                                        Кто-то знал, да забыл.

                                        В общем — типичный «пхп-стайл», и типичный же результат, ЕВПОЧЯ.

                                        Я не зря привел аналогию с SQL — там эти баталии на тему «легко решается» уже (надеюсь) отгремели, и все согласились наконец-то, что ручное экранирование должно быть забыто как страшный сон.
                                        • +1
                                          Возможно стоит поднять этот вопрос в core-комьюнити, о возможности дефолтного фильтра в echo|print* функциях.
                                          • 0
                                            Это очень скоропалительный комментарий, не проходит проверку практикой.
                                            Как раз в PHP, как языке общего назначения, так делать ни в коем случае нельзя.
                                            Ведь проблема касается только одной ипостаси, РНР-как-шаблонизатора.

                                            правда, для <?=?> оно с одной стороны, идеально подходит, но с другой — настолько ломать обратную совместимость — я думаю, невозможно.
                                            • +1
                                              Возможность не подразумевает переопределение поведения по-умолчанию, можно реализовать это так-же как и с ошибками, что нибудь вроде register_output_filter
                                      • +1
                                        Не понимаю откуда берется мысль, что в нативном PHP нельзя сделать авто-escape? Я не за этот вид шаблонизации, но ведь способов чуть меньше миллиона?

                                        function a($vars)
                                        {
                                            foreach($vars as $key => &$value)
                                            {
                                                $value = ЛЮБОЙ_ЭСКЕЙПИНГ($value);
                                            }
                                            extract $vars;
                                            unset($vars);
                                            require 'template.phtml';
                                        }
                                        


                                        $vars = get_defined_vars();
                                        foreach($vars as $key => $value)
                                        {
                                             $$key = ЛЮБОЙ_ЭСКЕЙПИНГ($value);
                                        }
                                        

                                        И так далее?
                                        • 0
                                          Вот он, самый простой шаблонизатор :D
                                          • +1
                                            Беда в том, что как раз в приведённом выше примере мы имеем объект $order, и это очень показательно.
                                            А объекты — штука тонкая. К моменту попытки автоискейпинга объект может ещё не знать, что у него такое свойство есть.
                                            Или вообще его не иметь.

                                            Ну то есть да — если заставить разработчика передавать в шаблон только скаляры и массивы — это работает.
                                            Но, увы, я еще не встречал ни одного, который бы не хотел передать в шаблон объект $user и уже в шаблоне обращаться к его свойствам/методам. Хотя сам считаю это порочной практикой.
                                            • +1
                                              В чем проблема вообще не понимаю)

                                              	class Templater
                                              	{
                                              		public function render($file, $vars)
                                              		{
                                              			$vars = $this->evalVars($vars);
                                              			extract($vars);
                                              			unset($vars);
                                              			require $file;			
                                              		}
                                              		protected function evalVars($vars)
                                              		{
                                              			$export_vars = array();
                                              			foreach($vars as $key => $var)
                                              			{
                                              				switch(gettype($var))
                                              				{
                                              					case 'object':
                                              						$export_vars = array_merge($export_vars, array( $key => $this->evalVars(get_object_vars($var))));
                                              					break;
                                              					case 'array':
                                              						$export_vars = array_merge($export_vars, array( $key => $this->evalVars($var) ));
                                              					break;
                                              					default:
                                              						$export_vars = array_merge($export_vars, array($key => $this->prepareVar($var) ));
                                              				}
                                              			}
                                              			return $export_vars;
                                              		}
                                              		protected function prepareVar($var)
                                              		{
                                              			return $var . 'ЧТО_УГОДНО';
                                              		}
                                              	}
                                              	$templater = new Templater;
                                              	$order = (object)(array('id' => 1, 'amount' => 5));
                                              	$vars = array('order'=>$order);	
                                              	$templater->render('template.phtml',$vars);
                                              
                                              • +1
                                                А если вам одну переменную НЕ НАДО эскейпить?
                                                • 0
                                                  Ну это-то как раз просто.
                                                  Переменные в шаблон в любом случае должны передаваться какой-нибудь tmpl::set() — и вот у этой функции должен быть дополнительный параметр, который, скажем, делает переменную свойством специального объекта, или помещает в отдельный список — способов много.
                                                  • 0
                                                    То есть передаем 2 набора параметров в шаблон: ескейпенные и неэскейпенные?
                                                    • 0
                                                      Я думаю, в хорошем приложении наборов должно быть больше.
                                                      «неэскейпенные» — это, на самом деле, частный случай, один из фильтров.
                                                      Но фильтров может быть много — urlencode, JSON к примеру.
                                                      • +2
                                                        Короче, в погоне за конями в вакууме вы понаделали кучу костылей. Не говоря уже о том, что обрабатывать данные, если мы еще не знаем, понадобятся они или нет, плохая практика. Испульзуйте нормальный шаблонизатор, жить станет намного лучше. Кроме ескейпинга там еще много разных плюшек. Я тоже раньше хейтерил шаблонизаторы, потом попробовал Твиг и теперь не могу соскочить.
                                                        • 0
                                                          Не понял, при чем здесь противопоставление «нейтив — шаблонизаторы».
                                                          Очевидно же, что разговор здесь идет о шаблонизаторах вообще, любых.
                                                          Все описанные выше принципы относятся к «шаблонизаторам» в той же самой мере. В них точно так же должна быть поддержка фильтров, которая должна иметь ту или иную внутреннюю реализацию. Вот варианты реализации фильтров мы и обсуждаем здесь.

                                                          На момент вызова tmpl::set() мы вообще не знаем, какой конкретно синтаксис в шаблонизаторе используется — нейтив или самопал. И не должны знать, по-хорошему.
                                                          • 0
                                                            Начиналось все с холивара «Нейтив — шаблонизаторы» =) habrahabr.ru/post/222453/#comment_7576125

                                                            По теме: переменная должна эскейпиться, если не указано иное. Эскейпить (или накладывать какой угодно фильтр) мы должны в момент вывода пременной на экран из соображений быстродействия. Чистый PHP такое, насколько я знаю, не умеет.
                                                          • 0
                                                            Я тупанул выше.
                                                            В «шаблонизаторах» мы как раз имеем inline-форматирование, когда фильтр накладывается уже перед самым выводом, и прописывается прямо в шаблоне. Так что да — в этом смысле шаблонизатор удобнее нейтива — о чем я и говорил, начиная эту ветку.

                                                            Но проблема с «конями», ей-богу — не самая большая у нейтива. Наложить фильтр эксплицитно — не проблема. Главная проблема — всё-таки, накладывание дефолтного фильтра.
                                                            • 0
                                                              Так в чем проблема то? Вы же прочитали это?
                                                              habrahabr.ru/post/222453/#comment_7576933
                                                              • 0
                                                                Прочитать мало, надо руками пощупать.
                                                                Чем я сейчас и занимаюсь. Это ж ведь не языком чесать — тут время нужно :)
                                                    • 0
                                                      Указать мы это должны где-то в любом случае, скорее всего в шаблоне.
                                                      class TemplateValue
                                                      {
                                                      	private $_value;
                                                      	public function __construct($value)
                                                      	{
                                                      		$this->_value = $value;
                                                      	}
                                                      	public function __toString()
                                                      	{
                                                      		return $this->escapeValue($this->_value);
                                                      	}
                                                      	public function getValue()
                                                      	{
                                                      		return $this->_value;
                                                      	}
                                                      	public function escapeValue($value)
                                                      	{
                                                      		return stripslashes(htmlentities($value));
                                                      	}
                                                      }
                                                      
                                                      function NOTESCAPE($var)
                                                      {
                                                      	return $var->getValue();
                                                      }
                                                      
                                                      $vars =array('a'=> '<div>tratata</div>');
                                                      foreach($vars as &$var)
                                                      {
                                                      	$var = new TemplateValue($var);
                                                      }
                                                      extract($vars);
                                                      var_dump((string)$a);
                                                      var_dump(NOTESCAPE($a));
                                                      
                                                      
                                                    • +1
                                                      Он имел ввиду магические свойства, кажется
                                                      • 0
                                                        Ну, я писал выше — в современных объектах далеко не все свойства доступны через public переменные, которые можно вытянуть через get_object_vars().
                                                        Всякий lazy loading, getters и прочая магия сильно затрудняют такой прямолинейный подход.
                                                        К тому же, возвращать данные может не только свойство, но и метод.

                                                        Но сам по себе подход хорош. Я пытался решить задачу таким же примерно наскоком, но обломался, по причинам, изложенным выше.
                                                        И вообще, очень приятно видеть ответы с кодом. Очень люблю такой подход!
                                                        • +1
                                                          Ну, я писал выше — в современных объектах далеко не все свойства доступны через public переменные, которые можно вытянуть через get_object_vars().
                                                          Всякий lazy loading, getters и прочая магия сильно затрудняют такой прямолинейный подход.
                                                          К тому же, возвращать данные может не только свойство, но и метод.

                                                          	class Order
                                                          	{		
                                                          		private $_fields=array();
                                                          		public function setName($value)
                                                          		{
                                                          			$this->_fields['name'] = $value;
                                                          		}
                                                          		public function __get($name)
                                                          		{
                                                          			if (!isset($this->_fields[$name]))
                                                          			{
                                                          				throw new \Exception('Invalid field ' . $name);
                                                          			}
                                                          			return $this->_fields[$name];
                                                          		}
                                                          	}
                                                          
                                                          	trait TemplateVarPreparing
                                                          	{
                                                          		protected function prepareVar($var)
                                                          		{
                                                          			return $var . 'ЧТО_УГОДНО';
                                                          		}
                                                          	}
                                                          	class TemplateProxyObject
                                                          	{		
                                                          		use TemplateVarPreparing;
                                                          		protected $_object;
                                                          		public function __construct($object)
                                                          		{
                                                          			$this->_object = $object;
                                                          		}
                                                          		public function __call($name, $args)
                                                          		{
                                                          			return $this->prepareVar( call_user_func_array($this->_object->$name,$args) );
                                                          		}
                                                          		public function __get($name)
                                                          		{
                                                          			return $this->prepareVar($this->_object->$name);
                                                          		}
                                                          	}
                                                          	
                                                          	class Templater
                                                          	{
                                                          		use TemplateVarPreparing;		
                                                          		public function render($file, $vars)
                                                          		{
                                                          			$vars = $this->evalVars($vars);
                                                          			extract($vars);
                                                          			unset($vars);
                                                          			
                                                          			var_dump($order->name);
                                                          			
                                                          			//require $file;			
                                                          		}
                                                          		protected function evalVars($vars)
                                                          		{
                                                          			$export_vars = array();
                                                          			foreach($vars as $key => $var)
                                                          			{
                                                          				switch(gettype($var))
                                                          				{
                                                          					case 'object':
                                                          						$export_vars = array_merge($export_vars, array( $key => new TemplateProxyObject($var) ));
                                                          					break;
                                                          					case 'array':
                                                          						$export_vars = array_merge($export_vars, array( $key => $this->evalVars($var) ));
                                                          					break;
                                                          					default:
                                                          						$export_vars = array_merge($export_vars, array($key => $this->prepareVar($var) ));
                                                          				}
                                                          			}
                                                          			return $export_vars;
                                                          		}
                                                          	}
                                                          	$templater = new Templater;
                                                          	$order = new Order;
                                                          	$order->setName('Katya');
                                                          	$vars = array('order'=>$order);	
                                                          	$templater->render('template.phtml',$vars);
                                                          
                                                          • 0
                                                            Ага, оно работает, и даже с методами (надо поправить опечатку в вызове call_user_func_array()).
                                                            Но беда в том, что принцип рекурсии, который распространяется на остальные типы, не распространяется на объекты. И если со свойством ещё можно как-то извернуться, то с методом, который возвращает массив — уже, кажется, никак… :(

                                                            А у меня, в моей практической задаче, есть, к примеру, у юзера свойство $geo, которое само объект, который не инициализирован изначально, а тянется только когда вызван. В общем, я пока бросил эту затею.
                                                            • +1
                                                              Ну и все то же самое, нужно только соединить мой пример отсюда с ProxyObject и добавить такой же рекурсивный проход в класс TemplateProxyObject при получении значения свойства.

                                                              Т.е. на входе у нас массив из чего угодно (объекты со свойствами-объектами, которые сами могут содержать объекты).
                                                              Дальше мы заменяем все объекты первого уровня на ProxyObject, при вызове свойства которого, если оно — объект. то опять же заменяем его на ProxyObject, если массив то заменяем и экранируем все элементы массива, если значение — просто экранируем и так сколько угодно рекурсивно и с поддержкой lazy-loading.

                                                              PHP очень гибок в этом плане, с помощью магических методов __call, __get, __toString мы можем реализовать что угодно в нашей шаблонизаторе, а взамен получим огромную библиотеку функций PHP для работы со строками, массивами и т.д. внутри шаблона.
                                                              Повторю, я не за такой способ шаблонизации, но меня вообще не устраивают любые шаблонизаторы, вставляющие в HTML новый язык. И если уж выбирать, то проще использовать уже известный и многофункциональный нативный PHP.
                                                              • 0
                                                                Проблема с не типизированным ProxyObject все равно есть( По-крайней мере я не знаю, как красиво ее решить.
                                                                Если проксированные объекты в шаблоне могут передаваться, например, во View Helper, который использует type-hinting, либо ему необходима проверка на интерфейс исходного объекта, возникают большие сложности.

                                                                Решается без костылей только созданием всех возможных проксей, которые реализуют те же интерфейсы, что и проксируемые объекты (вобщем-то классический паттерн и подразумевает следование интерфейсам проксируемого объекта).
                                                                • 0
                                                                  Ну ведь мы говорим о своем каком-то шаблонизаторе, ведь так? Тогда что мешает запросить у анонимного прокси-объекта информацию об интерфейсе настоящего?

                                                                  	class ProxyObject
                                                                  	{
                                                                  		protected $_object;
                                                                          public function __construct($object)
                                                                          {
                                                                              $this->_object = $object;
                                                                          }		
                                                                  		public function getObject()
                                                                  		{
                                                                  			return $this->_object;
                                                                  		}
                                                                  	}
                                                                  	Interface IModel
                                                                  	{
                                                                  		
                                                                  	}
                                                                  	class Order implements IModel
                                                                  	{
                                                                  		
                                                                  	}
                                                                  	$order = new Order;
                                                                  	$proxy_object = new ProxyObject($order);
                                                                  	var_dump(($proxy_object->getObject() instanceof IModel));
                                                                  


                                                                  Или конкретизируйте пример, пожалуйста.
                                                                  • 0
                                                                    Для собственного шаблонизатора и зависимых от него напрямую хелперов, конечно можно и так, но лишает возможности использовать, к примеру, сторонние хелперы, которые ничего не знают о ProxyObject конкретного шаблонизатора.
                                                                    Вобщем, для коробочного решения, работающего с любыми хелперами «без допилов» вряд ли годится, но для индивидуального решения — вполне себе работает.
                                                                    • 0
                                                                      Хм, а что это за хелперы в представлении, которые знают об интерфейсах модели?
                                                                      • 0
                                                                        Ну, к примеру, хелперы для рендеринга форм. Контроллер может отдавать в шаблон View Model формы и ее элементов, а хелперы могут помогать эти view model рендерить в зависимости от интерфейса view model.
                                                                        • 0
                                                                          Но что тогда мешает подменить ProxyObject на реальный объект при вызове стороннего хелпера?

                                                                          	function ВЫЗОВХЕЛПЕРА($proxy_object)
                                                                          	{
                                                                          		СТОРОННИЙ_ХЕЛПЕР($proxy_object->getObject());
                                                                          	}
                                                                          


                                                                          а в шаблоне

                                                                          <div>....<?=ВЫЗОВХЕЛПЕРА($order)?>..</div>
                                                                          
                                                                          • 0
                                                                            тоже ничего не мешает, разве что внутреннее ощущение нарастающего оверхеда и что ради одной возможности (хоть и важной) автоматически экранировать строки на вывод, приходится так интересно развлекаться:)
                                                                            Поэтому нельзя уж прямо с чистым сердцем сказать, что это легко реализуемо «нативно».
                                                                            Было бы действительно круто, если бы php сделали возможность регить что-то вроде output_filter, как кто-то из хабровчан выше заметил.
                                                                            • 0
                                                                              Ну уже мы разговариваем далеко не просто про экранирование — экранирование было в моем первом примере в 4 строчках. А это уже поддержка многовложенных объектов с магическими свойства, сторонние хелперы и т.д. И собственно разговор о том, что сторонние шаблонизаторы могут больше, с чем я согласиться пока не могу.

                                                                              Было бы действительно круто, если бы php сделали возможность регить что-то вроде output_filter, как кто-то из хабровчан выше заметил.

                                                                              Не представляю как это могло бы быть реализовано. Т.е. регистрируем функцию на вывод именно «echo ». Но опять же вопрос с экранированием, если мы вызовем функцию NOTESCAPE, то она вернет нам скларяное значение, которое опять же должно будет экранироваться или что, при ее вызове отключать output_filter?
                                                  • 0
                                                    Я думаю, в случае, когда мы собираем строку из кусков, одни из которых должны интерпретироваться, а другие нет, причём собираем не через какой-то API, а руками (читай, делаем конкатенацию), никакого автоэкранирования быть не должно. В тех же плейсхолдерах SQL мы указываем тип значения, которое мы ожидаем получить из переменной, и соотв. образом эти значения добавляем в запрос.

                                                    По-моему, экранирование (или указание типа укранирования) должно быть явным и осознанным. А неэкранированная вставка переменной в вывод по умолчанию должна считаться потенциальной уязвимостью до тех пор, пока явно не указано, что это значение — «безопасное».
                                                  • –1
                                                    Ужас начинается, когда появляется что-то типа:
                                                    <a href="<?= $page->url ?>">...</a>
                                                    От такого обилия вложенных угловых скобок глаза начинает колбасить.

                                                    Плюс чистый PHP не позволяет удобно использовать всякие полезные вещи, типа наследования шаблонов, автоматического экранирования и т.п.
                                                    • +1
                                                      От такого обилия вложенных угловых скобок глаза начинает колбасить.

                                                      Это проблема не PHP, а смешения HTML-разметки и кода, которое присуще любым шаблонизаторам подобного типа. Поэтому я за чистые шаблонизаторы, которые не суют ничего в HTML.

                                                      Плюс чистый PHP не позволяет удобно использовать всякие полезные вещи, типа наследования шаблонов, автоматического экранирования и т.п.

                                                      Про экранирования я писала выше, а с наследованием какие проблемы?
                                                      • +2
                                                        Ну, это уже вкусовщина. У кого-то от угловых рябит, у кого-то — от фигурных.

                                                        А по поводу остальных фич — надо различать РНР как язык разметки шаблонов и Шаблонизатор как модуль приложения. Чистый PHP не означает «чисто include()» как обработчик шаблонов — такой обработчик все равно пишется специально. и в нем уже можно реализовать и наследование и многие другие вкусности
                                                      • 0
                                                        Единственный весомый аргумент, который я когда-либо слышал в пользу шаблонизаторов — это лишить нерадивых джуниоров возможности писать бизнес логику и запросы в БД из вьюшек.
                                                        • 0
                                                          а так же принуждать экранировать данные при выводе, проверки в циклах, и кучу всяких мелочей.
                                                      • +13
                                                        Очень пафосный текст статьи… Особенно
                                                        Laravel Тэйлора Отвелла возник из пепла, чтобы стать любимцем общества
                                                        Не тянет статья на Tips and Tricks, скорее очередная пиар статья с кратким описанием фич.
                                                        • 0
                                                          Это перевод статьи Jeffrey Way. Поэтому я и оставил всё, как есть.
                                                          • +2
                                                            Я и не говорю чего-то в вашу сторону. Я просто не понимаю всей этой шумихи вокруг Laravel, это как-то по детски.
                                                            • 0
                                                              Хороший же фреймворк. Или не так?
                                                              • +2
                                                                Относительно большинства — да, но не лучший. Хотя множество решений в нем действительно хорошо, например тамошний IoC контейнер. Концепция AR мне же очень не нравится, мне больше по душе data-mapper в лице Doctrine. Фасады так же не ок, как бы проблем они не создают, и даже не ломают особо принципы ООП, но как-то не красиво. Но все это субъективизм.

                                                                Просто даже если брать эту статью, она практической пользы как таковой не несет, только рекламирует то что можно в документации почитать. Никаких разборов когда этот фреймворк выгодно использовать а когда нет, как правильно делать (в документации частенько проскакивают штуки, которые противоречат бест практис, в целях упрощения материала как я понимаю).
                                                              • –2
                                                                Ну, учитывая, что большинство пользователей похапешечки не вышли из ясельного возраста, то им такая реклама как раз.
                                                                Те же, которые вышли, или сами понимают сильные и слабые стороны движка безо всякой рекламы, либо вообще пилят большой портал на собственном софте, и им поп-фреймворки перпендикулярны.

                                                                А так-то да — ORM и роутенг преподносятся прям как исключительные заслуги Лярвы, и чуть фанфары из каждого абзаца не играют.
                                                          • +9
                                                            Вот только не Laravel вдохнул новую жизнь в PHP, а всетаки Fabien с Symfony2 и уже потом пришел Composer, во многом благодаря Fabien-у сообщество PHP продвинулась вперед, он попробовал принести PHP в мир enterprise решений.
                                                            • +2
                                                              А по мне так дело обстоит так:
                                                              Сначала в PHP вдохнули жизнь WordPress, Joomla, Drupal и т.д. На этом создали (и создается) огромное число небольших сайтов, шаблонных интернет-магазинов и т.д.
                                                              Затем ВКонтакте, Википедия, Facebook и др. показали, что на PHP можно создавать ведущие интернет-ресурсы в мире. И вот это вдохнуло уже в PHP такую жизнь, что не останавливается до сих пор, а о framework'ах никто, кроме использующих их разработчиках не знает.
                                                              И новичок, стоящий перед выбором будет сравнивать не Laravel, Symphony, ASP, Play или Django, а результаты:
                                                              1. На PHP написано подавляющее большинство сайтов.
                                                              2. История про написание 2 крупнейших соцсетей двумя людьми (Дуров и Цукерберг). Причем, судя по kPHP ВКонтакте вообще не использует ООП.
                                                              3. На PHP можно написать сайт из 1 строчки (чего не скажешь о любом framework'е).

                                                              И вот только потом, уже для продвинутых разработчиков в дело вмешиваются framework'и и доказывают, что на PHP можно писать и крупные проекты не одному человеку со всеми плюшками, в том числе в корпоративной сфере (однако, там где нужна надежность выбирают все еще Java).
                                                              Так что я бы так сильно не стала преувеличивать значимость framework'ов в истории PHP.
                                                              • 0
                                                                Вы правы, я как раз говорил о последнем пункте.
                                                                • +2
                                                                  Речь идет о событиях, которые просходят уже после описываемых.

                                                                  Интерес к РНР в мире стабильно падает уже несколько лет, и никакой ФБ этому не помеха.
                                                                  Сообщества закрываются, трафик на ресурсах падает. На Хабре частота статей по пхп упала в несколько раз. На Стаковерфлоу, скажем, бешеный трафик поддерживается исключительно за счет бангалорских бедняков, для которых писать на пхп — это альтернатива ручной разборке океанских лайнеров на металлолом. И пхп там — исключительно процедурная лапша из прошлого века (которая, кстати, на мой взгляд, и есть главный двигатель популярности). И в начале статьи упоминается именно этот факт.

                                                                  Так что важность фреймворков, действительно, проявляется не где-то в истории, а прямо сейчас.

                                                                  • +1
                                                                    Вы сами себе противоречите, после FB — был бешенный рост, сейчас развиваются framework'и и ужасное падение популярности. Получается как раз таки, что нужны новые facebook'и, а не новые framework'и.
                                                                    Но это только если судить по хабру и stackoverflow. Не представляю, что можно спросить о PHP на stackoverflow при работе над серьезным проектом. Разве что — об extensions (и то если нет C-специалистов в команде).
                                                                    На Стаковерфлоу, скажем, бешеный трафик поддерживается исключительно за счет бангалорских бедняков, для которых писать на пхп — это альтернатива ручной разборке океанских лайнеров на металлолом.

                                                                    А это дело не в PHP, просто в мире уже давно война не эффективности используемых ЯП, а умении грамотно организовать бизнес-процесс.
                                                                    Если в 1998 Грэм Пол хвастался преимуществами Lisp в конкурентной борьбе, то сейчас количество разработчиков, серверов и инвестиций решают любые вопросы.
                                                                    • 0
                                                                      Ну, на моей памяти из недавнего — например, об особенностях работы mysqli_multi_query(). Документация очень невнятная а результаты собственных экспериментов очень легко мисинтрпретировать.
                                                                      Или вот я ещё спрашивал про удивительный баг — все функции для работы с файлами как одна молча отказывались работать с HTTP враппером. Ответ, правда, я получил уже после того, как написал воркараунд, но тем не менее.

                                                                      После ФБ не было бешеного роста. Вот характерная картинка — www.google.ru/trends/explore#q=%2Fm%2F060kv
                                                                      Она, хоть, и в собственных гуглопопугаях, но тренд совершенно очевиден.
                                                                      Взрывной рост интереса к ПХП начался в начале века, когда он занял абсолютно пустую нишу, да ещё и предложил нулевой порог вхождения. Но уже к середине первой декады пошел на спад. А в середине второй, я, как активный участник многих ПХП-сообществ, невооруженным глазом вижу снижение интереса и трафика.

                                                                      Фреймворки развиваются на фоне падения популярности.
                                                                      Новичок читает статьи типа этвудовской «The PHP Singularity» с двойным гвоздодёром на картинке и выбирает что помоднее. Благо, выбор у него есть.
                                                                      Бангалорские неприкасаемые не пишут энтерпрайз. Они побираются на одеске за еду. И, сколько в них денег ни влей, «Войну и мир» они не напечатают, увы
                                                                      А организатор бизнес-процессов тоже анализирует тренды и выбирает наиболее, на его взгляд, перспективные.
                                                                      Вокруг Друпала и Уордпресса уже сложились эффективные экосистемы, в которых 99% пользователей устраивает базовый функционал, а запросы остальных удовлетворяет имеющееся сообщество разработчиков — и особого прорыва с той стороны не видно.

                                                                      В общем, падение популярности РНР в последние годы — это факт. И фреймворки — это действительно второе дыхание языка.
                                                                      • 0
                                                                        www.google.ru/trends/explore#q=%2Fm%2F060kv%2C%20%2Fm%2F07sbkfb%2C%20%2Fm%2F06ff5%2C%20%2Fm%2F0jgqg%2C%20Objective-C&cmpt=q

                                                                        Судя по всему динамика трендов практически идентичная для всех языков
                                                                      • +1
                                                                        Взрывной рост интереса к ПХП начался в начале века, когда он занял абсолютно пустую нишу

                                                                        Неправда ваша. Он был прямым конкурентом Perl.
                                                                        • –1
                                                                          С тобой дискутировать бесполезно, но один раз объяснить можно — именно наличие перла на поляне и означало абсолютно пустую нишу.
                                                                          • +1
                                                                            Абсолютно пустую нишу означало бы наличие «на поляне» исключительно компилируемых и т. п. языков. Главным преимуществом перед ними что Perl, что PHP было то, что создать сайт можно было тупо залив по ftp текстовые файлы, которые интерпретировались на лету, любые изменения сразу же отображались без всяких линковок и сборок. В пользу PHP сыграло два важных фактора (вернее один, но с двумя аудиториями) — низкий порог входа для тех, кто никогда не программировал, и низкий порог входа для программистов знакомых с Си и прочими си-образными языками.
                                                                        • 0
                                                                          Отвечу сразу всем.
                                                                          Имхо, падение популярности PHP связано с растущей популярностью ЯП для написания мобильных приложений.
                                                                          • +1
                                                                            Подождите, но ведь PHP для бэкенда и мобильным приложениям нужен бэкенд, почему бы не расти популярности вместе с ростом потребностей.
                                                                    • +1
                                                                      Сначала был wordpress, это был пожалуй самый мощьный популяризатор php. А до joomla были всякие mambo и прочие. До версии 5 php воспринимать как полноценный язык для web было смешно, а вот уже 5,3 можно говорить о нем серьезно.

                                                                      facebook напомню создавался одним разработчиком по началу, как и vk. Там не особо много думалось о выборе технологий, просто писалось на том, что знали разработчики.

                                                                      А по поводу новичков — это не особо интересно. Сейчас куча новичков с подачи интернетов идут в python/ruby, и плодят свой говнокод еще и на них. Не только на php можно писать сайты ничего не зная, благо время идет и все развивается.

                                                                      А помимо мелких сайтов есть еще решения для бизнеса, и там фреймворки это хорошо. Да и на базе фреймворков пишут всякие cms-ки.
                                                                  • +8
                                                                    У меня ощущение, что я читаю машинный перевод.
                                                                    • –4
                                                                      Зачем писать на пхп если можно писать на руби или хотя бы питоне? Мы не в северной корее, свобода выбора же есть.
                                                                      • 0
                                                                        Потому что свобода выбора, bro
                                                                        • +5
                                                                          ОМГ, на работе пишу и на php, и на ruby. Чего там такого у этого руби, не пойму.

                                                                          ЗЫ Промахнулся веткой
                                                                          • –1
                                                                            У руби есть отшлифованая экосистема библиотек и практик, тестирования и красота кода. У пхп нет вообще ничего, кроме популярности.
                                                                            Абсолютное большинство стартапов прототипируются на рельсах — это тоже о чем то говорит.
                                                                            • +3
                                                                              >> У руби есть отшлифованая экосистема библиотек и практик

                                                                              Настолько отшлифованная, что для работы с excel приходится юзать аж 2 разные библиотеки: roo — для парсинга, axlsx — для генерации документов.

                                                                              >> тестирования

                                                                              В PHP с этим не хуже.

                                                                              >> красота кода

                                                                              Это вообще никогда не было серьезным критерием полезности языка. Кроме того, красиво ruby выглядит только на хелловорлдах. Когда пишешь сложную логику, портянка, что там, что там, факт. Рассказы, будто бы на ruby кода в 2 раза меньше — наглое вранье.

                                                                              >> У пхп нет вообще ничего, кроме популярности.

                                                                              На PHP сейчас все есть даже для ентерпрайза.

                                                                              >> Абсолютное большинство стартапов прототипируются на рельсах — это тоже о чем то говорит.

                                                                              Кроме прототипирования ни на что эти рельсы больше и не годятся.

                                                                              При всем при этом я не хочу сказать, что PHP > ruby. Средняя температура по больнице одинаковая. Кому что нравится.
                                                                              • 0
                                                                                >В PHP с этим не хуже.
                                                                                нет, ну вот в тестировании нет ничего лучше руби экосистемы. это колыбель TDD

                                                                                >Кроме прототипирования ни на что эти рельсы больше и не годятся.
                                                                                да. Они медленные. Но ведь прототипирование это важнее для стартапа, переписать можно потом?
                                                                                • +2
                                                                                  это колыбель TDD

                                                                                  Пруф можно? Емнип, колыбелью TDD считается Smalltalk. Из мэйнстрима — то ли Java, то ли C#, но скорее Java. Ruby — колыбель BDD, но TDD он позаимствовал.
                                                                                • 0
                                                                                  >> Мы не в северной корее, свобода выбора же есть

                                                                                  Ну и говорить в контексте ruby я такое бы не стал. Нет в ruby никакой свободы. Вы либо пИшите в стиле ruby, либо вообще не пИшите на ruby. В PHP же реализовано целая куча всяких разных паттернов и практик.
                                                                                  • 0
                                                                                    Совершенно верно, технически вам никто не мешает создать новые библиотеки. Их будут использовать если они будут *лучше*. Так уж вышло что рельсы и стиль руби *достаточно хороши*. Когда меняешь рубистов им не нужно вникать в архитектуру, в отличии от ПХП, они могут сразу начать писать код, модели/контроллеры устроены одинаково во всех рельс приложениях.

                                                                                    В пхп же такое разнообразие фреймворков потому что они все недостаточно хороши, и каждую команду тянет написать еще один.
                                                                                    • +1
                                                                                      >> Когда меняешь рубистов…
                                                                                      С таким же успехом можно менять Yii-стов или Zend-истов, CakePHP-истов или Laravel-истов.

                                                                                      >> в пхп же такое разнообразие фреймворков…
                                                                                      Ruby тоже имеет парочку аналогов.
                                                                                      • 0
                                                                                        Ну это болезнь php-сообщества, велосипедостроение. Вообще если брать более мение серьезные фреймворки, типа Symfony/zend, да тот же laravel, который развивается внутри экосистемы symfony, то такой проблемы нету. А вот штуки типа yii/cakephp/ci и т.д. — тут да. Хотя, по сути не так проблемно спускаться с уровня повыше на уровень пониже, просто не приятно.

                                                                                        Словом, это вопрос личных предпочтений. Кому-то что-то не нравится, может от неопытности, может от незнания, а может и вовсе от упертости и максимализма, и начинаются велосипеды.
                                                                                  • +3
                                                                                    красота кода

                                                                                    Я конечно понимаю, что о вкусах не спорят. Но от синтаксиса Ruby у меня вынесло мозг, красотой этот язык мой язык (сорри за каламбур) не повернется никогда назвать. Не хочу быть неправильно понятым: я не говорю, что Ruby — говно, нет. Я осознаю его мощь, и в конце концов, именно с RoR'а слизаны многие фишки Laravel'а. Но лично я писать на Ruby не собираюсь.
                                                                              • +8
                                                                                Зачем писать на руби или питоне, если можно писать на пхп?
                                                                                • –9
                                                                                  Очевидно, потому что пхп говно?
                                                                                  • 0
                                                                                    Чем PHP говно? Тем, что до нас было написано куча говно сайтиков с брешами в безопасности? И теперь никто не признает PHP?
                                                                                    Или чем?

                                                                                    p.s. никаких наездов, просто вопрос)
                                                                                    • 0
                                                                                      Все говно, жизнь боль.
                                                                                • +2
                                                                                  Профессионально работаю на PHP примерно с 2007 года. Начинал с pure, потом был Zend. Видел кратце Yii — ужаснулся. А щас просто фанатею от Laravel. На нем все делается настолько просто и быстро, причем вполне красиво. Уже поднял 3 сайта на нем. Никогда еще не получал большего удовольствия от кодинга, чем щас на Laravel. На все задачи, которые у нас возникают, быстро находим решения на Laravel. Это мое краткое впечатление от фреймворка, подробнее здесь писать не буду, так как очередной холивар на тему «Какой фреймворк лучше» не нужен.
                                                                                  • 0
                                                                                    У меня опыт поменьше: сначала работал с проприетарным фреймворком (на котором розетка написана), а сейчас на работе — Yii, но все свои проекты делаю на Laravel! Впечатления такие же!
                                                                                    • 0
                                                                                      Попробуйте Symfony 2
                                                                                      • 0
                                                                                        Пробовал! Хорош, но Laravel мне больше нравится.
                                                                                    • +1
                                                                                      Пожалуй, вброшу немного на вентилятор.

                                                                                      >> $orders = Order::orderBy('release_date', 'desc')->get();

                                                                                      Я на Propel одним Enter-ом такое на phpstorm пишу, а тут надо поле руками писать.

                                                                                      >> $order->title = 'Xbox One';

                                                                                      На серьезном проекте с кучей бизнес-логики без геттеров-сеттеров далеко не уедешь. Чем этот Eloquent лучше, чем какой-нибудь бородатый Kohana ORM? Синтаксис один в один, как и все проблемы.

                                                                                      >> php artisan migrate:make create_users_table

                                                                                      2014 год, а все руками миграции пишем. ОК.

                                                                                      >> {{ Form::open() }}
                                                                                      >> {{ Form::text('name') }}
                                                                                      >> {{ Form::textarea('bio') }}
                                                                                      >> {{ Form::selectYear('dob', date('Y') — 80, date('Y')) }}
                                                                                      >> {{ Form::close() }}

                                                                                      Верстальщики за такое на кол посадят.

                                                                                      >> $questions = Question::remember(60)->get();

                                                                                      Зачем ORM лишний раз дергать для кэширования?

                                                                                      >> IoC контейнер (Inverse of control)

                                                                                      Ну и толку от этого контейнера, если весь фреймворк в статике написан.
                                                                                      • 0
                                                                                        Ну и толку от этого контейнера, если весь фреймворк в статике написан.

                                                                                        Здешняя «статика» называется фасадами, а в основе их — обычные нестатичные классы. Соотв-но эти самые низлежащие классы инстанциируются через IoC. Любой компонент Лараравела заменяется на собственный простым перебиндиванием в контейнере.
                                                                                        • +1
                                                                                          На серьезном проекте с кучей бизнес-логики без геттеров-сеттеров далеко не уедешь. Чем этот Eloquent лучше, чем какой-нибудь бородатый Kohana ORM? Синтаксис один в один, как и все проблемы.

                                                                                          Никто не мешает усложнить логику сеттеров/геттеров. Можно например написать getTitleAttribute(), который будет вызван при попытке доступа к $model->title;

                                                                                          Верстальщики за такое на кол посадят.

                                                                                          Вообще-то PHP-дэвелопер пишет блэйдовский шаблон ПОСЛЕ того, как его сверстали верстальщики.

                                                                                          2014 год, а все руками миграции пишем. ОК.

                                                                                          Частично можно автоматизировать, передав дополнительные параметры артизану.

                                                                                          Одним словом, данная статья — не исчерпывающий сборник рецептов и документация Laravel, а лишь в какой-то степени агитация, как уже говорили выше в комментах.
                                                                                          • +1
                                                                                            Никто не мешает усложнить логику сеттеров/геттеров. Можно например написать getTitleAttribute(), который будет вызван при попытке доступа к $model->title;

                                                                                            … а потом искать, где в коде этот метод вызывается напрямую, где косвенно. Знаю, проходили. Эта проблема, кстати, в других частях L4 еще глубже, так как есть мнеого способов сделать одно и то же — например:
                                                                                            В isFillable мы проверяем несколько разных способов, которыми может быть обработано массовое назначение. Сначала мы смотрим, установлена ли модель как unguarded, и если это так, то разрешаем назначение. Далее мы проверяем, находится ли атрибут в массиве fillable, тогда мы разрешаем назначение еще раз. Затем вызывается isGuarded, который проверяет, находится ли ключ в массиве guarded, или guarded содержит знак звездочки array('*') (который ставится по умолчанию), тогда мы не разрешаем массовое назначение. Наконец, если fillable пустой, мы возвращаем true, если ключ не начинается с подчеркивания, которое используется для скрытых атрибутов, как это принято и в Rails.

                                                                                            Если находится unfillable-ключ, то мы проверяем, является ли модель totallyGuarded. По сути это значит, что если fillable пустой и guarded содержит знак * (по умолчанию), тогда возникает исключение MassAssignmentException. Это значит, что если вы не измените свойства fillable или guarded, то при попытке вызвать fill будет возникать исключение MassAssignmentExceptions.
                                                                                            . Все это сильно затрудняет поддержку проекта.

                                                                                            Вообще-то PHP-дэвелопер пишет блэйдовский шаблон ПОСЛЕ того, как его сверстали верстальщики.

                                                                                            … который, конечно, больше никогда не меняется. Такой дзэн.
                                                                                            • 0
                                                                                              … который, конечно, больше никогда не меняется. Такой дзэн.

                                                                                              Как уже писал в ответ товарищу ниже: что, программисты настолько тупые, что не смогут найти различия в верстке?
                                                                                              • 0
                                                                                                Есть кучи примеров компаний, в котором очень жестко ограничиваются сферы работ. Нормальная практика не давать бэкэнд разработчику верстать, так как для этого есть отдельный человек который сделает все быстрее. Даже для фронтэнда частенько бывает такое жесткое разделение. Все зависит от процессов в компании.
                                                                                                • 0
                                                                                                  Ну дык речь не идет о том, что разработчик будет верстать. Верстку делает отдельный человек. Тут спор о том, что верстальщик помимо верстки еще и шаблон должен подстроить под бэк-энд, с чем я категорически не согласен.
                                                                                                  • 0
                                                                                                    именно. верстальщик должен лазать в шаблоны. backend-разработчик напротив не должен. Но это возможно только если разработчик полностью отвязал логику от представления, что в принципе нам и нужно.
                                                                                                    • 0
                                                                                                      Это красиво звучит в идеальной ситуации. Но зачастую в шаблонах тоже присутствует программерская логика: данные то от бэкэнда получены, но вот вывести их все равно нужно по-особенному. Простейший пример, когда нужно вывести элементы массива в зав-ти от четности-нечетности его нахождения в массиве. Верстальщику придется в какой-то степени уметь программировать, что не вписывается в идеологию полного разделения задач. Ему придется писать foreach, какой-бы шаблонизатор не использовался. Делать проверку на четность и т.д. Или более сложный пример: выводить записи допустим по три на строку. Нужно вести счетчик записей, на каждом третьем закрывать очередной див и открывать новый. В игру входят пускай и простые, но алгоритмы, что накладывает на плечи верстальщика дополнительные требования. А чем меньше требований к кандидату — тем проще его найти.
                                                                                                      Вот есть забубенный какой-то верстальщик, и умеет он допустим делать шаблоны для како-нибудь Twig'а допустим. Но так сложилось, что пришлось уволится с текущей конторы. Ищет другую работу: а там либо какой-нибудь Smarty используют, либо вообще все на Zend Framework, но политика компании придерживается этого идеала: верстальщик должен писать шаблоны. В итоге верстальщик должен познать еще и шаблонизацию в стиле Zend и т.п. Ситуация гораздо проще, когда верстальщик делает только то, что вложено в это слово — только верстает. Вот покупаете вы детали конструктора Лего допустим. Вы получили детали, аналог верстки. Теперь вам нужно из них построить домик, аналог фронт-энда. В это дело тоже должен вмешиваться производитель Лего, помогая вам из деталей собрать то, что нужно? Или купили болванку DVD пустую. Вы будете обращаться к производителю, чтобы на нее что-то записать? Сверстанный макет — эта та же болванка, те же детали, из которых можно сделать что нужно. И делать это должен программист. Полное разделение задач: дизайнер предоставляет дизайн, верстальщик предоставляет верстку-болванку с Lorem ipsum'ами, программист прикручивает это к написанному им самим бэк-энду. Дизайнер не знает, как верстать. Верстальщик не знает, как рисовать и программировать. Программист не знает как рисовать и верстать. Но в команде они работают как конвейер, не малозначимое изобретение, если не ошибаюсь, Форда. Можно много аналогий проводить.
                                                                                                      У меня большой опыт разработки на PHP, но с вариантом, когда верстальщик сам делает шаблоны, сталкивался всего один раз. Но тут было несколько но: 1) верстальщик четко знал, что писаться все будет на Zend'е; 2) он сам бывший программист. Но даже в этом случае мы теряли много времени на «состыковку»: какие переменные я сэтчу во вьюхи и каков их формат. Когда он не мог достучаться до меня, он сам лез в код и смотрел, а иногда даже что-то правил под удобный ему формат. И это еще хорошо, что основной функционал у меня был готов до верстки. Иначе бы ему приходилось ждать меня, пока я реализую фишку, чтобы он мог ее отобразить. Он сам «настроил» мой код под использование его шаблонов, так как он знал, как назовет файл лэйаута и другие под-шаблоны. Это не дело.
                                                                                                      На текущей работе все так, как я считаю и должно быть. Дизайнер --> верстальщик --> программист. Дизайнер нарисовал, отдал, свободен. Верстальщик сверстал, отдал, свободен. А вот программер уже над этим трудится. Верстальщик может отдать верстку до того, как функционал будет готов. Дизайнер же не подстраивается под верстальщика. Так и верстальщик не подстраивается под программиста.
                                                                                                      Резюмируя: верстальщик не должен уметь программировать и разбираться серверных языках программирования (не считая желательного для любого верстальщика знания JS); верстальщик не должен разбираться в шаблонизаторах. Он должен просто уметь верстать.
                                                                                                      Но это тоже «крайний случай». Конечно неплохо, когда верстальщик «шарит», но возводить это в обязанность неправильно с моей точки зрения. И со мной согласились все мои друзья и коллеги, кстати.
                                                                                                      Другими словами, возлагать на верстальщика обязанность подгонять шаблон под бэк-энд — непрактично.
                                                                                                      • +1
                                                                                                        Вы действительно считаете что верстальщики должны быть тупыми и не способными применить банальные проверки аля i % 2 == 0? Да и «верстать» сейчас это не так то просто.

                                                                                                        На самом деле все эти кейсы решаются стилями. Прошли уже те времена когда нужно было руками все это прописывать. Есть псевдоселекторы аля nth-child которые позволяют задавать над какими элементами по порядку нужно производить какие-то действия, над 2n или 2n+1 ( если мы про четность и нечетность).

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

                                                                                                        По поводу вашего опыта:
                                                                                                        1) верстальщик должен сидеть рядышком, вопросы все эти решаются до того как кто-либо из вас приступит к работе. Так что «что как стыковать» — такого вопроса вообще не должно быть. Если верстальщику чего-то не хватает — в шаблонизаторах есть фильтры. Он реквестит такой-то фильтр, вы его реализуете. Все в рамках тех-процессов. Править же данные, которые вы пробрасываете из контроллера во вьюху что бы поменять представление — это уже странно.

                                                                                                        2) Верстальщик должен знать хотя бы js на начальном уровне, в его распоряжении не только html+css, но и мириады препроцессоров, например less/sass, или autoprefixer. Так же средства сборки типа grunt/gulp, ну и js иногда нужно впилить простенький. Если вы работаете в рамках какого-то фреймворка, то для такой задачи верстальщику хватит одного проекта что бы въехать как ведется разработка. Да и не забывайте, в идеальном мире, при нормальных процессах, вся команда сидит рядом и что-то спросить не должно занимать много времени. Если у вас проблемы с коммуникацией в команде, это ваши проблемы и только. Верстальщик не должен лесть в код, это да, но и вы должны работать в команде при таком подходе. Я так понимаю что у вас все это было в рамках удаленки или сидели в разных концах офиса.

                                                                                                        То что вы описываете это очень не продуктивная методика. Для небольших проектов норм, но если проект в активной стадии разработки, то обычно это дизайнер нарисовал кусок — верстка + параллельно имплементация функционала — релиз — цикл повторяется в зависимости от фидбэка. Так что меняются стили и дизайн почти всегда, и тратить время на интеграцию верстки это глупо и не эффективно.
                                                                                                        • +1
                                                                                                          Ваши рассуждения сводятся к тому, что есть много разных шаблонизаторов и верстальщику трудно знать их все. Однако и браузеров много (по-крайней мере пока еще) и исходные форматы от дизайнера могут быть разные.
                                                                                                          И совсем не факт, что степень различия между Photoshop и Illustrator больше чем между Twig и Smarty.
                                                                                                          Вы говорите, что верстальщику придется программировать, однако не отказываете ему в знании JS. А ведь по сути программирование во всех шаблонизаторах сводится к FOREACH и IF. Это настолько элементарная логика, что думаю под силу любому. Все остальное, модификаторы, наследование и т.д. настолько же декларативно, насколько декларативен сам HTML и уж тем более CSS.
                                                                                                          Да, проблема интерфейса шаблона (передаваемые переменные) есть, но она касается в целом подхода, а не конкретно разделения программист-верстальщик. А в вашем примере мы с тем же успехом можем сказать, что дизайнер захотел изменить кнопочку, а верстальщик ему не ответил и тот сам полез в HTML-CSS менять ее. Это вообще вопрос организации взаимодействия.

                                                                                                          Корректными, я считаю, в контексте проблемы были бы рассуждения, кого выгоднее иметь компании — верстальщика-шаблонизаторщика или программиста-шаблонизаторщика, а на спрос уже родятся и предложения.
                                                                                                          Верстальщик-шаблонизаторщик:
                                                                                                          1. Позволяет менять дизайн/структуру страницы без дополнительных участников процесса.
                                                                                                          2. Позволяет менять логику на уровне шаблона без вмешательства бэкенд-программиста.
                                                                                                          3. Но зависит от переданных переменных, что собственно не относится к представлению, а значит не должно меняться часто. Также тут помогут различные lazy-loading и другие способы обращения к заранее не переданным данным.
                                                                                                          Программист-шаблонизаторщик:
                                                                                                          1. Позволяет изменить передаваемые данные и? Сообщить верстальщику, что можно переделывать дизайн под новые данные, затем получить сверстанную заново страницу, заново накидать на нее весь шаблон.
                                                                                                          2. При изменении дизайна, пункт 1.
                                                                                                          3. Логику в шаблоне может менять так же независимо от других участников процесса.

                                                                                                          Я делаю вывод, что компании выгоден верстальщик-шаблонизаторщик, а лень изучить новый шаблонизатор это вообще не разговор.
                                                                                                          • 0
                                                                                                            Тогда ответьте товарищу выше на его коммент:
                                                                                                            >> {{ Form::open() }}
                                                                                                            >> {{ Form::text('name') }}
                                                                                                            >> {{ Form::textarea('bio') }}
                                                                                                            >> {{ Form::selectYear('dob', date('Y') — 80, date('Y')) }}
                                                                                                            >> {{ Form::close() }}

                                                                                                            Верстальщики за такое на кол посадят.

                                                                                                            Значит ему приходилось работать с «тупыми» верстальщиками =) Ибо тут все очень даже просто.
                                                                                                            • 0
                                                                                                              С виду несложно, согласна. Но все при том же условии, что верстальщик независим от программиста и бэкенда и занимается представлением, а не моделью. Здесь же, насколько я понимаю — весь синтаксис нужен именно для модели, а не для представления? В таком случае, это явное нарушение инкапсуляции шаблона и вообще всего смысла MVC. И, как следствие, бессмысленность изучения таких команд (по сути логики бэкенда) для шаблонизаторщика.

                                                                                                              Да, наверное, когда один человек занимается на проекте всем — это быстро и удобно, не могу сказать — давно уже даже если делаю все одна, разделяю внутри себя эти вещи.
                                                                                                              • +1
                                                                                                                Готов признать, что по крайней мере частично вы меня переубедили. Как никак, а в споре рождается истина :)
                                                                                                                Здесь же Form — это можно сказать helper для генерации элементов форм. Очень удобная штука. К примеру нужно отобразить модель $user с полями допустим nickname и email:
                                                                                                                {{ Form::model($user) }} {{ Form::text('nickname') }} {{ Form::email('email') }} {{ Form::close() }}

                                                                                                                То есть сгенерятся соотв-но инпуты с проставленными $user->nickname и $user->email. Приятной фишкой также будет, если в бэк-энде будет сделано перенаправление на эту страницу с ->withInput(), то в эти поля проставятся ранее введенные пользователем данные (ситуация, когда пользователь ввел некорректные данные, и бэк-энд вернул пользователя на эту страницу — он увидит введенные ранее данные). То есть сам шаблон лишен логики всякой дополнительной. Все делается в этом хэлпере.

                                                                                                                P.S. Хабр странно отформатировал код х_Х
                                                                                                                • 0
                                                                                                                  Ради чего писать все это в шаблоне? Почему просто не создать класс этой формы (или хотя бы тупо массив) и сгенерировать из него html-код?
                                                                                                                  $form = array('nickname' => 'text',....);
                                                                                                                  $view_form = Form::render($form);
                                                                                                                  

                                                                                                                  Можно сказать, ради того, чтобы поля можно было бы вставлять в шаблон отдельно в нужное место, но они могут быть так же другого дизайна (пример с bootstrap). Да и шаблон формы можно описать отдельно один раз, а не вставлять эту кучу каждый раз.