Не секрет, что большинство интерфейсов в админке сейчас строится на фреймворке 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.
Работает это так:
- В папке App/Start правится файл global.php, дописывают в конце макросы типа:
Form::macro('myField', function() { return '<input type="awesome">'; });
- В шаблоне уже прописывают так
{{ Form::myField(); }}
Как видите, ничего сложного нет. Так что можно обойтись и без сторонних пакетов. Вот здесь уже куча готовых шаблонов под Bootstrap 3 таких макросов. Так что остается вам выбрать нужное, подправить под себя и использовать.
Для Laravel 5.x это уже не актуально.
Достаточно в форме вставить такой код
{!! Form::label(‘body’, ‘Body:’) !!}
{!! Form::textarea(‘body’, null, [‘class’ => ‘form-control’]) !!}
И при фейле валидации просто редиректить на эту же форму без параметров, и вместо null будут подставлены уже введенные значения.
Спасибо, я с 4.х работаю.
Что за глупости? Зачем Вы используйте устаревшее решение в виде Laravel 4? Мало того что оно не поддерживается разработчиками, так еще т не дай бог придется поддерживать проект после таких «умельцев»
Знаете, написал 3 едких ответа и стер. Не хочу уподобляться вам. Я работаю с 4.2. Точка.
Я обычно использую https://anahkiasen.github.io/former/ , это здорово помогает сократить код формы в админ панели.
P.S. Есть способ пропустить Input::old(‘…’), но для этого нужно найти метод который вызывается при вызове Form::text, и посмотреть какой там параметр стоит вторым по дефолту.
Спасибо, я знаю про этот пакет. Но я не хочу ставить что-то без особой необходимости. А то для меню — еще один пакет, для хлебных крошек — еще один. И так далее. Да и хотелось просто сделать руками, без пакетов, подсказок. В свое удовольствие ?