You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在API Platform中创建不基于实体的自定义API资源?

API Platform 原生支持非实体类作为资源使用,不需要你完全自行实现转换器,有两种成熟的方案可选:

方案1:使用自定义DTO作为ApiResource(更推荐,复用原生能力)

这种方式可以完全复用API Platform的序列化、格式适配、校验等能力,和实体资源的使用体验一致:

  1. 首先创建一个普通的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;
}
  1. 创建对应的数据提供器,实现你自定义的数据获取逻辑:
<?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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 03:24:03