Расскажу о 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
Only registered users can participate in poll. Log in, please.
Вы используете автогенерацию кода?
-
28.6%Нет такой необходимости2
-
28.6%Всё пишу сам2
-
0.0%Уже использую Craftable или другой инструмент0
-
14.3%Буду использовать Craftable1
-
28.6%Буду использовать, но точно не Craftable2
Специально для сайта ITWORLD.UZ. Новость взята с сайта Хабр