Basics
To use import and export in MoonShine resources, you need to install the dependency via composer.
composer require moonshine/import-exportcomposer require moonshine/import-export
Next, add the ImportExportConcern trait and implement the HasImportExportContract interface.
namespace App\MoonShine\Resources;use MoonShine\ImportExport\Contracts\HasImportExportContract;use MoonShine\ImportExport\Traits\ImportExportConcern;class CategoryResource extends ModelResource implements HasImportExportContract{use ImportExportConcern;// ...}
namespace App\MoonShine\Resources;use MoonShine\ImportExport\Contracts\HasImportExportContract;use MoonShine\ImportExport\Traits\ImportExportConcern;class CategoryResource extends ModelResource implements HasImportExportContract{use ImportExportConcern;// ...}
All set! Next, just declare the fields.
Import
Fields
To import, you need to declare the fields in the resource that will participate in the import.
use MoonShine\UI\Fields\ID;use MoonShine\UI\Fields\Text;protected function importFields(): iterable{return [ID::make(),Text::make('Name'),];}
use MoonShine\UI\Fields\ID;use MoonShine\UI\Fields\Text;protected function importFields(): iterable{return [ID::make(),Text::make('Name'),];}
Be sure to add ID to the import; otherwise, records will only be added without updating existing ones.
If you need to modify a value during import, you should use the field method fromRaw().
use App\Enums\StatusEnum;use MoonShine\UI\Fields\Enum;use MoonShine\UI\Fields\ID;protected function importFields(): iterable{return [ID::make(),Enum::make('Status')->attach(StatusEnum::class)->fromRaw(static fn(string $raw, Enum $ctx) => StatusEnum::tryFrom($raw)),];}
use App\Enums\StatusEnum;use MoonShine\UI\Fields\Enum;use MoonShine\UI\Fields\ID;protected function importFields(): iterable{return [ID::make(),Enum::make('Status')->attach(StatusEnum::class)->fromRaw(static fn(string $raw, Enum $ctx) => StatusEnum::tryFrom($raw)),];}
Import Settings
For configuring the import, optional methods are available.
To use them, you need to add the import() method that returns ImportHandler.
notifyUsers()- specify the IDs of users who will be notified when the operation is completed,disk()- select disk,dir()- select directory for saving the import file,deleteAfter()- delete the file after import,delimiter()- CSV delimiter,modifyButton()- modify button.
use MoonShine\Crud\Handlers\Handler;use MoonShine\ImportExport\ImportHandler;use MoonShine\UI\Components\ActionButton;protected function import(): ?Handler{return ImportHandler::make(__('moonshine::ui.import'))->notifyUsers(fn(ImportHandler $ctx) => [auth()->id()])->disk('public')->dir('/imports')->deleteAfter()->delimiter(',')->modifyButton(fn(ActionButton $btn) => $btn->class('my-class'));}
use MoonShine\Crud\Handlers\Handler;use MoonShine\ImportExport\ImportHandler;use MoonShine\UI\Components\ActionButton;protected function import(): ?Handler{return ImportHandler::make(__('moonshine::ui.import'))->notifyUsers(fn(ImportHandler $ctx) => [auth()->id()])->disk('public')->dir('/imports')->deleteAfter()->delimiter(',')->modifyButton(fn(ActionButton $btn) => $btn->class('my-class'));}
If the import() method returns NULL, the import button will not be displayed on the index page.
Events
To change the import logic, you can use the model resource events.
public function beforeImportFilling(array $data): array{return $data;}public function beforeImported(mixed $item): mixed{return $item;}public function afterImported(mixed $item): mixed{return $item;}public function beforeImportFilling(array $data): array{return $data;}public function beforeImported(mixed $item): mixed{return $item;}public function afterImported(mixed $item): mixed{return $item;}
Export
In the MoonShine admin panel, exporting all data considering the current filtering and sorting can be implemented.
By default, data is exported in XLSX format, but there is an option to change the format to CSV via the csv() method of the ExportHandler class.
Fields
To export, you need to declare the fields in the resource that will participate in the export.
use MoonShine\UI\Fields\ID;use MoonShine\UI\Fields\Text;protected function exportFields(): iterable{return [ID::make(),Text::make('Name'),];}
use MoonShine\UI\Fields\ID;use MoonShine\UI\Fields\Text;protected function exportFields(): iterable{return [ID::make(),Text::make('Name'),];}
If you need to modify a value during export, you should use the field method modifyRawValue().
use App\Enums\StatusEnum;use MoonShine\UI\Fields\Enum;use MoonShine\UI\Fields\ID;protected function exportFields(): iterable{return [ID::make(),Enum::make('Status')->attach(StatusEnum::class)->modifyRawValue(static fn(StatusEnum $raw, Order $data, Enum $ctx) => $raw->value),];}
use App\Enums\StatusEnum;use MoonShine\UI\Fields\Enum;use MoonShine\UI\Fields\ID;protected function exportFields(): iterable{return [ID::make(),Enum::make('Status')->attach(StatusEnum::class)->modifyRawValue(static fn(StatusEnum $raw, Order $data, Enum $ctx) => $raw->value),];}
Export Settings
For configuring the export, optional methods are available.
To use them, you need to add the export() method that returns ExportHandler.
notifyUsers()- specify the IDs of users who will be notified when the operation is completed,disk()- select disk,filename()- filename,dir()- select directory for saving the export file,csv()- export as CSV (default XLSX),delimiter()- CSV delimiter,withConfirm()- export with confirmation,modifyButton()- modify button.
use MoonShine\Crud\Handlers\Handler;use MoonShine\ImportExport\ExportHandler;use MoonShine\UI\Components\ActionButton;protected function export(): ?Handler{return ExportHandler::make(__('moonshine::ui.export'))->notifyUsers(fn() => [auth()->id()])->disk('public')->filename(sprintf('export_%s', date('Ymd-His')))->dir('/exports')->csv()->delimiter(',')->withConfirm()->modifyButton(fn(ActionButton $btn) => $btn->class('my-class'));}
use MoonShine\Crud\Handlers\Handler;use MoonShine\ImportExport\ExportHandler;use MoonShine\UI\Components\ActionButton;protected function export(): ?Handler{return ExportHandler::make(__('moonshine::ui.export'))->notifyUsers(fn() => [auth()->id()])->disk('public')->filename(sprintf('export_%s', date('Ymd-His')))->dir('/exports')->csv()->delimiter(',')->withConfirm()->modifyButton(fn(ActionButton $btn) => $btn->class('my-class'));}
If the export() method returns NULL, the export button will not be displayed on the index page.
Common methods
ImportHandler and ExportHandler extend the base class Handler, which implements additional methods.
icon
Icon for the button:
icon(string $icon)icon(string $icon)
queue
Run processes in the background:
queue()queue()
modifyButton
Modify button:
use MoonShine\UI\Components\ActionButton;modifyButton(fn(ActionButton $btn) => $btn->class('my-class'))
use MoonShine\UI\Components\ActionButton;modifyButton(fn(ActionButton $btn) => $btn->class('my-class'))
notifyUsers
Select users for notification:
notifyUsers(fn() => [auth()->id()])notifyUsers(fn() => [auth()->id()])
when
Methods by condition:
when($value = null,callable $callback = null,callable $default = null,)when($value = null,callable $callback = null,callable $default = null,)
$value- condition,$callback-callbackfunction that will be executed if the condition isTRUE,$default-callbackfunction that will be executed if the condition isFALSE.
use MoonShine\Crud\Handlers\Handler;use MoonShine\ImportExport\ImportHandler;protected function import(): ?Handler{return ImportHandler::make('Import')->when(true,fn($handler) => $handler->delimiter(','),fn($handler) => $handler->delimiter(';'));}
use MoonShine\Crud\Handlers\Handler;use MoonShine\ImportExport\ImportHandler;protected function import(): ?Handler{return ImportHandler::make('Import')->when(true,fn($handler) => $handler->delimiter(','),fn($handler) => $handler->delimiter(';'));}
unless
Methods by condition:
unless($value = null,callable $callback = null,callable $default = null,)unless($value = null,callable $callback = null,callable $default = null,)
$value- condition,$callback-callbackfunction that will be executed if the condition isFALSE,$default-callbackfunction that will be executed if the condition isTRUE.
The unless() method is the reverse of the when() method.
Custom implementation
There may be situations where you want to change the import or export implementation.
To do this, you need to implement your own class extending ImportHandler or ExportHandler.
The class can be generated using the following console command:
php artisan moonshine:handlerphp artisan moonshine:handler
After running the command, a base class Handler will be created in the app/MoonShine/Handlers directory.
Don’t forget to change the inheritance from Handler to ImportHandler or ExportHandler.