将端点反映为 Symfonys 序列化程序的模型,同时考虑共享响应属性

Reflect Endpoints as Model for Symfonys Serializer, also take shared response attributes into account

我想要什么:

我尝试反序列化使用 PHP 中的 API 调用的响应。对于我的端点,我喜欢有一个模型,这样序列化程序就可以做到这一点很神奇。

回复:

{
    "count": 123,
    "next": "string",
    "previous": "string",
    "limit": 123,
    "offset": 123,
    "results": 
      [
        {...},
        {...}
      ]

}

现在,每个响应都带有相同的“基本”属性:计数、限制、偏移...等等。然后在结果中,每个结果都是特定于端点的。

例如:

{
    "id": 0,
    "name": "string",
    "handle": "string"
}

在 Symfony 中我调用如下:

$this->serializer->deserialize($data, EndpointModel::class, 'json')

应该给我:

App\Api\Model\BaseModel {#541 ▼
  -count: 901
  -limit: 10
  -offset: 0
  -results: array:10 [▼
    0 => App\Api\Model\EndpointModel {#547 ▼
      -id: 3203
      -name: FooBar
    }
    1 => App\Api\Model\ResultModel {#549 ▶}
    ...
  ]
}

我被困在哪里:

我创建了 BaseModel.phphttps://hastebin.com/exagaworez.xml
我有 EndpointModel.php: https://hastebin.com/tijinojixo.xml
所以我称它为:

$this->serializer->deserialize($data, BaseModel::class, 'json')  

这工作得很好,但它只适用于一个端点。我想要的是每个端点的模型,并用序列化程序以某种方式调用它,以便它转换我的响应。

我怎样才能实现这样的目标?

由于我还需要在 BaseModel 中描述端点,因此我只能使用一个端点。我可以一遍又一遍地复制代码来实现我的目标,但这似乎很糟糕。

我使用 Symfony,使用 API 和 http_client 并希望使用序列化程序转换响应。也许有人可以指出正确的方向或给我一些阅读的东西:)

提前致谢!如果您需要更多信息,请告诉我

我最终得到了以下结构,它给出了我想要的输出:

由于我对大多数端点的响应具有相同的属性,因此我创建了一个名为 BaseResponse:

abstract class
<?php


namespace App\Api\Response;


abstract class BaseResponse
{
    /**
     * @var int
     */
    private $count;

    /**
     * @var int
     */
    private $limit;

    /**
     * @var int
     */
    private $offset;


    /**
     * @return int
     */
    public function getCount(): int
    {
        return $this->count;
    }

    /**
     * @param int $count
     */
    public function setCount(int $count): void
    {
        $this->count = $count;
    }

    /**
     * @return int
     */
    public function getLimit(): int
    {
        return $this->limit;
    }

    /**
     * @param int $limit
     */
    public function setLimit(int $limit): void
    {
        $this->limit = $limit;
    }

    /**
     * @return int
     */
    public function getOffset(): int
    {
        return $this->offset;
    }

    /**
     * @param int $offset
     */
    public function setOffset(int $offset): void
    {
        $this->offset = $offset;
    }
}

这里我存储了我回复的所有共享值。

然后我创建一个 class,其中 extends 我的 BaseResponse 并处理特定属性或主要是我的 results ,如下所示:

<?php


namespace App\Api\Response;


use App\Api\Model\CenterModel;

class CenterResponse extends BaseResponse
{

    /**
     * @var CenterModel
     */
    private $results;

    public function __construct(CenterModel ...$results)
    {
        $this->results = $results;
    }

    /**
     * @return array
     */
    public function getResults(): array
    {
        return $this->results;
    }

    /**
     * @param $results
     */
    public function setResults(CenterModel ...$results): void
    {
        $this->results = $results;
    }
}

最后我可以创建我的模型,它包含我的端点对象的结构。这样我就可以在不接触响应部分的情况下跟踪实体。看这里:

<?php


namespace App\Api\Model;

/**
 * Class CenterModel
 * @package App\Api\Model
 */
class CenterModel
{
    /**
     * @var string
     */
    private $name;

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * @param string $name
     */
    public function setName(string $name): void
    {
        $this->name = $name;
    }
}

这样我就可以跟踪我的响应和端点模型,而无需重复太多代码行。

稍后我使用序列化程序并调用 CenterResponse 来反序列化响应。像这样:

$this->serializer->deserialize($data, CenterResponse::class, 'json');

然后输出将是这样的:

Center.php on line 64:
App\Api\Response\CenterResponse {#541 ▼
  -results: array:10 [▼
    0 => App\Api\Model\CenterModel {#547 ▼
      -name: "Center Name here"
    }
    1 => App\Api\Model\CenterModel {#549 ▶}
    2 => App\Api\Model\CenterModel {#581 ▶}
    3 => App\Api\Model\CenterModel {#621 ▶}
    4 => App\Api\Model\CenterModel {#623 ▶}
    5 => App\Api\Model\CenterModel {#624 ▶}
    6 => App\Api\Model\CenterModel {#625 ▶}
    7 => App\Api\Model\CenterModel {#626 ▶}
    8 => App\Api\Model\CenterModel {#627 ▶}
    9 => App\Api\Model\CenterModel {#628 ▶}
  ]
  -count: 901
  -limit: 10
  -offset: 0
}

也许这对你们中的一些人来说是一个很好的起点 :) 现在我使用它,但也许也有不同的方法。