ModelResource

Импорт / Экспорт

Основы

Чтобы пользоваться импортом и экспортом в ресурсах MoonShine, необходимо установить зависимость через composer.

composer require moonshine/import-export

Далее, в ресурсе добавьте трейт ImportExportConcern и реализуйте интерфейс HasImportExportContract.

 namespaces
namespace App\MoonShine\Resources;
 
use MoonShine\ImportExport\Contracts\HasImportExportContract;
use MoonShine\ImportExport\Traits\ImportExportConcern;
use MoonShine\Laravel\Resources\ModelResource;
 
class CategoryResource extends ModelResource implements HasImportExportContract
{
use ImportExportConcern;
 
// ...
}

Все готово! Далее просто объявляйте поля.

Импорт

Поля

Для импорта необходимо в ресурсе объявить поля, которые будут участвовать в импорте.

 namespaces
namespace App\MoonShine\Resources;
 
use MoonShine\ImportExport\Contracts\HasImportExportContract;
use MoonShine\ImportExport\Traits\ImportExportConcern;
use MoonShine\Laravel\Resources\ModelResource;
use MoonShine\UI\Fields\ID;
use MoonShine\UI\Fields\Text;
 
class CategoryResource extends ModelResource implements HasImportExportContract
{
use ImportExportConcern;
 
// ...
 
protected function importFields(): iterable
{
return [
ID::make(),
Text::make('Name'),
];
}
}

Обязательно добавляйте в импорт ID, иначе записи будут только добавляться, без обновления существующих.

Если вам необходимо модифицировать значение при импорте, необходимо воспользоваться методом поля fromRaw().

 namespaces
namespace App\MoonShine\Resources;
 
use App\Enums\StatusEnum;
use MoonShine\ImportExport\Contracts\HasImportExportContract;
use MoonShine\ImportExport\Traits\ImportExportConcern;
use MoonShine\Laravel\Resources\ModelResource;
use MoonShine\UI\Fields\Enum;
use MoonShine\UI\Fields\ID;
 
class CategoryResource extends ModelResource implements HasImportExportContract
{
use ImportExportConcern;
 
// ...
 
protected function importFields(): iterable
{
return [
ID::make(),
Enum::make('Status')
->attach(StatusEnum::class)
->fromRaw(static fn(string $raw, Enum $ctx) => StatusEnum::tryFrom($raw)),
];
}
}

Настройка

Для настройки импорта доступны опциональные методы. Чтобы ими воспользоваться необходимо добавить метод import(), который возвращает ImportHandler.

 namespaces
namespace App\MoonShine\Resources;
 
use MoonShine\ImportExport\Contracts\HasImportExportContract;
use MoonShine\ImportExport\ImportHandler;
use MoonShine\ImportExport\Traits\ImportExportConcern;
use MoonShine\Laravel\Handlers\Handler;
use MoonShine\Laravel\Resources\ModelResource;
use MoonShine\UI\Components\ActionButton;
 
class CategoryResource extends ModelResource implements HasImportExportContract
{
use ImportExportConcern;
 
// ...
 
protected function import(): ?Handler
{
return ImportHandler::make(__('moonshine::ui.import'))
// Указать id пользователей, которые получат уведомление об окончании операции
->notifyUsers(fn(ImportHandler $ctx) => [auth()->id()])
// Выбор диска
->disk('public')
// Выбор директории для сохранения файла импорта
->dir('/imports')
// Удалять файл после импорта
->deleteAfter()
// Разделитель для csv
->delimiter(',')
// Модификация кнопки
->modifyButton(fn(ActionButton $btn) => $btn->class('my-class'))
;
}
}

Если метод import() вернет NULL, то кнопка импорта не будет отображаться на индексной странице.

События

Для изменения логики работы импорта можно воспользоваться событиями ресурса модели.

public function beforeImportFilling(array $data): array
{
return $data;
}
 
public function beforeImported(mixed $item): mixed
{
return $item;
}
 
public function afterImported(mixed $item): mixed
{
return $item;
}

Экспорт

В админ-панели MoonShine можно реализовать экспорт всех данных с учетом текущей фильтрации и сортировки.

По умолчанию данные экспортируются в формате xlsx, но существует возможность изменить формат на csv через метод csv() класса ExportHandler.

Поля

Для экспорта необходимо в ресурсе объявить поля, которые будут участвовать в экспорте.

 namespaces
namespace App\MoonShine\Resources;
 
use MoonShine\ImportExport\Contracts\HasImportExportContract;
use MoonShine\ImportExport\Traits\ImportExportConcern;
use MoonShine\Laravel\Resources\ModelResource;
use MoonShine\UI\Fields\ID;
use MoonShine\UI\Fields\Text;
 
class CategoryResource extends ModelResource implements HasImportExportContract
{
use ImportExportConcern;
 
// ...
 
protected function exportFields(): iterable
{
return [
ID::make(),
Text::make('Name'),
];
}
}

Если вам необходимо модифицировать значение при экспорте, необходимо воспользоваться методом поля modifyRawValue().

 namespaces
namespace App\MoonShine\Resources;
 
use App\Enums\StatusEnum;
use MoonShine\ImportExport\Contracts\HasImportExportContract;
use MoonShine\ImportExport\Traits\ImportExportConcern;
use MoonShine\Laravel\Resources\ModelResource;
use MoonShine\UI\Fields\Enum;
use MoonShine\UI\Fields\ID;
 
class CategoryResource extends ModelResource implements HasImportExportContract
{
use ImportExportConcern;
 
// ...
 
protected function exportFields(): iterable
{
return [
ID::make(),
Enum::make('Status')
->attach(StatusEnum::class)
->modifyRawValue(static fn(StatusEnum $raw, Enum $ctx) => $raw->value),
];
}
}

Настройка

Для настройки экспорта доступны опциональные методы. Чтобы ими воспользоваться необходимо добавить метод export(), который возвращает ExportHandler.

 namespaces
namespace App\MoonShine\Resources;
 
use MoonShine\ImportExport\Contracts\HasImportExportContract;
use MoonShine\ImportExport\ExportHandler;
use MoonShine\ImportExport\Traits\ImportExportConcern;
use MoonShine\Laravel\Handlers\Handler;
use MoonShine\Laravel\Resources\ModelResource;
use MoonShine\UI\Components\ActionButton;
 
class CategoryResource extends ModelResource implements HasImportExportContract
{
use ImportExportConcern;
 
// ...
 
protected function export(): ?Handler
{
return ExportHandler::make(__('moonshine::ui.export'))
// Указать id пользователей, которые получат уведомление об окончании операции
->notifyUsers(fn() => [auth()->id()])
// Выбор диска
->disk('public')
// Наименование файла
->filename(sprintf('export_%s', date('Ymd-His')))
// Выбор директории сохранения файла экспорта
->dir('/exports')
// Если необходимо экспортировать в формате csv
->csv()
// Разделитель для csv
->delimiter(',')
// Экспорт с подтверждением
->withConfirm()
// Модификация кнопки
->modifyButton(fn(ActionButton $btn) => $btn->class('my-class'))
;
}
}

Если метод export() вернет NULL, то кнопка экспорта не будет отображаться на индексной странице.

Общие методы

ImportHandler и ExportHandler расширяют базовый класс Handler который реализует дополнительные методы.

icon

Иконка для кнопки:

icon(string $icon)

queue

Запускать процессы в фоне:

queue()

modifyButton

Модификация кнопки:

 namespaces
use MoonShine\UI\Components\ActionButton;
 
modifyButton(
fn(ActionButton $btn) => $btn->class('my-class')
)

notifyUsers

Выбор пользователей для уведомления:

notifyUsers(
fn() => [auth()->id()]
)

when

Методы по условию:

when(
$value = null,
callable $callback = null,
callable $default = null,
)
  • $value - условие,
  • $callback - callback функция, которая будет выполнена, если условие имеет значение TRUE,
  • $default - callback функция, которая будет выполнена, если условие имеет значение FALSE.
 namespaces
namespace App\MoonShine\Resources;
 
use MoonShine\ImportExport\Contracts\HasImportExportContract;
use MoonShine\ImportExport\ImportHandler;
use MoonShine\ImportExport\Traits\ImportExportConcern;
use MoonShine\Laravel\Handlers\Handler;
use MoonShine\Laravel\Resources\ModelResource;
 
class CategoryResource extends ModelResource implements HasImportExportContract
{
use ImportExportConcern;
 
// ...
 
protected function import(): ?Handler
{
return ImportHandler::make('Import')
->when(
true,
fn($handler) => $handler->delimiter(','),
fn($handler) => $handler->delimiter(';')
);
}
}

unless

Методы по условию:

unless(
$value = null,
callable $callback = null,
callable $default = null,
)
  • $value - условие,
  • $callback - callback функция, которая будет выполнена, если условие имеет значение FALSE,
  • $default - callback функция, которая будет выполнена, если условие имеет значение TRUE.

Метод unless() является обратным методу when().

Кастомная реализация

Может возникнуть ситуация, когда вы захотите изменить реализацию импорта или экспорта. Для этого необходимо реализовать свой класс расширяющий ImportHandler или ExportHandler.

Класс можно сгенерировать, воспользовавшись консольной командой:

php artisan moonshine:handler

После выполнения команды будет создан базовый класс Handler в директории app/MoonShine/Handlers.

Не забудьте заменить наследование с Handler на ImportHandler или ExportHandler.