Формы в Laravel: как подружиться с bootstrap 3

Не секрет, что большинство интерфейсов в админке сейчас строится на фреймворке Bootstrap версии 3. Есть даже огромное количество бесплатных шаблонов административных панелей на разный вкус и цвет. Но Laravel из «коробки» не очень приспособлен для работы с Bootstrap.

Я не буду пересказывать документацию ни Bootstrap, ни Laravel. Укажу лишь на некоторые ключевые места, которые будут полезны.

Почти ручная работа с элементами форм в Laravel

Верстка элементов на Bootstrap обычна такая:

<div class="form-group">
    <label for="title">Название страницы</label>
    <input class="form-control" placeholder="Введите ссылку страницы " name="title" type="text" value="" id="title">
</div>

Как видите, ничего сложного. Но есть особенность — используется стиль класса «form-control».

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

В Laravel в FormBildere теоретически можно задать через массив особые свойства для отображения стилей:

Form::text('slug', $value, ['class' => 'form-control', 'placeholder' => 'Введите ссылку страницы ']);
$errors->first('keywords', '<p class="text-danger">:message</p>');

Однако откуда взять переменную $value? Если тупо пропустить значение, то php начинает ругаться на неправильный синтаксис. А если поставить просто кавычки или null, при косяках будет выводиться сообщение, но то что вы набирали потеряется. Ладно, это можно будет потерпеть в форме авторизации, но если вы создаете страницу с 10-20 полями, то обидно будет все это заново набирать.

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

Оказывается, в Laravel есть класс для работы с полями форм Input. Его можно не только использовать для получения данных из формы в таком виде:

$date = Input::all();

а потом разбирать этот массив по ключам, но передавать значения назад в форму через метод Old().

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

// выводим форму - метод GET
public function create()
{
    return View::make('admin.pages.create');
}
 
// сохраняем форму - метод PUT
public function store()
{
    $validator = Validator::make($data = Input::all(), Page::$rules);
 
    if ($validator->fails())
    {
        return Redirect::back()->withErrors($validator)->withInput();
    }
 
    Page::create($data);
 
    return Redirect::route('admin.pages.index');
}

То есть сначала показали форму. По нажатию на «сохранить» формы нас перекидывает в метод store() контроллера и мы обрабатываем данные.

Сначала данные сохраняются в переменную $data, на основании этих данных и массива правил валидации создается объект валидатора и проверяется условие: все ли в порядке. Если все хорошо, то у модели Page вызывается метод create с данными из формы для создания записи в базе и перебрасывает на роут вывода всех страниц контроллера.

Но нас интересует дальнейшая работа с формой если не все данные прошли валидацию. Вот как раз в условии нас возвращает назад, а в вьюху с формой передают сначала коллекцию с сообщениями валидации, а затем и данные, которые были введены. Что и требовалось!

А теперь глянем на вид с формой:

{{ Form::open(array('route' => 'admin.pages.store', 'files' => true)) }}
    <div class="form-group">
        {{ Form::label('title', 'Название страницы') }}
        {{ Form::text('title', Input::old('title'), ['class' => 'form-control', 'placeholder' => 'Введите ссылку страницы '])  }}
        {{ $errors->first('title', '<p class="text-danger">:message</p>') }}
    </div>
 
    <div class="form-group">
        {{ Form::label('slug', 'Постоянная ссылка') }}
        {{ Form::text('slug', Input::old('slug'), ['class' => 'form-control', 'placeholder' => 'Введите ссылку страницы '])  }}
        {{ $errors->first('slug', '<p class="text-danger">:message</p>') }}
    </div>
    .....
{{ Form::close() }}

Тут как раз показана магия: как вывести предыдущие значения поля если они были. Причем если форма выводится в первый раз, то показывается плейсхолдер. Так же обратите внимание на самое первое значение в одинарных кавычках. У label идет привязка по нему к input, у input это значение в массиве объекта Input, а у вывода ошибок это опять значение в массиве объекта Validation. Поставите другое, особенно во второй и третей строки одной группы и будете долго искать ошибку почему ничего не получается (как я сегодня 🙁 ).

Второй интересный момент — это вывод сообщений валидатора. Маленькая подсказка: если вы поставили язык допустим русский, но не создали в папке app/lang подпапки с этим языком и не перенесли/создали там файл validation.php, то получите «очень информативное» сообщение валидатора: validation.required. Все! Тоже долго сегодня не мог въехать, пока не решил создать русскую локаль.

Макросы для форм

Нашлись спецы, которые написали обертки для элементов FormBilder в Laravel.

Работает это так:

  1. В папке App/Start правится файл global.php, дописывают в конце макросы типа:
    Form::macro('myField', function()
    {
        return '<input type="awesome">';
    });
  2. В шаблоне уже прописывают так
    {{ Form::myField(); }}

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

Ссылка на основную публикацию