Models Resources

Основы

Основы

В сердце любой админ-панели лежат разделы для редактирования данных. MoonShine не является исключением и использует модели Eloquent для работы с базой данных, а для разделов используются стандартные ресурсные контроллеры и ресурсные маршруты Laravel.

Если бы вы разрабатывали самостоятельно, то создание ресурсных контроллеров и ресурсных маршрутов могло бы выглядеть так:

php artisan make:controller Controller --resource
Route::resource('resources', Controller::class);

Однако эту работу можно доверить админ-панели MoonShine, которая сгенерирует и объявит их самостоятельно.

ModelResource является основным компонентом для создания раздела в админ-панели при работе с базой данных.

Создание раздела

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="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'; // Поле для отображения значений в ссылках и хлебных крошках
 
//...
}

resource_paginate resource_paginate_dark

Объявление раздела в системе

Зарегистрировать ресурс в системе и сразу добавить ссылку на раздел в навигационное меню можно с помощью сервис-провайдера 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.

// или indexPageComponents/formPageComponents/detailPageComponents
public 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
{
//
}
// ...
}

Вы также можете подключить трейт к ресурсу и внутри трейта добавить метод по соглашению об именовании - boot{TraitName} и через трейт получить доступ к загрузке ресурса

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,
)
);
}
}