api-resource-patterns by iserter/laravel-claude-agents
npx skills add https://github.com/iserter/laravel-claude-agents --skill api-resource-patterns<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class PostResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'content' => $this->content,
'created_at' => $this->created_at->toISOString(),
'updated_at' => $this->updated_at->toISOString(),
];
}
}
public function toArray($request): array
{
return [
'id' => $this->id,
'title' => $this->title,
// 仅在已加载时包含
'author' => new UserResource($this->whenLoaded('user')),
// 仅在条件为真时包含
'content' => $this->when($request->user()?->can('view', $this->resource), $this->content),
// 仅在非空时包含
'comments_count' => $this->when($this->comments_count !== null, $this->comments_count),
// 条件性合并
$this->mergeWhen($request->user()?->isAdmin(), [
'internal_notes' => $this->internal_notes,
]),
];
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
public function toArray($request): array
{
return [
'id' => $this->id,
'title' => $this->title,
// 单一关系
'author' => new UserResource($this->whenLoaded('user')),
// 集合关系
'comments' => CommentResource::collection($this->whenLoaded('comments')),
// 嵌套关系
'category' => new CategoryResource($this->whenLoaded('category')),
];
}
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class PostCollection extends ResourceCollection
{
public function toArray($request): array
{
return [
'data' => $this->collection,
'meta' => [
'total' => $this->total(),
'count' => $this->count(),
'per_page' => $this->perPage(),
'current_page' => $this->currentPage(),
'total_pages' => $this->lastPage(),
],
'links' => [
'self' => $request->url(),
'first' => $this->url(1),
'last' => $this->url($this->lastPage()),
'prev' => $this->previousPageUrl(),
'next' => $this->nextPageUrl(),
],
];
}
}
public function toArray($request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'links' => [
'self' => route('posts.show', $this->id),
'author' => route('users.show', $this->user_id),
'comments' => route('posts.comments.index', $this->id),
],
];
}
// 在控制器中
public function store(Request $request)
{
$post = Post::create($request->validated());
return (new PostResource($post))
->response()
->setStatusCode(201)
->header('Location', route('posts.show', $post));
}
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'assigned_at' => $this->whenPivotLoaded('role_user', function () {
return $this->pivot->created_at;
}),
'expires_at' => $this->whenPivotLoadedAs('assignment', 'role_user', function () {
return $this->assignment->expires_at;
}),
];
}
// 在 AppServiceProvider 中禁用包装
use Illuminate\Http\Resources\Json\JsonResource;
public function boot()
{
JsonResource::withoutWrapping();
}
// 或针对每个资源
public static $wrap = 'post';
public function with($request): array
{
return [
'version' => '1.0.0',
'timestamp' => now()->toISOString(),
];
}
public function withResponse($request, $response)
{
$response->header('X-Value', 'True');
}
// ✅ 防止 N+1 查询
'author' => new UserResource($this->whenLoaded('user')),
// ❌ 会导致 N+1 查询
'author' => new UserResource($this->user),
use Illuminate\Http\Request;
public function toArray(Request $request): array
{
// ...
}
// ✅ 为不同上下文创建独立的资源
class PostResource extends JsonResource { }
class PostListResource extends JsonResource { }
class PostDetailResource extends JsonResource { }
// ❌ 不要让一个资源处理所有事情
// ✅ 使用集合类
return new PostCollection(Post::paginate());
// ✅ 或使用集合方法
return PostResource::collection(Post::all());
class PostController extends Controller
{
public function index()
{
$posts = Post::with(['user', 'category'])
->withCount('comments')
->paginate(15);
return new PostCollection($posts);
}
public function show(Post $post)
{
$post->load(['user', 'comments.user', 'tags']);
return new PostResource($post);
}
public function store(StorePostRequest $request)
{
$post = Post::create($request->validated());
return (new PostResource($post))
->response()
->setStatusCode(201);
}
}
每周安装量
110
代码仓库
GitHub 星标数
28
首次出现
2026年1月22日
安全审计
安装于
opencode94
codex88
gemini-cli81
github-copilot78
claude-code72
cursor70
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class PostResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'content' => $this->content,
'created_at' => $this->created_at->toISOString(),
'updated_at' => $this->updated_at->toISOString(),
];
}
}
public function toArray($request): array
{
return [
'id' => $this->id,
'title' => $this->title,
// Only include if loaded
'author' => new UserResource($this->whenLoaded('user')),
// Only include if condition is true
'content' => $this->when($request->user()?->can('view', $this->resource), $this->content),
// Only include if not null
'comments_count' => $this->when($this->comments_count !== null, $this->comments_count),
// Merge conditionally
$this->mergeWhen($request->user()?->isAdmin(), [
'internal_notes' => $this->internal_notes,
]),
];
}
public function toArray($request): array
{
return [
'id' => $this->id,
'title' => $this->title,
// Single relationship
'author' => new UserResource($this->whenLoaded('user')),
// Collection relationship
'comments' => CommentResource::collection($this->whenLoaded('comments')),
// Nested relationships
'category' => new CategoryResource($this->whenLoaded('category')),
];
}
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class PostCollection extends ResourceCollection
{
public function toArray($request): array
{
return [
'data' => $this->collection,
'meta' => [
'total' => $this->total(),
'count' => $this->count(),
'per_page' => $this->perPage(),
'current_page' => $this->currentPage(),
'total_pages' => $this->lastPage(),
],
'links' => [
'self' => $request->url(),
'first' => $this->url(1),
'last' => $this->url($this->lastPage()),
'prev' => $this->previousPageUrl(),
'next' => $this->nextPageUrl(),
],
];
}
}
public function toArray($request): array
{
return [
'id' => $this->id,
'title' => $this->title,
'links' => [
'self' => route('posts.show', $this->id),
'author' => route('users.show', $this->user_id),
'comments' => route('posts.comments.index', $this->id),
],
];
}
// In controller
public function store(Request $request)
{
$post = Post::create($request->validated());
return (new PostResource($post))
->response()
->setStatusCode(201)
->header('Location', route('posts.show', $post));
}
public function toArray($request): array
{
return [
'id' => $this->id,
'name' => $this->name,
'assigned_at' => $this->whenPivotLoaded('role_user', function () {
return $this->pivot->created_at;
}),
'expires_at' => $this->whenPivotLoadedAs('assignment', 'role_user', function () {
return $this->assignment->expires_at;
}),
];
}
// Disable wrapping in AppServiceProvider
use Illuminate\Http\Resources\Json\JsonResource;
public function boot()
{
JsonResource::withoutWrapping();
}
// Or per resource
public static $wrap = 'post';
public function with($request): array
{
return [
'version' => '1.0.0',
'timestamp' => now()->toISOString(),
];
}
public function withResponse($request, $response)
{
$response->header('X-Value', 'True');
}
// ✅ Prevents N+1 queries
'author' => new UserResource($this->whenLoaded('user')),
// ❌ Will cause N+1 queries
'author' => new UserResource($this->user),
use Illuminate\Http\Request;
public function toArray(Request $request): array
{
// ...
}
// ✅ Create separate resources for different contexts
class PostResource extends JsonResource { }
class PostListResource extends JsonResource { }
class PostDetailResource extends JsonResource { }
// ❌ Don't make one resource do everything
// ✅ Use collection class
return new PostCollection(Post::paginate());
// ✅ Or collection method
return PostResource::collection(Post::all());
class PostController extends Controller
{
public function index()
{
$posts = Post::with(['user', 'category'])
->withCount('comments')
->paginate(15);
return new PostCollection($posts);
}
public function show(Post $post)
{
$post->load(['user', 'comments.user', 'tags']);
return new PostResource($post);
}
public function store(StorePostRequest $request)
{
$post = Post::create($request->validated());
return (new PostResource($post))
->response()
->setStatusCode(201);
}
}
Weekly Installs
110
Repository
GitHub Stars
28
First Seen
Jan 22, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode94
codex88
gemini-cli81
github-copilot78
claude-code72
cursor70
lark-cli 共享规则:飞书资源操作指南与权限配置详解
39,000 周安装