- Основы
- Создание
- Базовые свойства
- Объявление в системе
- Автозагрузка
- Добавление в меню
- Текущий элемент/модель
- Модальные окна
- Редиректы
- Активные действия
- Кнопки
- Модификаторы
- Компоненты
- Жизненный цикл
- Assets
- Response модификаторы
Основы
ModelResource
расширяет CrudResource
и предоставляет функциональность для работы с моделями Eloquent.
Он обеспечивает основу для создания ресурсов, связанных с моделями базы данных.
ModelResource
предоставляет методы для выполнения CRUD-операций, управления отношениями, применения фильтров и многое другое.
Вы также можете ознакомиться с разделом CrudResource.
CrudResource
- это абстрактный класс предоставляющий базовый интерфейс для CRUD
операций без привязки к хранилищу и типу данных.
Под капотом, ModelResource
расширяет CrudResource
и сразу включает возможность работы с Eloquent
.
Если углубляться в детали MoonShine, то вы увидите все те же стандартные Controller
, Model
и blade views
.
Если бы вы разрабатывали самостоятельно, то создать ресурс контроллеры и ресурс маршруты можно следующим образом:
php artisan make:controller Controller --resource
use Illuminate\Support\Facades\Route; Route::resource('resources', Controller::class);
Но эту работу можно поручить админ-панели MoonShine, которая будет их генерировать и объявлять самостоятельно.
ModelResource
является основным компонентом для создания раздела в админ-панели при работе с базой данных.
Создание
php artisan moonshine:resource Post
Для более подробной информации обратитесь к разделу Команды.
Базовые свойства
Базовые параметры, которые можно менять у ресурса, чтобы кастомизировать его работу.
namespace App\MoonShine\Resources; use App\Models\Post;use MoonShine\Laravel\Resources\ModelResource; /** * @extends ModelResource<Post> */class PostResource extends ModelResource{ // Модель protected string $model = Post::class; // Заголовок раздела protected string $title = 'Posts'; // Eager load protected array $with = ['category']; // Поле для отображения значений в связях и хлебных крошках protected string $column = 'id'; // ...}
Объявление в системе
Ресурс автоматически регистрируется в MoonShineServiceProvider
при вызове команды php artisan moonshine:resource
.
Но если вы создаете раздел вручную, то вам необходимо самостоятельно его объявить в системе в MoonShineServiceProvider
.
namespace App\Providers; use App\MoonShine\Resources\ArticleResource; use Illuminate\Support\ServiceProvider;use MoonShine\Contracts\Core\DependencyInjection\CoreContract;use MoonShine\Laravel\DependencyInjection\ConfiguratorContract;use MoonShine\Laravel\DependencyInjection\MoonShine;use MoonShine\Laravel\DependencyInjection\MoonShineConfigurator; class MoonShineServiceProvider extends ServiceProvider{ /** * @param MoonShine $core * @param MoonShineConfigurator $config * */ public function boot( CoreContract $core, ConfiguratorContract $config, ): void { $core ->resources([ MoonShineUserResource::class, MoonShineUserRoleResource::class, ArticleResource::class, // ... ]) ->pages([ ...$config->getPages(), ]) ; }}
Автозагрузка
В MoonShine также доступна автозагрузка страниц и ресурсов.
Она выключена по-умолчанию и для активации нужно вызвать метод autoload()
в MoonShineServiceProvider
вместо указания ссылок на страницы и ресурсы.
namespace App\Providers; use App\MoonShine\Resources\ArticleResource; use Illuminate\Support\ServiceProvider;use MoonShine\Contracts\Core\DependencyInjection\CoreContract;use MoonShine\Laravel\DependencyInjection\ConfiguratorContract; class MoonShineServiceProvider extends ServiceProvider{ public function boot( CoreContract $core, ConfiguratorContract $config, ): void { $core->autoload(); }}
При деплое проекта на продакшен в Laravel 11 рекомендуется вызывать консольную команду php artisan optimize
.
Помимо её основных функций, она также выполнит кэширование ресурсов MoonShine.
При использовании Laravel 10 необходимо вручную вызывать консольную команду php artisan moonshine:optimize
для оптимизации процесса инициализации админ панели.
Очистить кэш панели можно как командой php artisan optimize:clear
в Laravel 11, так и прямым вызовом консольной команды php artisan moonshine:optimize-clear
.
Если после создания классов приложение их не видит - обновите кэш композера командой composer dump-autoload
.
Добавление в меню
Все страницы в MoonShine имеют Layout
и у каждой страницы он может быть свой.
По умолчанию при установке MoonShine добавляет базовый MoonShineLayout
в директорию app/MoonShine/Layouts
.
В Layout
кастомизируется всё, что отвечает за внешний вид ваших страниц и это касается также и навигации.
Чтобы добавить раздел в меню, необходимо объявить его через метод menu()
в Layout
.
namespace App\MoonShine\Layouts; use App\MoonShine\Resources\PostResource; use MoonShine\Laravel\Layouts\CompactLayout;use MoonShine\Laravel\Resources\MoonShineUserResource;use MoonShine\Laravel\Resources\MoonShineUserRoleResource;use MoonShine\MenuManager\MenuGroup;use MoonShine\MenuManager\MenuItem; final class MoonShineLayout extends CompactLayout{ // ... protected function menu(): array { return [ MenuGroup::make(__('moonshine::ui.resource.system'), [ MenuItem::make( __('moonshine::ui.resource.admins_title'), MoonShineUserResource::class ), MenuItem::make( __('moonshine::ui.resource.role_title'), MoonShineUserRoleResource::class ), ]), MenuItem::make('Posts', PostResource::class), // ... ]; }}
О расширенных настройках Layout
можно узнать в разделе Layout.
О расширенных настройках MenuManager
можно узнать в разделе Menu.
Alias
По умолчанию alias ресурса, который используется в url
, генерируется на основе наименования класс в kebab-case
, например:
MoonShineUserResource
-> moon-shine-user-resource
.
Для того чтобы изменить alias
, можно воспользоваться свойством ресурса $alias
или методом getAlias()
.
namespace App\MoonShine\Resources; use MoonShine\Laravel\Resources\ModelResource; class PostResource extends ModelResource{ protected ?string $alias = 'custom-alias'; // ...}
или
namespace App\MoonShine\Resources; use MoonShine\Laravel\Resources\ModelResource; class PostResource extends ModelResource{ public function getAlias(): ?string { return 'custom-alias'; }}
Текущий элемент/модель
Если в url
детальной страницы или страницы редактирования присутствует параметр resourceItem
, то в ресурсе вы можете получить доступ к текущему элементу через метод getItem()
.
$this->getItem();
Через метод getModel()
можно получить доступ к модели.
$this->getModel();
Модальные окна
Вы можете добавлять, редактировать и просматривать записи прямо на странице со списком в модальном окне.
namespace App\MoonShine\Resources; use MoonShine\Laravel\Resources\ModelResource; class PostResource extends ModelResource{ protected bool $createInModal = true; protected bool $editInModal = true; protected bool $detailInModal = true; // ...}
Редиректы
По умолчанию при создании и редактировании записи осуществляется редирект на страницу с формой, но это поведение можно контролировать.
use MoonShine\Support\Enums\PageType; // Через свойство в ресурсеprotected ?PageType $redirectAfterSave = PageType::FORM; // или через методы (также доступен редирект после удаления) public function getRedirectAfterSave(): string{ return '/';} public function getRedirectAfterDelete(): string{ return $this->getIndexPageUrl();}
Активные действия
Часто бывает, что необходимо создать ресурс, в котором будет исключена возможность удалять, или добавлять, или редактировать.
И здесь речь не об авторизации, а о глобальном исключении этих разделов.
Делается это крайне просто за счет метода activeActions()
в ресурсе.
namespace App\MoonShine\Resources; use MoonShine\Support\ListOf;use MoonShine\Laravel\Enums\Action;use MoonShine\Laravel\Resources\ModelResource; class PostResource extends ModelResource{ // ... protected function activeActions(): ListOf { return parent::activeActions() ->except(Action::VIEW, Action::MASS_DELETE) // ->only(Action::VIEW) ; }}
Также можно просто создать новый список, например:
use MoonShine\Laravel\Enums\Action;use MoonShine\Support\ListOf; protected function activeActions(): ListOf{ return new ListOf(Action::class, [Action::VIEW, Action::UPDATE]);}
Кнопки
По умолчанию на индексной странице ресурса модели присутствует только кнопка для создания.
Метод topButtons()
позволяет добавить дополнительные кнопки.
namespace App\MoonShine\Resources; use MoonShine\Laravel\Resources\ModelResource;use MoonShine\Support\AlpineJs;use MoonShine\Support\Enums\JsEvent;use MoonShine\Support\ListOf;use MoonShine\UI\Components\ActionButton; class PostResource extends ModelResource{ // ... protected function topButtons(): ListOf { return parent::topButtons()->add( ActionButton::make('Refresh', '#') ->dispatchEvent(AlpineJs::event(JsEvent::TABLE_UPDATED, $this->getListComponentName())) ); }}
Отображение
Вы также можете изменить отображение кнопок, отображать их в линию или же в выпадающем меню для экономии места.
namespace App\MoonShine\Resources; use MoonShine\Support\ListOf;use MoonShine\UI\Components\ActionButton; class PostResource extends ModelResource{ // ... protected function indexButtons(): ListOf { return parent::indexButtons()->prepend( ActionButton::make('Button 1', '/') ->showInLine(), ActionButton::make('Button 2', '/') ->showInDropdown(), ); }}
Модификаторы
Для модификации основного компонента IndexPage
, FormPage
или DetailPage
страницы из ресурса можно переопределить соответствующие методы modifyListComponent()
, modifyFormComponent()
и modifyDetailComponent()
.
use MoonShine\Contracts\UI\ComponentContract; public function modifyListComponent(ComponentContract $component): ComponentContract{ return parent::modifyListComponent($component)->customAttributes([ 'data-my-attr' => 'value' ]);}
use MoonShine\Contracts\UI\ComponentContract;use MoonShine\UI\Components\FlexibleRender; public function modifyFormComponent(ComponentContract $component): ComponentContract{ return parent::modifyFormComponent($component)->fields([ FlexibleRender::make('Top'), ...parent::modifyFormComponent($component)->getFields()->toArray(), FlexibleRender::make('Bottom'), ])->submit('Go');}
use MoonShine\Contracts\UI\ComponentContract; public function modifyDetailComponent(ComponentContract $component): ComponentContract{ return parent::modifyDetailComponent($component)->customAttributes([ 'data-my-attr' => 'value' ]);}
Компоненты
Лучший способ изменить компоненты страниц - это опубликовать страницы и взаимодействовать через них.
Но, если вы хотите быстро добавить компоненты на страницы, то можете воспользоваться методами ресурса pageComponents()
, indexPageComponents()
, formPageComponents()
и detailPageComponents()
.
use MoonShine\Core\Collections\Components;use MoonShine\UI\Components\FormBuilder;use MoonShine\UI\Components\Modal;use MoonShine\UI\Fields\Text; // or indexPageComponents/formPageComponents/detailPageComponentsprotected function pageComponents(): array{ return [ Modal::make( 'My Modal' components: Components::make([ FormBuilder::make()->fields([ Text::make('Title') ]) ]) ) ->name('demo-modal') ];}
Компоненты будут добавлены в bottomLayer
.
Жизненный цикл
Resource
имеет несколько различных методов подключения к различным частям своего жизненного цикла. Давайте пройдемся по ним:
Активный ресурс
Метод onLoad()
дает возможность интегрироваться в момент когда ресурс загружен и в данный момент является активным.
namespace App\MoonShine\Resources; use MoonShine\Laravel\Resources\ModelResource; class PostResource extends ModelResource{ // ... protected function onLoad(): void { // ... }}
Рецепт: Изменение breadcrumbs из ресурса.
Вы также можете подключить trait
к ресурсу и внутри trait
добавить метод согласно конвенции наименований - load{TraitName}
и через трейт обратиться к onLoad
ресурса.
namespace App\MoonShine\Resources; use App\Traits\WithPermissions;use MoonShine\Laravel\Resources\ModelResource; class PostResource extends ModelResource{ use WithPermissions; // ...}
use MoonShine\Support\Enums\Layer;use MoonShine\Support\Enums\PageType; trait WithPermissions{ protected function loadWithPermissions(): void { $this->getPages() ->findByUri(PageType::FORM->value) ->pushToLayer( layer: Layer::BOTTOM, component: Permissions::make( label: 'Permissions', resource: $this, ) ); }}
Создание экземпляра
Метод onBoot
дает возможность интегрироваться в момент когда MoonShine создает экземпляр ресурса в системе.
namespace App\MoonShine\Resources; use MoonShine\Laravel\Resources\ModelResource; class PostResource extends ModelResource{ // ... protected function onBoot(): void { // ... }}
Вы также можете подключить trait
к ресурсу и внутри trait
добавить метод согласно конвенции наименований - boot{TraitName}
и через трейт обратиться к onBoot()
ресурса.
Assets
use MoonShine\AssetManager\Css;use MoonShine\AssetManager\Js; protected function onLoad(): void{ $this->getAssetManager() ->add(Css::make('/css/app.css')) ->append(Js::make('/js/app.js'));}
Response модификаторы
Если ресурс в режиме async
, то вы можете модифицировать ответ:
public function modifyDestroyResponse(MoonShineJsonResponse $response): MoonShineJsonResponse{ return $response;} public function modifyMassDeleteResponse(MoonShineJsonResponse $response): MoonShineJsonResponse{ return $response;} public function modifySaveResponse(MoonShineJsonResponse $response): MoonShineJsonResponse{ return $response;}