CrudResource
is a fundamental part of "MoonShine for Laravel".
It is important to understand that the core of MoonShine does not depend on Laravel and even more so on Eloquent models.
However, in the implementation for Laravel, we provide a ready-made ModelResource
for working with models and corresponding type-casts
.
MoonShine is very flexible, and you can create your own resource to work with any data sources.
CrudResource
provides a basic structure for working with data without being tied to a specific implementation.
This allows:
- working with any data sources (databases, API, files, etc.),
- creating your own implementations for specific tasks,
- using a single interface regardless of the data source.
To create a custom resource, it is enough to extend CrudResource
and implement the abstract methods.
namespace App\MoonShine\Resources;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Laravel\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function findItem(bool $orFail = false): mixed
{
}
public function getItems(): mixed
{
}
public function massDelete(array $ids): void
{
}
public function delete(mixed $item, ?FieldsContract $fields = null): bool
{
}
public function save(mixed $item, ?FieldsContract $fields = null): mixed
{
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Laravel\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function findItem(bool $orFail = false): mixed
{
// ...
}
public function getItems(): mixed
{
// ...
}
public function massDelete(array $ids): void
{
// ...
}
public function delete(mixed $item, ?FieldsContract $fields = null): bool
{
// ...
}
public function save(mixed $item, ?FieldsContract $fields = null): mixed
{
// ...
}
}
namespace App\MoonShine\Resources;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Laravel\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function findItem(bool $orFail = false): mixed
{
// ...
}
public function getItems(): mixed
{
// ...
}
public function massDelete(array $ids): void
{
// ...
}
public function delete(mixed $item, ?FieldsContract $fields = null): bool
{
// ...
}
public function save(mixed $item, ?FieldsContract $fields = null): mixed
{
// ...
}
}
namespaces
namespace App\MoonShine\Resources;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Laravel\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function findItem(bool $orFail = false): mixed
{
// ...
}
public function getItems(): mixed
{
// ...
}
public function massDelete(array $ids): void
{
// ...
}
public function delete(mixed $item, ?FieldsContract $fields = null): bool
{
// ...
}
public function save(mixed $item, ?FieldsContract $fields = null): mixed
{
// ...
}
}
namespace App\MoonShine\Resources;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Laravel\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function findItem(bool $orFail = false): mixed
{
// ...
}
public function getItems(): mixed
{
// ...
}
public function massDelete(array $ids): void
{
// ...
}
public function delete(mixed $item, ?FieldsContract $fields = null): bool
{
// ...
}
public function save(mixed $item, ?FieldsContract $fields = null): mixed
{
// ...
}
}
Here is an example of implementing a resource for working with a REST API
:
namespace App\MoonShine\Resources;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Laravel\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function getItems(): iterable
{
yield from Http::get('https://jsonplaceholder.typicode.com/todos')->json();
}
public function findItem(bool $orFail = false): array
{
yield from 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(['id' => $id]);
}
$this->afterMassDeleted($ids);
}
public function delete(mixed $item, ?FieldsContract $fields = null): bool
{
return Http::delete('https://jsonplaceholder.typicode.com/todos/' . $item['id'])->successful();
}
public function save(mixed $item, ?FieldsContract $fields = null): mixed
{
$data = request()->all();
if ($item['id'] ?? false) {
return Http::put('https://jsonplaceholder.typicode.com/todos/' . $item['id'], $data)->json();
}
$this->isRecentlyCreated = true;
return Http::post('https://jsonplaceholder.typicode.com/todos', $data)->json();
}
}
namespaces
namespace App\MoonShine\Resources;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Laravel\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function getItems(): iterable
{
yield from Http::get('https://jsonplaceholder.typicode.com/todos')->json();
}
public function findItem(bool $orFail = false): array
{
yield from 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(['id' => $id]);
}
$this->afterMassDeleted($ids);
}
public function delete(mixed $item, ?FieldsContract $fields = null): bool
{
return Http::delete('https://jsonplaceholder.typicode.com/todos/' . $item['id'])->successful();
}
public function save(mixed $item, ?FieldsContract $fields = null): mixed
{
$data = request()->all();
if ($item['id'] ?? false) {
return Http::put('https://jsonplaceholder.typicode.com/todos/' . $item['id'], $data)->json();
}
$this->isRecentlyCreated = true;
return Http::post('https://jsonplaceholder.typicode.com/todos', $data)->json();
}
}
namespace App\MoonShine\Resources;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Laravel\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function getItems(): iterable
{
yield from Http::get('https://jsonplaceholder.typicode.com/todos')->json();
}
public function findItem(bool $orFail = false): array
{
yield from 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(['id' => $id]);
}
$this->afterMassDeleted($ids);
}
public function delete(mixed $item, ?FieldsContract $fields = null): bool
{
return Http::delete('https://jsonplaceholder.typicode.com/todos/' . $item['id'])->successful();
}
public function save(mixed $item, ?FieldsContract $fields = null): mixed
{
$data = request()->all();
if ($item['id'] ?? false) {
return Http::put('https://jsonplaceholder.typicode.com/todos/' . $item['id'], $data)->json();
}
$this->isRecentlyCreated = true;
return Http::post('https://jsonplaceholder.typicode.com/todos', $data)->json();
}
}
namespaces
namespace App\MoonShine\Resources;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Laravel\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function getItems(): iterable
{
yield from Http::get('https://jsonplaceholder.typicode.com/todos')->json();
}
public function findItem(bool $orFail = false): array
{
yield from 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(['id' => $id]);
}
$this->afterMassDeleted($ids);
}
public function delete(mixed $item, ?FieldsContract $fields = null): bool
{
return Http::delete('https://jsonplaceholder.typicode.com/todos/' . $item['id'])->successful();
}
public function save(mixed $item, ?FieldsContract $fields = null): mixed
{
$data = request()->all();
if ($item['id'] ?? false) {
return Http::put('https://jsonplaceholder.typicode.com/todos/' . $item['id'], $data)->json();
}
$this->isRecentlyCreated = true;
return Http::post('https://jsonplaceholder.typicode.com/todos', $data)->json();
}
}
namespace App\MoonShine\Resources;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Http;
use MoonShine\Contracts\Core\DependencyInjection\FieldsContract;
use MoonShine\Laravel\Resources\CrudResource;
final class RestCrudResource extends CrudResource
{
public function getItems(): iterable
{
yield from Http::get('https://jsonplaceholder.typicode.com/todos')->json();
}
public function findItem(bool $orFail = false): array
{
yield from 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(['id' => $id]);
}
$this->afterMassDeleted($ids);
}
public function delete(mixed $item, ?FieldsContract $fields = null): bool
{
return Http::delete('https://jsonplaceholder.typicode.com/todos/' . $item['id'])->successful();
}
public function save(mixed $item, ?FieldsContract $fields = null): mixed
{
$data = request()->all();
if ($item['id'] ?? false) {
return Http::put('https://jsonplaceholder.typicode.com/todos/' . $item['id'], $data)->json();
}
$this->isRecentlyCreated = true;
return Http::post('https://jsonplaceholder.typicode.com/todos', $data)->json();
}
}
If you require complete control over the resource, instead of inheriting from CrudResource
, you can implement the interface CrudResourceContract
.
This will give you maximum flexibility in implementing all necessary methods.