<?php
namespace App\Http\Resources;
use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\JsonResource;
class PostResource extends JsonResource
{
public function toArray(Request $request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'slug' => $this->slug,
'excerpt' => $this->excerpt,
'body' => $this->when($request->user()?->id === $this->user_id, $this->body),
'status' => $this->status,
'published_at' => $this->published_at?->toISOString(),
'created_at' => $this->created_at->toISOString(),
'updated_at' => $this->updated_at->toISOString(),
// Computed properties
'read_time' => $this->readTime(),
'is_published' => $this->isPublished(),
// Conditional relationships
'author' => new UserResource($this->whenLoaded('author')),
'tags' => TagResource::collection($this->whenLoaded('tags')),
'comments' => CommentResource::collection($this->whenLoaded('comments')),
// Counts
'comments_count' => $this->when(
$this->relationLoaded('comments'),
fn () => $this->comments->count()
),
// Links
'links' => [
'self' => route('api.posts.show', $this->id),
'author' => route('api.users.show', $this->user_id),
],
];
}
public function with(Request $request): array
{
return [
'meta' => [
'version' => '1.0',
],
];
}
}
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Http\Resources\PostResource;
use App\Models\Post;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index(Request $request)
{
$posts = Post::query()
->with(['author', 'tags'])
->when($request->include === 'comments', fn ($q) => $q->with('comments'))
->latest()
->paginate(20);
return PostResource::collection($posts);
}
public function show(Post $post)
{
$post->load(['author', 'tags', 'comments.author']);
return new PostResource($post);
}
}
API resources transform Eloquent models into JSON responses with full control over structure and data exposure. I create resource classes that extend JsonResource and define a toArray() method returning the desired JSON structure. Resources hide sensitive attributes, format dates, include computed properties, and conditionally include relationships. The whenLoaded() method includes relationships only if they're eager loaded, preventing N+1 queries. Resource collections handle arrays of models, while preserveQuery() maintains pagination links. Anonymous resources work for one-off transformations without creating dedicated classes. The with() method adds meta information to all responses. This layer provides consistent API responses and decouples database structure from API contracts.
Related snips
payload = {
sub: user.id,
iss: 'https://auth.example.com',
aud: 'codesnips-api',
exp: 15.minutes.from_now.to_i,
iat: Time.now.to_i,
JWT issuance and verification without common footguns
module Api
module V1
class UsersController < BaseController
def show
user = User.includes(:profile).find(params[:id])
ETags for conditional requests and caching
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
createdAt: String!
GraphQL API with Spring Boot
<?php
namespace App\Providers;
use App\Contracts\PaymentGateway;
use App\Services\StripePaymentGateway;
Laravel service container and dependency injection
import axios, { AxiosError } from 'axios'
import { v4 as uuidv4 } from 'uuid'
const api = axios.create({
baseURL: import.meta.env.VITE_API_URL || 'http://localhost:3000/api/v1',
timeout: 15000,
Axios API client with interceptors
import graphene
from graphene_django import DjangoObjectType
from blog.models import Post, Comment
class PostType(DjangoObjectType):
Django GraphQL with Graphene
Share this code
Here's the card — post it anywhere.