Расскажу о CRUD генераторе для Laravel. Для студенческой работы мне надо было сделать много CRUD формочек, последний раз когда у меня была такая задача (в 2017), я использовал Yii2 и Gii.
В этот раз я решил сделать решение на базе Laravel, но своего встроенного генератора для GUI в Ларавель не завезли, пришлось искать «стороннее» решение.
Гугл выдал четыре варианта, первым шёл CRUDBooster, с ним я бился пару часов, ни чего не получилось, код генериться, GUI нет.
Следующим был Craftable, с этим товарищем тоже пришлось повозиться, даже просто что бы его установить, но какой то GUI он генерил и я решил на этом варианте остановиться.
Ниже я расскажу о работе с Craftable и покажу пару скриншотов GUI.
Начало работы с Craftable
После установки обязательно выполните команды (в корневой директории проекта):
npm install && npm run dev
И после каждого изменения ресурсов в части JS («resources/js») надо выполнять команду:
npm run dev
При выполнении этой команды создаются новые бандлы для JS и CSS («public/js/admin.js» и «public/css/admin.css»), файлы бандлов лучше сразу добавить в ".gitignore", поскольку эти файлы автоматически генерируются, и нет смысла вести историю их изменений.
Вход в админку
Можно пользоваться встроенной админской учёткой, имя — «administrator@brackets.sk», пароль смотрим в скрипте миграции («protected $password = 'PjucggYEOK';») «database/migrations/2020_03_24_214249_fill_default_admin_user_and_permissions.php», часть имени файла «2020_03_24_214249_» у вас будет другой.
Можно зарегистрировать нового пользователя используя регистрацию из коробки Ларавеля.
После этого заходим в админку "/admin", и в меню выбираем «Manage access» ("/admin/admin-users"), и разрешаем доступ в админку для новой учётки.
Как работает генерация
Создаём таблицу базы данных, допустим «posts» и выполняем команду:
php artisan admin:generate posts
Craftable сгенерирует для нас:
- Модель
- Контроллер
- Классы FormRequest для всех действий (action) где требуется обработка данных формы
- Таблицу с разрешениями на действия и соответствующие проверки в контроллере
- Шаблоны представлений для всех CRUD действий (/resources/views/admin/%имя-вашей-таблицы%/)
- Переводы для всех подписей
- Классы для «посева» тестовых записей базы данных
Так же в методе контроллера index(), будет добавлен код для фильтрации значений базы данных, это очень удобно — если не надо, то выкинуть не сложно, если надо, то уже есть место куда писать логику фильтрации.
Не смотря на то что Craftable генерирует записи в таблицу Разрешений («permissions»), в админке нет странички для управления этими разрешениями. Без этого управлять разрешениями ролей не удобно, но конечно можно вообще не генерировать разрешения.
После генерации модели, выполняем:
npm run dev
Автоматически эта команда не выполняется.
Подробней о генерации в документации.
Представление для списка
Представление для создания записи
Представление для редактирования
Типы данных
Таблицу для генерации CRUD удобно делать с помощью миграции, потому что Craftable генерирует представления и правила валидации параметров формы исходя из типа колонки, при этом такие колонки как decimal не поддерживаются, и будут проигнорированы.
То есть:
- делаем миграцию, для создания колонки используем «integer()»,
- генерируем модель,
- откатываем миграцию,
- в миграции в описании таблицы заменяем «integer()» на «decimal()»,
- накатываем миграцию.
В итоге имеем и сгенерированный CRUD, и таблицу с нужными типами данных.
Типы которые поддерживаются:
- string
- text
- date
- datetime
- time
- boolean
Переводы
По умолчанию доступен только один язык, и в админке ни где нет возможности добавить ещё один язык для переводов. Что бы добавить ещё один язык, надо открыть файл "/config/translatable.php" и добавить желаемый язык.
Язык для интерфейса выбирается в профиле пользователя.
Craftable генерирует переводы для всех подписей и сообщений, это с одной стороны круто, а с другой стороны не очень.
Первый раз у меня в представлениях появились подстановки для переводов:
trans('admin.wood-specie.actions.index')
и сами переводы:
'wood-specie' => [
'title' => 'Wood Specie',
'actions' => [
'index' => 'Wood Specie',
'create' => 'New Wood Specie',
'edit' => 'Edit :name',
],
'columns' => [
'id' => 'ID',
'title' => 'Title',
'calculation_period' => 'Calculation period',
'timber_harvesting_age' => 'Timber harvesting age',
'main_harvesting_age' => 'Main harvesting age',
],
],
И это было очень круто!
Но для остальных страничек в представлениях генерировались подстановки, но сами переводы не генерировались (возможно потому что когда я генерировал первую модель, был задан только один язык, а когда генерировал остальные страницы, языков уже было два).
Поэтому пришлось открыть Translations (/admin/translations) и делать переводы в ручную, если кодов для перевода нет, то надо нажать кнопку «Re-scan translations» или выполнить команду:
php artisan admin-translations:scan-and-save
Когда переводы генерируются в файл их можно сохранить в репозитории, когда переводы создаются через «Re-scan translations», то они записываются в базу данных и накатывать их (при разворачивании нового «сервера») придётся SQL скриптом (или написать скрипт для генерации файла с переводами из записей базы данных).
Подробней о локализации в документации.
Использование Vue
Craftable генерирует JS скрипты для клиент сайд рендеринга с помощью Vue, это:
- index.js
- Listing.js
- Form.js
Если вам не нужны представления для списка (Listing.js) или для одиночной записи (Form.js), то вы можете удалить соответствующий файл и внести изменения в index.js.
Поскольку Vue получает наши шаблоны представлений как части компонента, то ни каких тегов
<script>
в представлении быть не должно и весь JS код должен быть в соответствующем файле.Если мы добавляем какое то свойство в нашу модель, и не делаем принудительную генерацию:
php artisan admin:generate --force posts
то нам необходимо в ручную добавить это новое свойство в Form.js.
Использование multiselect
В документации Craftable есть пример редактирования свойства, которое является внешним ключом, то есть в таблице храниться внешний ключ, но для редактирования мы используем не значение идентификатора, для редактирования мы используем выпадающий список со значениями из родительской таблицы.
У меня этот пример заработал не сразу.
Допустим у нас есть свойство «bonitet», значения для выпадающего списка мы передаём через атрибут компонента «bonitets», что бы задать список значений мы должны писать:
<multiselect
v-model="form.bonitet"
:options="$attrs.bonitets"
:multiple="false"
:searchable="false"
:allow-empty="false"
track-by="id"
label="title"
tag-placeholder="{{ __('Select Bonitet') }}"
placeholder="{{ __('Bonitet') }}">
</multiselect>
В примере из документации не используется $attrs, но у меня без этого компонент имел пустой список.
Если мы открываем страницу редактирования существующей записи, то для того что бы в выпадающем списке было выбрано текущее значение, то нам надо задать это значение на стороне сервера (PHP):
public function edit(ForestResource $forestResource)
{
$this->authorize('admin.forest-resource.edit', $forestResource);
$bonitet = $forestResource->bonitet()->get()[0];
$forestResource->bonitet = $bonitet;
return view('admin.forest-resource.edit', [
'forestResource' => $forestResource,
'specieTitle' => $forestResource->woodSpecie()->get()[0]->title,
'timberClassTitle' => $forestResource->timberClass()->get()[0]->title,
'bonitets' => Bonitet::all(),
]);
}
Ключевые строки это:
$bonitet = $forestResource->bonitet()->get()[0];
$forestResource->bonitet = $bonitet;
Конечно в модели у вас должно быть определено отношение bonitet():
public function bonitet()
{
return $this->belongsTo(Bonitet::class);
}
Кастомизация
Представления
Часть представлений, например меню админки, будет расположено в ресурсах «resources/views/admin/layout/sidebar.blade.php», другие части представления будут браться из исходников собственно Craftable — «vendor/brackets/admin-ui/resources/views/admin/partials/header.blade.php». Соответственно если мы хотим переделать эти части оформления, то мы копируем шаблоны представлений из исходников Craftable и меняем «ссылки», было:
@extends('brackets/admin-ui::admin.layout.default')
стало:
@extends('admin.layout.default')
Роуты
Все роуты которые добавляет Craftable будут требовать проверку на роль 'admin', будут иметь префикс «admin/», и неймспейс 'Admin':
/* Auto-generated admin routes */
Route::middleware(['auth:' . config('admin-auth.defaults.guard'), 'admin'])->group(static function () {
Route::prefix('admin')->namespace('Admin')->name('admin/')->group(static function() {
Route::prefix('cutting-areas')->name('cutting-areas/')->group(static function() {
Route::get('/','CuttingAreaController@index')->name('index');
});
});
});
У Craftable нет настройки для отключения генерации этих проверок, поэтому если вам это не требуется, то вы удаляете это в ручную.
Заключение
Работать с Craftable мне было удобно.
Репозиторий с примерами использования Craftable
alexeydg
посмотрите backpackforlaravel.com вот там очень богатый функционал, достаточно гибкая кастомизация
SbWereWolf Автор
мне показалось или он коммерческий?
alexeydg
если не на продажу, то его можно использовать бесплатно