如何在API Platform中创建不基于实体的自定义API资源?
API Platform 原生支持非实体类作为资源使用,不需要你完全自行实现转换器,有两种成熟的方案可选:
方案1:使用自定义DTO作为ApiResource(更推荐,复用原生能力)
这种方式可以完全复用API Platform的序列化、格式适配、校验等能力,和实体资源的使用体验一致:
- 首先创建一个普通的PHP类作为非实体资源,添加
#[ApiResource]注解配置即可:
<?php // src/Resource/Profile.php namespace App\Resource; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\Get; #[ApiResource( operations: [ new Get( uriTemplate: '/api/v1/get-profile', provider: ProfileProvider::class ) ] )] class Profile { public int $id; public string $firstName; public string $lastName; public string $email; public int $country; public int $countryCode; public string $phoneNumber; public string $nationality; public string $professionalIndustry; public string $jobTitle; public string $specialisation; public int $careerLengthMonth; public int $careerLengthYear; }
- 创建对应的数据提供器,实现你自定义的数据获取逻辑:
<?php // src/Provider/ProfileProvider.php namespace App\Provider; use ApiPlatform\Metadata\Operation; use ApiPlatform\State\ProviderInterface; use App\Resource\Profile; use Symfony\Contracts\HttpClient\HttpClientInterface; use Doctrine\DBAL\Connection; class ProfileProvider implements ProviderInterface { public function __construct( private HttpClientInterface $httpClient, private Connection $dbConnection ) {} public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null { // 步骤1:请求外部接口获取数据 $externalData = $this->httpClient->request('GET', '你的外部接口地址')->toArray(); // 步骤2:查询数据库补充数据 $extraData = $this->dbConnection->fetchAssociative('SELECT xxx FROM xxx WHERE id = ?', [$externalData['id']]); // 映射为Profile实例 $profile = new Profile(); $profile->id = $externalData['id']; $profile->firstName = $externalData['first_name']; // 其他字段赋值... // 补充数据库查到的字段 $profile->xxx = $extraData['xxx']; return $profile; } public function supports(Operation $operation, array $uriVariables = [], array $context = []): bool { return $operation->getClass() === Profile::class; } }
配置完成后直接访问接口,API Platform会自动输出符合JSON API规范的响应,不需要你手动处理格式。
方案2:在现有控制器中直接调用JSON API序列化器
如果你不想改动现有控制器结构,可以直接注入API Platform的序列化服务,手动序列化数据为JSON API格式:
<?php // src/Controller/MyController.php namespace App\Controller; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; use Doctrine\DBAL\Connection; class MyController extends AbstractController { public function getMemberInfo(SerializerInterface $serializer, HttpClientInterface $httpClient, Connection $dbConnection): Response { // 步骤1:使用http client从其他应用请求数据 $externalData = $httpClient->request('GET', '你的外部接口地址')->toArray(); // 步骤2:查询数据库获取数据并补充到数据数组 $extraData = $dbConnection->fetchAssociative('SELECT xxx FROM xxx WHERE id = ?', [$externalData['id']]); $data = array_merge($externalData, $extraData); // 序列化为JSON API格式,指定资源类型为profiles $jsonContent = $serializer->serialize($data, 'jsonapi', [ 'jsonapi_resource_type' => 'profiles', 'id' => $data['id'] ]); return new Response($jsonContent, Response::HTTP_OK, [ 'Content-Type' => 'application/vnd.api+json' ]); } }
内容的提问来源于stack exchange,提问作者Nguyen Nhut Tien
相关产品推荐
相关产品推荐

