- Основы
- Создание раздела
- Основные свойства раздела
- Объявление раздела в системе
- Текущий элемент/модель
- Модальные окна
- Перенаправления
- Активные действия
- Кнопки
- Модификация
- Компоненты
- Загрузка
Основы
В сердце любой админ-панели лежат разделы для редактирования данных. MoonShine не является исключением и использует модели Eloquent
для работы с базой данных, а для разделов используются стандартные ресурсные контроллеры и ресурсные маршруты Laravel.
Если бы вы разрабатывали самостоятельно, то создание ресурсных контроллеров и ресурсных маршрутов могло бы выглядеть так:
php artisan make:controller Controller --resource
php artisan make:controller Controller --resource
Route::resource('resources', Controller::class);
Route::resource('resources', Controller::class);
Однако эту работу можно доверить админ-панели MoonShine, которая сгенерирует и объявит их самостоятельно.
ModelResource
является основным компонентом для создания раздела в админ-панели при работе с базой данных.
Создание раздела
php artisan moonshine:resource Post
php artisan moonshine:resource Post
- измените имя ресурса, если требуется
- выберите тип ресурса
При создании ModelResource доступно несколько вариантов:
- Ресурс модели по умолчанию - ресурс модели с общими полями
- Отдельный ресурс модели - ресурс модели с разделением полей
- Ресурс модели со страницами - ресурс модели со страницами.
В результате будет создан класс PostResource
, который станет основой нового раздела в панели. По умолчанию он располагается в директории app/MoonShine/Resources
.
MoonShine автоматически, на основе имени, свяжет ресурс с моделью app/Models/Post
. Заголовок раздела также будет сгенерирован автоматически и будет "Posts".
Вы можете сразу указать привязку модели и заголовок раздела для команды:
php artisan moonshine:resource Post --model=CustomPost --title="Articles"
php artisan moonshine:resource Post --model=CustomPost --title="Articles"
php artisan moonshine:resource Post --model="App\Models\CustomPost" --title="Articles"
php artisan moonshine:resource Post --model="App\Models\CustomPost" --title="Articles"
Основные свойства раздела
Основные параметры, которые можно изменить для ресурса, чтобы настроить его работу
namespace App\MoonShine\Resources;use App\Models\Post;use MoonShine\Resources\ModelResource;class PostResource extends ModelResource{protected string $model = Post::class; // Модельprotected string $title = 'Posts'; // Заголовок разделаprotected array $with = ['category']; // Жадная загрузкаprotected string $column = 'id'; // Поле для отображения значений в ссылках и хлебных крошках//...}
namespace App\MoonShine\Resources;use App\Models\Post;use MoonShine\Resources\ModelResource;class PostResource extends ModelResource{protected string $model = Post::class; // Модельprotected string $title = 'Posts'; // Заголовок разделаprotected array $with = ['category']; // Жадная загрузкаprotected string $column = 'id'; // Поле для отображения значений в ссылках и хлебных крошках//...}
Объявление раздела в системе
Зарегистрировать ресурс в системе и сразу добавить ссылку на раздел в навигационное меню можно с помощью сервис-провайдера MoonShineServiceProvider
.
namespace App\Providers;use App\MoonShine\Resources\PostResource;use MoonShine\Providers\MoonShineApplicationServiceProvider;class MoonShineServiceProvider extends MoonShineApplicationServiceProvider{//...protected function menu(): array{return [MenuItem::make('Posts', new PostResource())];}//...}
namespace App\Providers;use App\MoonShine\Resources\PostResource;use MoonShine\Providers\MoonShineApplicationServiceProvider;class MoonShineServiceProvider extends MoonShineApplicationServiceProvider{//...protected function menu(): array{return [MenuItem::make('Posts', new PostResource())];}//...}
О расширенных настройках вы можете узнать в разделе Меню.
Если вам нужно только зарегистрировать ресурс в системе, не добавляя его в навигационное меню:
namespace App\Providers;use App\MoonShine\Resources\PostResource;use MoonShine\Providers\MoonShineApplicationServiceProvider;class MoonShineServiceProvider extends MoonShineApplicationServiceProvider{protected function resources(): array{return [new PostResource()];}//...}
namespace App\Providers;use App\MoonShine\Resources\PostResource;use MoonShine\Providers\MoonShineApplicationServiceProvider;class MoonShineServiceProvider extends MoonShineApplicationServiceProvider{protected function resources(): array{return [new PostResource()];}//...}
Текущий элемент/модель
Если url страницы детального просмотра или редактирования содержит параметр resourceItem
, то в ресурсе вы можете получить доступ к текущему элементу через метод getItem()
.
$this->getItem();
$this->getItem();
Вы можете получить доступ к модели через метод getModel()
.
$this->getModel();
$this->getModel();
Модальные окна
Возможность добавления, редактирования и просмотра записей прямо на странице со списком в модальном окне.
namespace App\MoonShine\Resources;use App\Models\Post;use MoonShine\Resources\ModelResource;class PostResource extends ModelResource{protected string $model = Post::class;protected string $title = 'Posts';protected bool $createInModal = false;protected bool $editInModal = false;protected bool $detailInModal = false;//...}
namespace App\MoonShine\Resources;use App\Models\Post;use MoonShine\Resources\ModelResource;class PostResource extends ModelResource{protected string $model = Post::class;protected string $title = 'Posts';protected bool $createInModal = false;protected bool $editInModal = false;protected bool $detailInModal = false;//...}
Перенаправления
По умолчанию при создании и редактировании записи выполняется редирект на страницу с формой, но этим поведением можно управлять.
// Через свойство в ресурсеprotected ?PageType $redirectAfterSave = PageType::FORM;// или через методы (также доступен редирект после удаления)public function redirectAfterSave(): string{return '/';}public function redirectAfterDelete(): string{return to_page(CustomPage::class);}
// Через свойство в ресурсеprotected ?PageType $redirectAfterSave = PageType::FORM;// или через методы (также доступен редирект после удаления)public function redirectAfterSave(): string{return '/';}public function redirectAfterDelete(): string{return to_page(CustomPage::class);}
Активные действия
Часто бывает, что необходимо создать ресурс, в котором будет исключена возможность удаления, или добавления, или редактирования. Причем речь идет не об авторизации, а о глобальном исключении этих разделов. Делается это предельно просто с помощью метода getActiveActions
в ресурсе.
namespace MoonShine\Resources;class PostResource extends ModelResource{//...public function getActiveActions(): array{return ['create', 'view', 'update', 'delete', 'massDelete'];}//...}
namespace MoonShine\Resources;class PostResource extends ModelResource{//...public function getActiveActions(): array{return ['create', 'view', 'update', 'delete', 'massDelete'];}//...}
Кнопки
По умолчанию на странице индекса ресурса модели есть только кнопка создания.
Метод actions()
позволяет добавить дополнительные кнопки.
namespace MoonShine\Resources;class PostResource extends ModelResource{//...public function actions(): array{return [ActionButton::make('Refresh', '#')->dispatchEvent(AlpineJs::event(JsEvent::TABLE_UPDATED, 'index-table'))];}//...}
namespace MoonShine\Resources;class PostResource extends ModelResource{//...public function actions(): array{return [ActionButton::make('Refresh', '#')->dispatchEvent(AlpineJs::event(JsEvent::TABLE_UPDATED, 'index-table'))];}//...}
Отображение
Вы также можете изменить отображение кнопок, отображать их в строке или в выпадающем меню для экономии места.
namespace MoonShine\Resources;class PostResource extends ModelResource{//...public function actions(): array{return [ActionButton::make('Button 1', '/')->showInLine(),ActionButton::make('Button 2', '/')->showInDropdown()];}//...}
namespace MoonShine\Resources;class PostResource extends ModelResource{//...public function actions(): array{return [ActionButton::make('Button 1', '/')->showInLine(),ActionButton::make('Button 2', '/')->showInDropdown()];}//...}
Модификация
Для модификации основных компонентов страниц IndexPage, FormPage или DetailPage из ресурса можно переопределить соответствующие методы modifyListComponent()
, modifyFormComponent()
и modifyDetailComponent()
.
public function modifyListComponent(MoonShineRenderable $component): MoonShineRenderable{return parent::modifyListComponent($component)->customAttributes(['data-my-attr' => 'value']);}
public function modifyListComponent(MoonShineRenderable $component): MoonShineRenderable{return parent::modifyListComponent($component)->customAttributes(['data-my-attr' => 'value']);}
public function modifyFormComponent(MoonShineRenderable $component): MoonShineRenderable{return parent::modifyFormComponent($component)->fields([FlexibleRender::make('Top'),...parent::modifyFormComponent($component)->getFields()->toArray(),FlexibleRender::make('Bottom'),])->submit('Go');}
public function modifyFormComponent(MoonShineRenderable $component): MoonShineRenderable{return parent::modifyFormComponent($component)->fields([FlexibleRender::make('Top'),...parent::modifyFormComponent($component)->getFields()->toArray(),FlexibleRender::make('Bottom'),])->submit('Go');}
public function modifyDetailComponent(MoonShineRenderable $component): MoonShineRenderable{return parent::modifyDetailComponent($component)->customAttributes(['data-my-attr' => 'value']);}
public function modifyDetailComponent(MoonShineRenderable $component): MoonShineRenderable{return parent::modifyDetailComponent($component)->customAttributes(['data-my-attr' => 'value']);}
Компоненты
Лучший способ изменить компоненты страниц - это опубликовать страницы и взаимодействовать через них, но если вы хотите быстро добавить компоненты на страницы, то можете использовать методы ресурса pageComponents
, indexPageComponents
, formPageComponents
, detailPageComponents
.
// или indexPageComponents/formPageComponents/detailPageComponentspublic function pageComponents(): array{return [Modal::make('My Modal'components: PageComponents::make([FormBuilder::make()->fields([Text::make('Title')])]))->name('demo-modal')];}
// или indexPageComponents/formPageComponents/detailPageComponentspublic function pageComponents(): array{return [Modal::make('My Modal'components: PageComponents::make([FormBuilder::make()->fields([Text::make('Title')])]))->name('demo-modal')];}
Компоненты будут добавлены в bottomLayer
Загрузка
Если вам нужно добавить логику в работу ресурса, когда он активен и загружен, то используйте метод onBoot
.
namespace App\MoonShine\Resources;use App\Models\Post;use MoonShine\Resources\ModelResource;class PostResource extends ModelResource{// ...protected function onBoot(): void{//}// ...}
namespace App\MoonShine\Resources;use App\Models\Post;use MoonShine\Resources\ModelResource;class PostResource extends ModelResource{// ...protected function onBoot(): void{//}// ...}
Рецепт: Изменение хлебных крошек из ресурса.
Вы также можете подключить трейт к ресурсу и внутри трейта добавить метод по соглашению об именовании - boot{TraitName}
и через трейт получить доступ к загрузке ресурса
namespace App\MoonShine\Resources;use App\Models\Post;use MoonShine\Resources\ModelResource;use App\Traits\WithPermissions;class PostResource extends ModelResource{use WithPermissions;}
namespace App\MoonShine\Resources;use App\Models\Post;use MoonShine\Resources\ModelResource;use App\Traits\WithPermissions;class PostResource extends ModelResource{use WithPermissions;}
trait WithPermissions{protected function bootWithPermissions(): void{$this->getPages()->findByUri(PageType::FORM->value)->pushToLayer(layer: Layer::BOTTOM,component: Permissions::make(label: 'Permissions',resource: $this,));}}
trait WithPermissions{protected function bootWithPermissions(): void{$this->getPages()->findByUri(PageType::FORM->value)->pushToLayer(layer: Layer::BOTTOM,component: Permissions::make(label: 'Permissions',resource: $this,));}}