Основы
Основой MoonShine являются пакеты Laravel. Если вы новичок в разработке пакетов Laravel, вот несколько ресурсов, которые помогут вам понять основные концепции:
- Глава Разработка пакетов в документации Laravel служит отличным справочным руководством,
- Курс по разработке пакетов от CutCode,
- Бесплатное руководство по разработке пакетов от CutCode.
ServiceProvider
Через ServiceProvider
вашего пакета вы можете автоматически добавлять ресурсы, страницы, создавать меню и правила авторизации, и многое другое.
namespace Author\MoonShineMyPackage; use Illuminate\Support\ServiceProvider;use MoonShine\Contracts\Core\DependencyInjection\CoreContract;use MoonShine\Laravel\DependencyInjection\MoonShine; class MyPackageServiceProvider extends ServiceProvider{ /** @param MoonShine $core */ public function boot(CoreContract $core): void { $core ->resources([ MyPackageResource::class ]) ->page([ MyPackagePage::class ]); }}
Также вы можете взаимодействовать с MenuManager
.
namespace Author\MoonShineMyPackage; use Illuminate\Support\ServiceProvider;use MoonShine\Contracts\Core\DependencyInjection\CoreContract;use MoonShine\Contracts\MenuManager\MenuManagerContract;use MoonShine\Laravel\DependencyInjection\MoonShine; class MyPackageServiceProvider extends ServiceProvider{ /** @param MoonShine $core */ public function boot( CoreContract $core, MenuManagerContract $menu ): void { $menu->add([ MenuItem::make('MyPackagePage', MyPackagePage::class) ]); }}
Также вы можете взаимодействовать с AssetManager
или ColorManager
.
use MoonShine\Contracts\AssetManager\AssetManagerContract; // ... public function boot( CoreContract $core, AssetManagerContract $assets): void{ $assets->add([ InlineCss::make('body {background: red;}') ]);}
use MoonShine\Contracts\ColorManager\ColorManagerContract; // ... public function boot( CoreContract $core, ColorManagerContract $colors): void{ $colors ->background('#A3C3D9') ->content('#A3C3D9') ->tableRow('#AE76A6') ->dividers('#AE76A6') ->borders('#AE76A6') ->buttons('#AE76A6') ->primary('#CCD6EB') ->secondary('#AE76A6');}
Если вам нужно добавить дополнительную логику авторизации в приложение или во внешний пакет, используйте метод authorizationRules()
.
use MoonShine\Contracts\Core\DependencyInjection\ConfiguratorContract;use MoonShine\Laravel\DependencyInjection\MoonShineConfigurator; // ... /** * @param MoonShineConfigurator $configurator */public function boot(ConfiguratorContract $configurator): void{ $configurator->authorizationRules( static function (ResourceContract $resource, Model $user, Ability $ability): bool { return true; } );}
Вы также можете прямо из ServiceProvider
добавлять компоненты на страницы.
public function boot(): void{ ProfilePage::pushComponent( fn() => MyPackageComponent::make() );}
Не забудьте автоматически подключить ваш ServiceProvider
в composer.json
.
"extra": { "laravel": { "providers": [ "Author\\MoonShineMyPackage\\MyPackageServiceProvider" ] }}
Traits
Вы также можете включать в свой пакет трейты для ресурсов или страниц и изменять логику с помощью load{TraitName}()
/boot{TraitName}()
магических методов.
trait HasMyPackageTrait{ public function loadHasMyPackageTrait(): void { $this->getFormPage()->addAssets([ Js::make('vendor/my-package/js/app.js'), Css::make('vendor/my-package/css/app.css'), ]); } public function modifyFormComponent(ComponentContract $component): ComponentContract { return parent::modifyFormComponent($component)->fields([ Modal::make( 'This is my package modal.', '' ), ...$component->getFields()->toArray(), ]); }}
Пример пользовательского поля
Давайте быстро рассмотрим создание собственного поля! Это будет визуальный редактор на основе плагина Quill.js.
Создадим поле с помощью команды moonshine:field
и выберем, что оно расширяет Textarea
.
php artisan moonshine:field Quill
Удалим ненужные методы и добавим css/js.
namespace App\MoonShine\Fields; use MoonShine\AssetManager\Css;use MoonShine\AssetManager\Js;use MoonShine\UI\Fields\Textarea; final class Quill extends Textarea{ protected string $view = 'moonshine-quill::fields.quill'; public function assets(): array { return [ Css::make('/css/moonshine/quill/quill.snow.css'), Js::make('/js/moonshine/quill/quill.js'), Js::make('/js/moonshine/quill/quill-init.js'), ]; }}
Также изменим представление поля:
<div x-data="quill"> <div class="ql-editor" :id="$id('quill')" style="height: auto;">{!! $value ?? '' !!}</div> <x-moonshine::form.textarea :attributes="$attributes->merge([ 'class' => 'ql-textarea', 'style' => 'display: none;' ])->except('x-bind:id')" >{!! $value ?? '' !!}</x-moonshine::form.textarea></div>
Мы взяли quill.snow.css
и quill.js
из библиотеки, а инициализация JS с использованием Alpine.js представлена ниже.
document.addEventListener('alpine:init', () => { Alpine.data('quill', () => ({ textarea: null, editor: null, init() { this.textarea = this.$root.querySelector('.ql-textarea') this.editor = this.$root.querySelector('.ql-editor') const t = this this.$nextTick(function() { let quill = new Quill(`#${t.editor.id}`, { theme: 'snow' }); quill.on('text-change', () => { t.textarea.value = t.editor.innerHTML || ''; t.textarea.dispatchEvent(new Event('change')); }); }) }, }))})
Пример кода этого поля можно найти в репозитории.