Skip to content

Instantly share code, notes, and snippets.

@greabock
Last active May 4, 2022 08:57
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save greabock/5e1be5e8b97cededb7fe to your computer and use it in GitHub Desktop.
Save greabock/5e1be5e8b97cededb7fe to your computer and use it in GitHub Desktop.
Вольный перевод офф доки по Former в двух частях. Часть первая

Уже был тут? Может ты вторую часть искал?


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();

Установка

Под Laravel 3

Копируешь laravel3 ветку репозитория в папку со своими бандлами, и добавляешь 'former' => array('auto' => true) в файл бандлов. Потом добавляешь алиас 'Former' => 'Former\Facades\Former' в application файл, профит!

Под Laravel 4

Установка 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')

Конец первой части...

Часть два

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment