Created
February 5, 2025 09:14
-
-
Save trovster/e75a7f2f1729c49bbc6cf1b01f734448 to your computer and use it in GitHub Desktop.
API Controllers and Resources for Laravel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Controllers\Subdomains\Api; | |
use App\Http\Controllers\Subdomains\Api\Controller; | |
use App\Http\Requests\Api\Blog\StoreRequest; | |
use App\Http\Requests\Api\Blog\UpdateRequest; | |
use App\Http\Resources\Blog\Post as Resource; | |
use App\Http\Resources\Blog\Posts as Collection; | |
use App\Models\Blog\Post; | |
use Illuminate\Http\JsonResponse; | |
use Illuminate\Http\Request; | |
use Knuckles\Scribe\Attributes\Endpoint; | |
use Knuckles\Scribe\Attributes\Group; | |
use Knuckles\Scribe\Attributes\ResponseFromApiResource; | |
use Knuckles\Scribe\Attributes\UrlParam; | |
#[Group('Blog')] | |
class BlogController extends Controller | |
{ | |
#[ResponseFromApiResource( | |
Collection::class, | |
Post::class, | |
collection: true, | |
paginate: 10, | |
with: ['categories'], | |
factoryStates: ['published', 'notHidden'] | |
)] | |
#[Endpoint('List All Blog Posts', <<<DESC | |
This endpoint allows you to list all blog posts. | |
Each entry contains basic post information, such as title, date, summary, | |
word count and an array of categories. | |
<aside>The results are paginated.</aside> | |
DESC)] | |
public function index(Request $request): Collection | |
{ | |
return Collection::make( | |
Post::query()->withOnly('categories')->paginate( | |
$request->integer('per_page', 10) | |
) | |
)->preserveQuery(); | |
} | |
public function store(StoreRequest $request): JsonResponse | |
{ | |
$blog = Post::query()->create( | |
$request->validated() | |
); | |
return new JsonResponse([ | |
'status' => JsonResponse::HTTP_CREATED, | |
'message' => 'Created', | |
'data' => Resource::make($blog), | |
], JsonResponse::HTTP_CREATED); | |
} | |
#[ResponseFromApiResource( | |
Resource::class, | |
Post::class, | |
with: ['categories'], | |
factoryStates: ['published', 'notHidden'] | |
)] | |
#[UrlParam('ID', 'int', 'The ID of the blog post.', example: 1)] | |
#[Endpoint('Get a Blog Post', <<<DESC | |
This endpoint allows you to get a specific blog post, based on the ID. | |
The entry contains the full blog post information, including the full html. | |
The category array contains objects of category ID and name. | |
DESC)] | |
public function show(Post $blog): Resource | |
{ | |
return Resource::make( | |
$blog->loadMissing('categories') | |
); | |
} | |
#[UrlParam('ID', 'int', 'The ID of the blog post.', example: 1)] | |
public function update(UpdateRequest $request, Post $blog): JsonResponse | |
{ | |
$blog->update( | |
$request->validated() | |
); | |
return new JsonResponse([ | |
'status' => JsonResponse::HTTP_OK, | |
'message' => 'Updated', | |
'data' => Resource::make($blog), | |
], JsonResponse::HTTP_OK); | |
} | |
#[UrlParam('ID', 'int', 'The ID of the blog post.', example: 1)] | |
public function destroy(Post $blog): JsonResponse | |
{ | |
$blog->delete(); | |
return new JsonResponse([ | |
'status' => JsonResponse::HTTP_OK, | |
'message' => 'Deleted', | |
], JsonResponse::HTTP_OK); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Resources\Blog; | |
use App\Http\Resources\Blog\Category; | |
use Illuminate\Contracts\Support\Arrayable; | |
use Illuminate\Http\Request; | |
use Illuminate\Http\Resources\Json\AnonymousResourceCollection; | |
use Illuminate\Http\Resources\Json\JsonResource; | |
use Illuminate\Support\Collection; | |
use JsonSerializable; | |
/** @mixin \App\Models\Blog\Post */ | |
class Post extends JsonResource | |
{ | |
public function toArray(Request $request): Arrayable|JsonSerializable|array | |
{ | |
return array_merge( | |
[ | |
'id' => $this->resource->getKey(), | |
'title' => $this->Title->squish(), | |
'date' => $this->Published->format('c'), | |
'summary' => $this->Summary, | |
'wordCount' => $this->description->wordCount(), | |
], | |
$this->details($request), | |
$this->categories($request), | |
$this->links($request) | |
); | |
} | |
public function details(Request $request): array | |
{ | |
return [ | |
$this->mergeWhen(! $request->boolean('collection'), [ | |
'html' => $this->html, | |
]), | |
]; | |
} | |
public function categories(Request $request): array | |
{ | |
return [ | |
$this->mergeWhen($request->boolean('collection'), [ | |
'categories' => $this->whenLoaded( | |
'categories', | |
fn (): Collection => $this->categories->pluck('Tag')->unique() | |
), | |
]), | |
$this->mergeWhen(! $request->boolean('collection'), [ | |
'categories' => $this->whenLoaded( | |
'categories', | |
fn (): AnonymousResourceCollection => Category::collection($this->categories->unique()) | |
), | |
]), | |
]; | |
} | |
public function links(Request $request): array | |
{ | |
return [ | |
'links' => [ | |
'self' => route('api.blog.show', $this), | |
'permalink' => $this->permalink, | |
], | |
]; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment