Первые шаги

Быстрый старт

Скринкасты

MoonShine — это админ-панель для Laravel, которая помогает быстро запускать MVP, внутренние кабинеты, CRM и CMS. Ниже — пошаговая инструкция по установке и первичной настройке.

1. Установка

Laravel

Убедитесь, что у вас установлен Laravel 10.48+. Подробнее в документации Laravel

composer global require laravel/installer
 
laravel new example-app
 
cd example-app
composer global require laravel/installer
 
laravel new example-app
 
cd example-app

MoonShine

composer require moonshine/moonshine
composer require moonshine/moonshine

Starter kit

Если у вас уже установлен laravel/installer, то вы можете установить Laravel + MoonShine одной командой:

laravel new example-app --using=moonshine/app
laravel new example-app --using=moonshine/app

2. Настройка

php artisan moonshine:install -Q
php artisan moonshine:install -Q

Создайте первого администратора. Введите e-mail (логин), имя и пароль — эти данные будут использоваться для входа.

make-user

3. Запуск проекта

Запустите локальный сервер:

php artisan serve
php artisan serve

Откройте в браузере: http://127.0.0.1:8000/admin

Войдите под учётной записью администратора.

4. Создание первого ресурса

Сгенерируйте ресурс для модели (например, User):

php artisan moonshine:resource User
php artisan moonshine:resource User

Готово! Теперь раздел Users доступен в админке.

http://127.0.0.1:8000/admin/resource/user-resource/index-page

Также вы найдёте его в меню.

user-resource

5. Добавление полей в ресурс

Раздел добавлен, но если открыть создание записей, то вы увидите пустую страницу без полей формы. Давайте это исправим.

Вот как выглядит новый ресурс сразу после создания:

/**
* @extends ModelResource<User>
*/
class UserResource extends ModelResource
{
protected string $model = User::class;
 
protected string $title = 'Users';
 
protected function indexFields(): iterable
{
return [
ID::make()->sortable(),
];
}
 
protected function formFields(): iterable
{
return [
Box::make([
ID::make(),
]),
];
}
 
protected function detailFields(): iterable
{
return [
ID::make(),
];
}
 
protected function rules(mixed $item): array
{
return [];
}
}
/**
* @extends ModelResource<User>
*/
class UserResource extends ModelResource
{
protected string $model = User::class;
 
protected string $title = 'Users';
 
protected function indexFields(): iterable
{
return [
ID::make()->sortable(),
];
}
 
protected function formFields(): iterable
{
return [
Box::make([
ID::make(),
]),
];
}
 
protected function detailFields(): iterable
{
return [
ID::make(),
];
}
 
protected function rules(mixed $item): array
{
return [];
}
}

Изменим заголовок раздела, добавив метод getTitle() для удобства локализации в будущем:

public function getTitle(): string
{
return __('Clients');
}
public function getTitle(): string
{
return __('Clients');
}

Также рекомендуется указать $column, чтобы изменить отображаемое поле при связях. Вместо id укажем email:

protected string $column = 'email';
protected string $column = 'email';

Теперь добавим поля формы. Используем Text, Email, Password и компоненты для лучшей структуры:

protected function formFields(): iterable
{
return [
Grid::make([
Column::make([
Box::make('Contact information', [
ID::make()->sortable(),
Text::make('Name'),
Email::make('E-mail', 'email'),
]),
 
LineBreak::make(),
 
Box::make('Change password', [
Password::make('Password')
->customAttributes(['autocomplete' => 'new-password']),
 
PasswordRepeat::make('Password repeat')
->customAttributes(['autocomplete' => 'confirm-password']),
]),
]),
]),
];
}
protected function formFields(): iterable
{
return [
Grid::make([
Column::make([
Box::make('Contact information', [
ID::make()->sortable(),
Text::make('Name'),
Email::make('E-mail', 'email'),
]),
 
LineBreak::make(),
 
Box::make('Change password', [
Password::make('Password')
->customAttributes(['autocomplete' => 'new-password']),
 
PasswordRepeat::make('Password repeat')
->customAttributes(['autocomplete' => 'confirm-password']),
]),
]),
]),
];
}

Добавим валидацию:

protected function rules(mixed $item): array
{
return [
'name' => 'required',
'email' => [
'sometimes',
'bail',
'required',
'email',
Rule::unique('users', 'email')->ignore($item->id),
],
'password' => !$item->exists
? 'required|min:6|required_with:password_repeat|same:password_repeat'
: 'sometimes|nullable|min:6|required_with:password_repeat|same:password_repeat',
];
}
protected function rules(mixed $item): array
{
return [
'name' => 'required',
'email' => [
'sometimes',
'bail',
'required',
'email',
Rule::unique('users', 'email')->ignore($item->id),
],
'password' => !$item->exists
? 'required|min:6|required_with:password_repeat|same:password_repeat'
: 'sometimes|nullable|min:6|required_with:password_repeat|same:password_repeat',
];
}

6. Фильтрация записей

Добавим фильтр по email:

protected function filters(): iterable
{
return [
Text::make('E-mail', 'email')
->onApply(fn(Builder $query, ?string $value) => $value === null ? $query : $query->whereLike('email', "%$value%")),
];
}
protected function filters(): iterable
{
return [
Text::make('E-mail', 'email')
->onApply(fn(Builder $query, ?string $value) => $value === null ? $query : $query->whereLike('email', "%$value%")),
];
}

7. Брендирование

Настроим логотип и цветовую схему в App\Providers\MoonShineServiceProvider.php:

$config
->logo('/images/logo.png')
->logo('/images/logo-mini.png', small: true);
 
$colors
->primary('#2563EB')
->secondary('#93C5FD');
$config
->logo('/images/logo.png')
->logo('/images/logo-mini.png', small: true);
 
$colors
->primary('#2563EB')
->secondary('#93C5FD');

8. Локализация

Настройка локализации в config/moonshine.php:

'locale' => 'ru',
'locales' => [
'en',
'ru'
],
'locale' => 'ru',
'locales' => [
'en',
'ru'
],

Языковые файлы должны находиться в /lang/vendor/moonshine. Их можно найти в разделе Плагины или сделать самостоятельно.

9. Документация

Мы установили MoonShine, настроили ресурс, добавили поля, фильтры, брендирование и локализацию.

Рекомендуем изучить документацию, рецепты и видео-гайды, чтобы использовать все возможности платформы.

Важные разделы:

Спасибо, что выбрали MoonShine!