Создание CRUD операций с Laravel Backpack

Продолжение цикла статей о Laravel Backpack. По умолчанию все CRUD имеют эти операции:

  • Create — с помощью формы создания
  • ListEntries — с использованием AJAX DataTables (он же «список записей» или «табличный вид»)
  • Update — с использованием формы обновления (также называемой «формой редактирования»)
  • Delete — с помощью кнопки в списке записей

Это основные операции, которые администратор может выполнить для модели Eloquent, благодаря Backpack. Также есть дополнительные операции (Preview, Reorder, Revisions), и вы можете легко создать пользовательскую операцию. Рассмотрим самые важные функции операций, которые вы будете использовать все время: ListEntries, Create и Update .

Tag CRUD - List Entries OperationОперации создания и редактирования

Tag CRUD - Edit Operation

Поля форм

Внутри метода setup() контроллера вы можете определить, какие поля вы хотите показывать администратору при создании и обновлении записей. В примере из прошлой части есть два поля и оба текстового типа. Когда администратор нажимает кнопку «Сохранить», если модель имеет эти два атрибута как $fillable, Backpack сохранит запись и перенаправит пользователя на страницу ListEntries. Внутри модели вы можете использовать аксессоры, мутаторы, события и т. д.

Но рано или поздно текстовых полей окажется недостаточно и вы захотите большего. Вам понадобятся дата-пикеры, кнопки загрузки файлов, отношения 1-n, отношения n-n, textarea и т. д. Для каждого поля нужно правильно определить его в методе setup() контроллера. Вот наиболее используемые методы для управления полями:

// Вы можете передать второй параметр с нужными операциями:
// - "create" для Create
// - "update" для Update
// - ничего (отсутствует) для Create и Update
$this->crud->addField($field_definition_array);
$this->crud->addFields([$field_definition_array_1, $field_definition_array_2]);
$this->crud->removeField('name');
$this->crud->removeFields(['name_1', 'name_2']);
// быстрый способ добавления простых полей: пусть сам CRUD определит тип поля
$this->crud->addField('db_column_name');

Для типичного определения массива полей потребуется как минимум три вещи:

  • name — атрибут (столбец в базе данных), который также станет именем поля ввода;
  • type — тип поля, которое мы хотели бы использовать (текст, число, select2 и т. д.);
  • label — метка для пользователя (будет генерироваться на основе имени, если не указано);

Вы можете использовать один из 44+ типов полей, которые идут в комплекте, или легко создать настраиваемый тип поля или даже переопределить поведение типа поля, если у вас есть какая-то сверх-специфическая потребность. Разные типы полей могут иметь дополнительные параметры для настройки и конфигурации. Ещё один пример, немного сложнее, чем текстовые поля. То, что вы обнаружите, постоянно сталкивается с полями отношений. Итак, предположим, что модель тега имеет отношение n-n с моделью статьи:

public function articles() {
        return $this->belongsToMany('App\Models\Article', 'article_tag');
    }

Можно использовать следующий код, чтобы добавить поле select2_multiple в формы обновления тега:

$this->crud->addField([
    'type' => 'select2_multiple',
    // имя отношения в модели
    'name' => 'articles',
    // имя отношения в модели
    'entity' => 'articles',
    // атрибут Article, который будет показан пользователю
    'attribute' => 'title',
    // при создании и обновлении вам нужно добавлять/удалять записи сводной таблицы?
    'pivot' => true,
], 'update');

Из-за последнего параметра («update») поле будет добавляться только в форму «Обновить», но не в «Создать»). Поскольку не указан label, Backpack возьмёт name «articles» и превратит его в label «Articles». Для CRUD articles логично создать обратные отношения, определённые в модели Article, в которую можно добавить поле select2_multiple, чтобы позволить администратору выбирать, какие теги относятся к каждой статье.

$this->crud->addField([
    'label' => "Tags",
    'type' => 'select2_multiple',
    // метод, который определяет отношения в модели
    'name' => 'tags',
    // метод, который определяет отношения в модели
    'entity' => 'tags',
    // атрибут внешнего ключа, который отображается пользователю
    'attribute' => 'name',
    // при создании и обновлении нужно добавлять/удалять записи сводной таблицы?
    'pivot' => true,
]);

Поскольку последний параметр отсутствует, поле будет добавлено в обе формы — «Создать и обновить».

При создании CrudController вы будете использовать $this->crud->setFromDb(); метод по умолчанию, который пытается выяснить, какие поля вам могут понадобиться в формах создания, обновления и в представлении списка, но, как и следовало ожидать, работает только для простых типов полей. Поэтому лучше воспользоваться одним из способов:

  • оставьте setFromDb() и добавьте, удалите и измените дополнительные поля
  • удалите setFromDb() и вручную определите каждое поле и столбец

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

Функции обратного вызова

Разработчики, которые ранее работали с GroceryCRUD в CodeIgniter или с другими подобными системами CRUD, хорошо знакомы с обратными вызовами before_insert, before_update, after_insert, after_update.

В Backpack нет обратных вызовов, потому что в этом нет необходимости. Код для операций создания и обновления открыт для переопределения и изменения. Обратите внимание, что у EntityCrudController уже есть следующие методы, которые можно изменить по своему усмотрению:

public function store(StoreRequest $request) {
    // <---------  место для логики обратного вызова before_insert
    $response = parent::storeCrud();
    // <---------  место для логики обратного вызова after_insert
    return $response;
}
public function update(UpdateRequest $request) {
    // <---------  место для логики обратного вызова before_update
    $response = parent::updateCrud();
    // <---------  место для логики обратного вызова after_update
    return $response;
}

Но прежде чем вы это сделаете, спросите себя — это то, что должно быть сделано, когда запись добавляется/обновляется/удаляется из приложения? Если это так, лучшим местом для неё будет модель. Помните, что ваша модель представляет собой чистую Eloquent модель, поэтому самым лучшим способом может быть использование Eloquent Event Observer или аксессуаров и мутаторов.

Операция ListEntries

ListEntries показывает администратору таблицу со всеми записями. В пользовательском интерфейсе информация вытягивается с использованием AJAX-запросов и отображается с помощью DataTables. Это самая функциональная операция в Backpack, которая отображает самые важные функции: столбцы, фильтры и кнопки.

Столбцы

Столбцы помогают указать, какие атрибуты отображаются в таблице и в каком порядке. Они определены в методе setup(), то же, что и в полях, и их синтаксис слишком похож на поля:

// добавить один столбец в конец таблиц
$this->crud->addColumn($column_definition_array);
// добавить несколько столбцов в конец таблицы
$this->crud->addColumns([$column_definition_array_1, $column_definition_array_2]);
$this->crud->removeColumn('column_name'); // remove a column from the table
// удалить несколько столбцов из таблицы
$this->crud->removeColumns(['column_name_1', 'column_name_2']);
$this->crud->setColumnDetails('column_name', ['attribute' => 'value']);
$this->crud->setColumnsDetails(['column_1', 'column_2'], ['attribute' => 'value']);
// заменить столбцы в таблице на новые
$this->crud->setColumns([$column_definition_array_1, $column_definition_array_2]);

Вы можете использовать один из 14 + типов столбцов, чтобы показывать информацию пользователю в таблице, или легко создать собственный тип столбца, если у вас есть сверх-специфическая потребность. Ниже приведён пример использования вышеприведённых методов:

$this->crud->addColumn([
            'name' => 'published_at',
            'type' => 'date',
            'label' => 'Publish_date',
 ]);
// для быстрого добавления текстового столбца просто передайте строку имени вместо массива
// добавить текстовый столбец в конец таблицы
$this->crud->addColumn('text');

Фильтры

Monster CRUD - List Entries Filters

Фильтры обеспечивают простой способ фильтровать таблицу ListEntries. Синтаксис очень похож на поля и столбцы, и вы можете использовать один из существующих 8 типов фильтров или легко создать собственный фильтр.

$this->crud->addFilter($options, $values, $filter_logic);
$this->crud->removeFilter($name);
$this->crud->removeAllFilters();

Подробнее об этом, смотрите на странице документации по фильтрам.

Кнопки

Tag CRUD - List Entries Buttons

Вы можете добавлять и удалять пользовательские кнопки к записям.

// positions: 'beginning' and 'end'
// stacks: 'line', 'top', 'bottom'
// types: view, model_function
$this->crud->addButton($stack, $name, $type, $content, $position);
$this->crud->removeButton($name);
$this->crud->removeButtonFromStack($name, $stack);

Вот и всё! Это был самый важный и длинный урок по Laravel Backpack. Смотрите также и остальные статьи на эту тему: