Уже был тут? Может ты вторую часть искал?
Former - это название небольшого проекта, который я хочу тебе показать. Садись поближе, сейчас начнется...
Так вот, Former - это такой хитрый пакет PHP, который позволяет делать всевозможные манипуляции с формами, и он очень удобный в использовании. Да и вообще он крутой чувак, если узнать его поближе.
Former пережуёт все и положит тебе прямо в рот - он обработает за тебя и отвалидирует ввод, автоматически сгруппирует поля, отловит отчет об ошибке, и даже создаст разметку для твоего любимого css-фрейма (Bootstrap, Foundation). Ну а что бы узнать больше, я предлагаю тебе ознакомится со всеми, описанными ниже, фишками.
Former нацелен на переосмысление удобного создания форм - изменяем свойства каждого поля в его собственной модели, со своими методами и свойствами. Это значит, что можно мутить такие фишки типа:
Former::horizontal_open()
->id('MyForm')
->secure()
->rules(['name' => 'required'])
->method('GET')
Former::xlarge_text('name')
->class('myclass')
->value('Joseph')
->required();
Former::textarea('comments')
->rows(10)->columns(20)
->autofocus();
Former::actions()
->large_primary_submit('Submit')
->large_inverse_reset('Reset')
Former::close()
Каждый раз, когда ты вызываешь метод, которого на самом деле нет, Former думает, что ты пытаешься задать какой-то атрибут и создает его магически. Поэтому ты можешь мутить такие вещи, как в приведенном выше примере ->rows(10) ;
, а если ты хочешь задать атрибут который содержит дефисы, ты просто заменяешь дефисы подчеркиваниями:
->data_foo('bar')
преобразуется в data-foo="bar"
.
Теперь ты конечно спросишь: "а фто ефли я хатю падсеркивания в африбутах?"(ну охренеть, какой ты умный!). Ты всегда можешь обратится к методу setAttribute('data_foo', 'bar')
. И тадааам! Наслаждайся.
В общем, в этом самая суть. Однако, Former - это и кое что еще... Читай ниже и ты узнаешь, на что способен Former.
###Основная концепция Former был задуман как View helper – в том смысле, что он предоставляет тебе класс, который ты можешь использовать прямо во вьюхах, для вывода готового HTML-кода.
{{ Former::open()->method('GET') }}
{{ Former::text('name')->required() }}
{{ Former::close() }}
(шорттеги были заменены мной на blade-синтаксис - п.п.)
Но, ты точно также можешь запихать результат в переменную для передачи ее в шаблон в уже готовом виде:
$form = Former::open()->method('GET');
$form .= Former::text('name')->required();
$form .= Former::close();
Копируешь laravel3 ветку репозитория в папку со своими бандлами, и добавляешь 'former' => array('auto' => true)
в файл бандлов. Потом добавляешь алиас 'Former' => 'Former\Facades\Former
' в application файл, профит!
Установка Former'a проста, как два пальца об асфальт. Добавляешь строку в composer.json
:
"anahkiasen/former": "dev-master"
Допиливаешь поставщика Former'а в app/config/app.php
'Former\FormerServiceProvider',
и там же пишешь алиас:
'Former' => 'Former\Facades\Former',
###Или через установщик пакетов
Просто сделай artisan package:install anahkiasen/former:dev-master
и не парься.
###Без фрейма Также как и под Laravel 4, добавь Former в файл Composer'а. А потом:
use Former\Facades\Former;
И готово.
##Фишки ###Поддержка интеграции с Bootstrap и Foundation из коробки. Это все ништяк, но вроде выглядит, будто налепили модификашек на Laravel'овский Form-класс. Ну что у автора совсем нет фантазии? Вот где спрятана магия: Former распознает какого типа ты создаешь форму - вертикальную или горизонтальную, и сам оборачивает все поля в контрол-группы. Это значит, что если ты пишешь что-то вроде:
Former::select('clients')->options($clients, 2)
->help('Pick some dude')
->state('warning')
На выходе получится вот это (Bootstrap) :
<div class="control-group warning">
<label for="clients" class="control-label">Clients</label>
<div class="controls">
<select id="clients" name="clients">
<option value="0">Mickael</option>
<option value="1">Joseph</option>
<option value="2" selected="selected">Patrick</option>
</select>
<span class="help-inline">Pick some dude</span>
</div>
</div>
По умолчанию Former использует Twitter Bootstrap, но ты можешь выбрать какой фрейм использовать с помощью метода Former::framework()
. На данный момент поддерживаются 'TwitterBootstrap', 'ZurbFoundation' и 'Nude' (без фрейма).
// Выключаем Bootstrap
Former::framework('Nude');
// Включаем его назад (господи, да включи ты мозг)
Former::framework('TwitterBootstrap');
Да, да и для Foundation есть пример:
Former::framework('ZurbFoundation');
Former::four_text('foo')->state('error')->help('bar')
Выдаст :
<div class="error">
<label for="foo">Foo</label>
<input class="four" type="text" name="foo" id="foo">
<small>Bar</small>
</div>
####Связываем с Laravel'овским валидатором.
Ладно, ок, мы типа посчистли все от мусора и бесконечных вызовов Form::control_group()
. Теперь я слышу: "О, ты знаеф, я до фих пор проверял мои формы врусьную и со..." - нет, ты больше не будешь этого делать. Добро пожаловать в волшебный мир хелпера withErrors
, который сделает тебя счастливым, и заставит коров давать вдвое больше молока. Раз уж ты уже завернул свои хорошенькие поля в контрол-группы, осталось только пойти до конца - проверить объект валидации на ошибки, которые могут иметь поля, и добавить их в .help-inline.
Тут ты используешь Former по-разному в зависимости от, как твой код ведет себя после зафейленой проверки:
Если ты рендеришь вьюху при ошибке (без редиректа):
if($validation->fails()) {
Former::withErrors($validation);
return View::make('myview');
}
Если у тебя редирект при фейле:
if($validation->fails()) {
return Redirect::to('login')
->with_errors($validation);
}
В последнем примере уже не нужно вызывать Former::withErrors()
, ни в контроллере ни во вьюхе. Почему? Да потому что формер автоматом пытается распарсить ошибки в сессии, каждый раз, когда вызывается Former::open()
Формер любит тебя и заботится о тебе. Но конечно же, мой догадливый друг, ты как-то можешь отключить это поведение. А именно: Former::setOption('fetch_errors', false)
.
####Заполнение форм
Ты легко можешь заполонить форму данными используя метод Former::populate()
. Ты даже можешь сделать это двумя разными способами. Первый - это просто передать туда массив:
// Заполнит поле с именем 'name' значением 'value'
Former::populate( array('name' => 'value') )
А еще ты можешь передать прямо туда экземпляр модели Eloquent (это, кстати, открывает доступ к кое каким фишулям; но мы с тобой к этому еще вернемся).
Former::populate( Client::find(2) )
Former распознает модель, и заполнит соответствующие поля соответствующими значениями.
Ну и конечно, ты можешь переопределить определенные поля ( да я мастер каламбуров ) уже после того как ты их заполнил из модели или массива:
Former::populate($project)
Former::populateField('client', $project->client->name)
Оставшиеся поля формы можно легко заполнить просто запилив ->value('чето-там')
.
Чтобы создать список опций для селекта, ты можешь вызвать Former::select('foo')->options([array], [facultative: selected value])
. А еще ты можешь заполнить опции прямо из коллекции, типа вот так:
Former::select('foo')->fromQuery(Client::all(), 'name', 'id')
Первый аргумент - собственно сама коллекция, второй - имя атрибута, который пойдет в текст, а третий, как ты уже догадался - значение (которое, кстати, id
по дефолту ).
Former, между тем, и тут без магии не обошелся - можно вообще не передавать дополнительные аргументы в метод. Надо только саму модель настроить. Former получит ключ по Eloquent'овскому методу get_key()
, и использует __toString()
метод для отрисовки текста. Например так:
class Client extends Eloquent
{
public static $key = 'code';
public function __toString()
{
return $this->name;
}
}
Former::select('clients')->fromQuery(Client::all());
Все это отрисуется в подобный код:
<div class="control-group">
<label for="foo" class="control-label">Foo</label>
<div class="controls">
<select id="foo" name="foo">
@foreach(Client::all() as $client)
@if(Input::get('foo', Input::old('foo')) == $client->code)
<option selected="selected" value="{{ $client->code }}">{{ $client->name }}</option>
@else
<option value="{{ $client->code }}">{{ $client->name }}</option>
@endif
@endforeach
</select>
</div>
</div>
Former может даже заполнить поля прямо из отношений. Вместо тысячи слов:
Former::populate(Client::find(2))
// Заполняешь $client->name
Former::text('name')
// Заполняешь $client->store->name
Former::text('store.name')
// Да детка, еще глубже
Former::text('customer.name.adress')
// Заполняешь из всех дат в резерве
Former::select('reservations.date')
// По сути тоже самое ^
Former::select('reservations')->fromQuery($client->reservations, 'date')
// Если ты запилишь отношение в текстовое поле, вместо селекта,
// они успешно сконкатенируются
Former::text('customers.name') // Выведет "name, name, name"
// кстати, можно перименовать поле уже после заполнения, коли приспичит.
Former::text('comment.title')->name('title')
Конец первой части...