# Основы
В основе любой админ-панели лежат разделы для редактирования данных.
MoonShine не является исключением в этом
и для работы с базой данных использует Eloquent
модели,
а для разделов стандартные Laravel ресурс контроллеры и ресурс маршруты.
Если бы вы разрабатывали самостоятельно, то создать ресурс контроллеры и ресурс маршруты можно следующим образом:
php artisan make:controller Controller --resource
Route::resource('resources', Controller::class);
Но эту работу можно поручить админ-панели MoonShine, которая будет их генерировать и объявлять самостоятельно.
ModelResource
является основным компонентом для создания раздела
в админ-панели при работе с базой данных.
# Создание раздела
php artisan moonshine:resource Post
- измените название вашего ресурса, если требуется
- выберите тип ресурса
При создания ModelResource доступно несколько вариантов:
- Default model resource - ресурс модели с общими полями
- Separate model resource - ресурс модели с разделением полей
- Model resource with pages - ресурс модели со страницами.
В результате создастся класс PostResource
, который будет основой нового раздела в панели.
Располагается он, по умолчанию, в директории app/MoonShine/Resources
.
MoonShine автоматически, исходя из названия, привяжет ресурс к модели app/Models/Post
.
Заголовок раздела так же сгенерируется автоматически и будет "Posts".
Можно сразу указать команде привязку к модели и заголовок раздела:
php artisan moonshine:resource Post --model=CustomPost --title="Статьи"
php artisan moonshine:resource Post --model="App\Models\CustomPost" --title="Статьи"
# Основные свойства раздела
Основные параметры, которые можно менять у ресурса, чтобы кастомизировать его работу
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']; // Eager load 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 resources(): array { return [ new PostResource() ]; } //...}
# Текущий элемент/модель
Если в url детальной страницы или страницы редактирования присутствует параметр resourceItem
,
то в ресурсе вы можете получить доступ к текущему элементу через метод getItem()
.
$this->getItem();
Через метод 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; //...}
# Редиректы
По умолчанию при создании и редактировании записи осуществляется редирект на страницу с формой, но это поведение можно контролировать
// Через свойство в ресурсе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']; } //...}
# Кнопки
По умолчанию на индексной странице ресурса модели присутствует только кнопка для создания.
Метод 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('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 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' ]);}
# Компоненты
Лучший способ изменять компоненты страниц это опубликовать страницы
и взаимодействовать через них, но если вы хотите быстро добавить компоненты на страницы,
то можете воспользоваться методами ресурса pageComponents
,
indexPageComponents
,
formPageComponents
,
detailPageComponents
// or indexPageComponents/formPageComponents/detailPageComponentspublic function pageComponents(): array{ return [ Modal::make( 'My Modal', components: PageComponents::make([ FormBuilder::make()->fields([ Text::make('Title') ]) ]) ) ->name('demo-modal') ];}
Компоненты будут добавлены в bottomLayer
# Boot
Если Вам необходимо добавить логику в работу ресурса в момент когда он активен и загружен,
то воспользуйтесь методом onBoot
namespace App\MoonShine\Resources; use App\Models\Post;use MoonShine\Resources\ModelResource; class PostResource extends ModelResource{ // ... protected function onBoot(): void { // } // ...}
Рецепт: Изменение breadcrumbs из ресурса .
Вы также можете подключить trait к ресурсу и внутри trait добавить метод согласно конвенции наименований - boot{TraitName} и через трейт обратится к boot ресурса
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, ) ); }}