CrudResource является фундаментальной частью "MoonShine для Laravel".
Важно понимать, что ядро MoonShine не зависит от Laravel и тем более от моделей Eloquent.
Но в реализации для Laravel мы предоставляем готовый ModelResource для работы с моделями и соответствующие type-casts.
MoonShine очень гибкий и вы можете создать собственный ресурс для работы с любыми источниками данных.
CrudResource предоставляет базовую структуру для работы с данными, не привязываясь к конкретной реализации.
Это позволяет:
- работать с любыми источниками данных (базы данных, API, файлы и т.д.),
- создавать собственные реализации для специфических задач,
- использовать единый интерфейс независимо от источника данных.
Для создания собственного ресурса достаточно расширить CrudResource и реализовать абстрактные методы.
namespace App\MoonShine\Resources;
use Illuminate\Contracts\Pagination\CursorPaginator;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Support\Collection;
use Illuminate\Support\LazyCollection;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Crud\Resources\CrudResource;
use MoonShine\Contracts\Core\TypeCasts\DataWrapperContract;
final class RestCrudResource extends CrudResource
{
public function findItem(bool $orFail = false): ?DataWrapperContract
{
}
public function getItems(): iterable|Collection|LazyCollection|CursorPaginator|Paginator;
{
}
public function massDelete(array $ids): void
{
}
public function delete(DataWrapperContract $item, ?FieldsContract $fields = null): bool
{
}
public function save(DataWrapperContract $item, ?FieldsContract $fields = null): DataWrapperContract
{
}
}
namespaces
namespace App\MoonShine\Resources;
use Illuminate\Contracts\Pagination\CursorPaginator;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Support\Collection;
use Illuminate\Support\LazyCollection;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Crud\Resources\CrudResource;
use MoonShine\Contracts\Core\TypeCasts\DataWrapperContract;
final class RestCrudResource extends CrudResource
{
public function findItem(bool $orFail = false): ?DataWrapperContract
{
// ...
}
public function getItems(): iterable|Collection|LazyCollection|CursorPaginator|Paginator;
{
// ...
}
public function massDelete(array $ids): void
{
// ...
}
public function delete(DataWrapperContract $item, ?FieldsContract $fields = null): bool
{
// ...
}
public function save(DataWrapperContract $item, ?FieldsContract $fields = null): DataWrapperContract
{
// ...
}
}
namespace App\MoonShine\Resources;
use Illuminate\Contracts\Pagination\CursorPaginator;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Support\Collection;
use Illuminate\Support\LazyCollection;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Crud\Resources\CrudResource;
use MoonShine\Contracts\Core\TypeCasts\DataWrapperContract;
final class RestCrudResource extends CrudResource
{
public function findItem(bool $orFail = false): ?DataWrapperContract
{
// ...
}
public function getItems(): iterable|Collection|LazyCollection|CursorPaginator|Paginator;
{
// ...
}
public function massDelete(array $ids): void
{
// ...
}
public function delete(DataWrapperContract $item, ?FieldsContract $fields = null): bool
{
// ...
}
public function save(DataWrapperContract $item, ?FieldsContract $fields = null): DataWrapperContract
{
// ...
}
}
namespaces
namespace App\MoonShine\Resources;
use Illuminate\Contracts\Pagination\CursorPaginator;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Support\Collection;
use Illuminate\Support\LazyCollection;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Crud\Resources\CrudResource;
use MoonShine\Contracts\Core\TypeCasts\DataWrapperContract;
final class RestCrudResource extends CrudResource
{
public function findItem(bool $orFail = false): ?DataWrapperContract
{
// ...
}
public function getItems(): iterable|Collection|LazyCollection|CursorPaginator|Paginator;
{
// ...
}
public function massDelete(array $ids): void
{
// ...
}
public function delete(DataWrapperContract $item, ?FieldsContract $fields = null): bool
{
// ...
}
public function save(DataWrapperContract $item, ?FieldsContract $fields = null): DataWrapperContract
{
// ...
}
}
namespace App\MoonShine\Resources;
use Illuminate\Contracts\Pagination\CursorPaginator;
use Illuminate\Contracts\Pagination\Paginator;
use Illuminate\Support\Collection;
use Illuminate\Support\LazyCollection;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Crud\Resources\CrudResource;
use MoonShine\Contracts\Core\TypeCasts\DataWrapperContract;
final class RestCrudResource extends CrudResource
{
public function findItem(bool $orFail = false): ?DataWrapperContract
{
// ...
}
public function getItems(): iterable|Collection|LazyCollection|CursorPaginator|Paginator;
{
// ...
}
public function massDelete(array $ids): void
{
// ...
}
public function delete(DataWrapperContract $item, ?FieldsContract $fields = null): bool
{
// ...
}
public function save(DataWrapperContract $item, ?FieldsContract $fields = null): DataWrapperContract
{
// ...
}
}
Вот пример реализации ресурса для работы с REST API:
namespace App\MoonShine\Resources;
use Illuminate\Support\Facades\Http;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Contracts\Core\TypeCasts\DataWrapperContract;
use MoonShine\Crud\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function getItems(): iterable
{
yield from collect(Http::get('https://jsonplaceholder.typicode.com/todos')->json())
->map(fn ($item): DataWrapperContract => $this->getCaster()->cast($item))
->toArray();
}
public function findItem(bool $orFail = false): ?DataWrapperContract
{
return $this->getCaster()->cast(
Http::get('https://jsonplaceholder.typicode.com/todos/' . $this->getItemID())->json()
);
}
public function massDelete(array $ids): void
{
$this->beforeMassDeleting($ids);
foreach ($ids as $id) {
$this->delete($this->getCaster()->cast(['id' => $id]));
}
$this->afterMassDeleted($ids);
}
public function delete(DataWrapperContract $item, ?FieldsContract $fields = null): bool
{
return Http::delete('https://jsonplaceholder.typicode.com/todos/' . $item->getOriginal()['id'])->successful();
}
public function save(DataWrapperContract $item, ?FieldsContract $fields = null): DataWrapperContract
{
$originalItem = $item->getOriginal();
$data = request()->all();
if ($originalItem['id'] ?? false) {
return Http::put('https://jsonplaceholder.typicode.com/todos/' . $originalItem['id'], $data)->json();
}
$this->isRecentlyCreated = true;
return $this->getCaster()->cast(Http::post('https://jsonplaceholder.typicode.com/todos', $originalItem)->json());
}
}
namespaces
namespace App\MoonShine\Resources;
use Illuminate\Support\Facades\Http;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Contracts\Core\TypeCasts\DataWrapperContract;
use MoonShine\Crud\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function getItems(): iterable
{
yield from collect(Http::get('https://jsonplaceholder.typicode.com/todos')->json())
->map(fn ($item): DataWrapperContract => $this->getCaster()->cast($item))
->toArray();
}
public function findItem(bool $orFail = false): ?DataWrapperContract
{
return $this->getCaster()->cast(
Http::get('https://jsonplaceholder.typicode.com/todos/' . $this->getItemID())->json()
);
}
public function massDelete(array $ids): void
{
$this->beforeMassDeleting($ids);
foreach ($ids as $id) {
$this->delete($this->getCaster()->cast(['id' => $id]));
}
$this->afterMassDeleted($ids);
}
public function delete(DataWrapperContract $item, ?FieldsContract $fields = null): bool
{
return Http::delete('https://jsonplaceholder.typicode.com/todos/' . $item->getOriginal()['id'])->successful();
}
public function save(DataWrapperContract $item, ?FieldsContract $fields = null): DataWrapperContract
{
$originalItem = $item->getOriginal();
$data = request()->all();
if ($originalItem['id'] ?? false) {
return Http::put('https://jsonplaceholder.typicode.com/todos/' . $originalItem['id'], $data)->json();
}
$this->isRecentlyCreated = true;
return $this->getCaster()->cast(Http::post('https://jsonplaceholder.typicode.com/todos', $originalItem)->json());
}
}
namespace App\MoonShine\Resources;
use Illuminate\Support\Facades\Http;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Contracts\Core\TypeCasts\DataWrapperContract;
use MoonShine\Crud\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function getItems(): iterable
{
yield from collect(Http::get('https://jsonplaceholder.typicode.com/todos')->json())
->map(fn ($item): DataWrapperContract => $this->getCaster()->cast($item))
->toArray();
}
public function findItem(bool $orFail = false): ?DataWrapperContract
{
return $this->getCaster()->cast(
Http::get('https://jsonplaceholder.typicode.com/todos/' . $this->getItemID())->json()
);
}
public function massDelete(array $ids): void
{
$this->beforeMassDeleting($ids);
foreach ($ids as $id) {
$this->delete($this->getCaster()->cast(['id' => $id]));
}
$this->afterMassDeleted($ids);
}
public function delete(DataWrapperContract $item, ?FieldsContract $fields = null): bool
{
return Http::delete('https://jsonplaceholder.typicode.com/todos/' . $item->getOriginal()['id'])->successful();
}
public function save(DataWrapperContract $item, ?FieldsContract $fields = null): DataWrapperContract
{
$originalItem = $item->getOriginal();
$data = request()->all();
if ($originalItem['id'] ?? false) {
return Http::put('https://jsonplaceholder.typicode.com/todos/' . $originalItem['id'], $data)->json();
}
$this->isRecentlyCreated = true;
return $this->getCaster()->cast(Http::post('https://jsonplaceholder.typicode.com/todos', $originalItem)->json());
}
}
namespaces
namespace App\MoonShine\Resources;
use Illuminate\Support\Facades\Http;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Contracts\Core\TypeCasts\DataWrapperContract;
use MoonShine\Crud\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function getItems(): iterable
{
yield from collect(Http::get('https://jsonplaceholder.typicode.com/todos')->json())
->map(fn ($item): DataWrapperContract => $this->getCaster()->cast($item))
->toArray();
}
public function findItem(bool $orFail = false): ?DataWrapperContract
{
return $this->getCaster()->cast(
Http::get('https://jsonplaceholder.typicode.com/todos/' . $this->getItemID())->json()
);
}
public function massDelete(array $ids): void
{
$this->beforeMassDeleting($ids);
foreach ($ids as $id) {
$this->delete($this->getCaster()->cast(['id' => $id]));
}
$this->afterMassDeleted($ids);
}
public function delete(DataWrapperContract $item, ?FieldsContract $fields = null): bool
{
return Http::delete('https://jsonplaceholder.typicode.com/todos/' . $item->getOriginal()['id'])->successful();
}
public function save(DataWrapperContract $item, ?FieldsContract $fields = null): DataWrapperContract
{
$originalItem = $item->getOriginal();
$data = request()->all();
if ($originalItem['id'] ?? false) {
return Http::put('https://jsonplaceholder.typicode.com/todos/' . $originalItem['id'], $data)->json();
}
$this->isRecentlyCreated = true;
return $this->getCaster()->cast(Http::post('https://jsonplaceholder.typicode.com/todos', $originalItem)->json());
}
}
namespace App\MoonShine\Resources;
use Illuminate\Support\Facades\Http;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Contracts\Core\TypeCasts\DataWrapperContract;
use MoonShine\Crud\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function getItems(): iterable
{
yield from collect(Http::get('https://jsonplaceholder.typicode.com/todos')->json())
->map(fn ($item): DataWrapperContract => $this->getCaster()->cast($item))
->toArray();
}
public function findItem(bool $orFail = false): ?DataWrapperContract
{
return $this->getCaster()->cast(
Http::get('https://jsonplaceholder.typicode.com/todos/' . $this->getItemID())->json()
);
}
public function massDelete(array $ids): void
{
$this->beforeMassDeleting($ids);
foreach ($ids as $id) {
$this->delete($this->getCaster()->cast(['id' => $id]));
}
$this->afterMassDeleted($ids);
}
public function delete(DataWrapperContract $item, ?FieldsContract $fields = null): bool
{
return Http::delete('https://jsonplaceholder.typicode.com/todos/' . $item->getOriginal()['id'])->successful();
}
public function save(DataWrapperContract $item, ?FieldsContract $fields = null): DataWrapperContract
{
$originalItem = $item->getOriginal();
$data = request()->all();
if ($originalItem['id'] ?? false) {
return Http::put('https://jsonplaceholder.typicode.com/todos/' . $originalItem['id'], $data)->json();
}
$this->isRecentlyCreated = true;
return $this->getCaster()->cast(Http::post('https://jsonplaceholder.typicode.com/todos', $originalItem)->json());
}
}
Если вам требуется полный контроль над ресурсом, вместо наследования от CrudResource, вы можете реализовать интерфейс CrudResourceContract.
Это даст вам максимальную гибкость в реализации всех необходимых методов.