По умолчанию в MoonShine поля работают с примитивными типами и ничего не знают о моделях. Это было сделано для того, чтобы система не была привязана только к моделям, и поля могли, в зависимости от ситуации, иметь доступ как к необработанным данным, так и к типизированным данным.
TypeCast
для моделей уже включен в MoonShine, но если вам нужно работать с другим типом данных, вам понадобится объект, реализующий интерфейс MoonShine\Contracts\Core\TypeCasts\DataCasterContract
.
interface DataCasterContract{ public function cast(mixed $data): DataWrapperContract; public function paginatorCast(mixed $data): ?PaginatorContract;}
Также необходимо реализовать интерфейс DataWrapperContract
.
Данная абстракция помогает определить что именно является ключом объекта и как его привести к массиву.
interface DataWrapperContract{ public function getOriginal(): mixed; public function getKey(): int|string|null; public function toArray(): array;}
Давайте рассмотрим пример TypeCast
для моделей.
final readonly class ModelCaster implements DataCasterContract{ public function __construct( /** @var class-string<T> $class */ private string $class ) { } /** @return class-string<T> $class */ public function getClass(): string { return $this->class; } /** * @return ModelDataWrapper<T> */ public function cast(mixed $data): ModelDataWrapper { $model = new ($this->getClass()); return new ModelDataWrapper($model->fill($data)); } public function paginatorCast(mixed $data): ?PaginatorContract { if (! $data instanceof Paginator && ! $data instanceof CursorPaginator) { return null; } $paginator = new PaginatorCaster( $data->appends( moonshine()->getRequest()->getExcept('page') )->toArray(), $data->items() ); return $paginator->cast(); }}
ModelDataWrapper
реализует DataWrapperContract
и за счет методов модели getKey
и toArray
помогает определить ключ и трансформировать объект в массив.
final readonly class ModelDataWrapper implements DataWrapperContract{ public function __construct(private Model $model) { } public function getOriginal(): Model { return $this->model; } public function getKey(): int|string|null { return $this->model->getKey(); } public function toArray(): array { return $this->model->toArray(); }}
Теперь рассмотрим его применение в FormBuilder
/TableBuilder
.
TableBuilder::make(items: User::paginate()) ->fields([ Text::make('Email'), ]) ->cast(new ModelCaster(User::class))
FormBuilder::make() ->fields([ Text::make('Email'), ]) ->fillCast(User::query()->first(), new ModelCaster(User::class))