Laravel+API Platform完整示例求助及响应格式疑问
Laravel + API Platform 完整使用示例(含分页、过滤器、序列化分组)
1. 配置齐全的Model示例
以下是包含分页、过滤器、序列化分组及JSON-LD支持的Model代码,直接适配Laravel环境:
<?php namespace App\Models; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Put; use ApiPlatform\Metadata\Delete; use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Doctrine\Orm\Filter\OrderFilter; use ApiPlatform\Metadata\ApiFilter; use ApiPlatform\Serializer\Filter\PropertyFilter; use Symfony\Component\Serializer\Annotation\Groups; use Illuminate\Database\Eloquent\Model; #[ApiResource( operations: [ new Get(normalizationContext: ['groups' => ['post:read']]), new GetCollection( normalizationContext: ['groups' => ['post:collection']], paginationEnabled: true, paginationItemsPerPage: 10, // 默认每页条数 paginationMaximumItemsPerPage: 50 // 允许的最大每页条数 ), new Post(denormalizationContext: ['groups' => ['post:write']]), new Put(normalizationContext: ['groups' => ['post:read']], denormalizationContext: ['groups' => ['post:write']]), new Delete() ], // 启用JSON-LD格式,解决@context/@id/@type缺失问题 formats: ['jsonld', 'json', 'html'] )] // 配置过滤器:模糊搜索、排序、返回字段过滤 #[ApiFilter(SearchFilter::class, properties: ['title' => 'partial', 'author.name' => 'exact'])] #[ApiFilter(OrderFilter::class, properties: ['id', 'created_at'], arguments: ['orderParameterName' => 'order'])] #[ApiFilter(PropertyFilter::class)] class Post extends Model { protected $fillable = ['title', 'content', 'author_id']; // 序列化分组定义 #[Groups(['post:collection', 'post:read'])] public $id; #[Groups(['post:collection', 'post:read', 'post:write'])] public $title; #[Groups(['post:read', 'post:write'])] public $content; #[Groups(['post:collection', 'post:read'])] public $created_at; // 关联关系示例 public function author() { return $this->belongsTo(User::class); } }
2. 自定义处理器示例
如果需要在CRUD流程中加入自定义业务逻辑,比如创建资源时自动关联当前用户:
<?php namespace App\Processor; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProcessorInterface; use App\Models\Post; use Symfony\Component\Serializer\SerializerInterface; class PostCreateProcessor implements ProcessorInterface { public function __construct(private readonly SerializerInterface $serializer) {} public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []) { // 按序列化分组反序列化数据到模型 /** @var Post $post */ $post = $this->serializer->deserialize( json_encode($data), Post::class, 'json', ['groups' => ['post:write']] ); // 自定义逻辑:绑定当前登录用户为作者 $post->author_id = auth()->id(); $post->save(); return $post; } }
要启用该处理器,只需在#[ApiResource]的对应操作中指定:
new Post( denormalizationContext: ['groups' => ['post:write']], processor: PostCreateProcessor::class )
3. 解决@context/@id/@type字段缺失问题
Laravel环境下API Platform默认未启用JSON-LD格式,才会导致这些字段丢失,两种解决方式:
- 在Model中配置支持JSON-LD:如上面Model示例中的
formats: ['jsonld', 'json', 'html'],请求时携带Accept: application/ld+json头即可返回带JSON-LD字段的响应。 - 全局设置默认格式为JSON-LD:修改
config/api_platform.php:
return [ // ... 'formats' => [ 'jsonld' => ['application/ld+json'], 'json' => ['application/json'], ], 'default_format' => 'jsonld', // ... ];
4. 你的PushToken模型&处理器适配建议
针对你现有的PushToken代码,调整后即可满足需求:
修改后的PushToken模型
<?php namespace App\Models; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Post; use ApiPlatform\Metadata\Delete; use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; use ApiPlatform\Metadata\ApiFilter; use Symfony\Component\Serializer\Annotation\Groups; use Illuminate\Database\Eloquent\Model; #[ApiResource( operations: [ new Get(normalizationContext: ['groups' => ['push_token:read']]), new GetCollection( normalizationContext: ['groups' => ['push_token:collection']], paginationEnabled: true ), new Post(denormalizationContext: ['groups' => ['push_token:write']]), new Delete() ], formats: ['jsonld', 'json'] )] #[ApiFilter(SearchFilter::class, properties: ['token' => 'exact', 'user_id' => 'exact'])] class PushToken extends Model { protected $fillable = ['token', 'user_id', 'device_type']; #[Groups(['push_token:collection', 'push_token:read'])] public $id; #[Groups(['push_token:collection', 'push_token:read', 'push_token:write'])] public $token; #[Groups(['push_token:collection', 'push_token:read', 'push_token:write'])] public $user_id; #[Groups(['push_token:collection', 'push_token:read', 'push_token:write'])] public $device_type; #[Groups(['push_token:collection', 'push_token:read'])] public $created_at; }
修改后的处理器示例
<?php namespace App\Processor; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProcessorInterface; use App\Models\PushToken; use Symfony\Component\Serializer\SerializerInterface; class PushTokenCreateProcessor implements ProcessorInterface { public function __construct(private readonly SerializerInterface $serializer) {} public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []) { /** @var PushToken $pushToken */ $pushToken = $this->serializer->deserialize( json_encode($data), PushToken::class, 'json', ['groups' => ['push_token:write']] ); // 自定义逻辑:避免重复存储相同token $existingToken = PushToken::where('token', $pushToken->token)->first(); if ($existingToken) { return $existingToken; } $pushToken->save(); return $pushToken; } }
内容的提问来源于stack exchange,提问作者Shahzaib Tariq Butt
相关产品推荐
相关产品推荐

