不确定标题是否有意义,但会尝试用示例进行解释:
例如,我有以下实体:
#[ORM\Entity(repositoryClass: Post::class)]
class Post
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $body = null;
#[ORM\ManyToOne(inversedBy: 'post')]
private ?User $user = null;
}
还有
#[ORM\Entity(repositoryClass: User::class)]
#[UniqueEntity(fields: ['email'], message: 'There is already an account with this email')]
class User
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 180, unique: true)]
private ?string $email = null;
#[ORM\Column(type: Types::BLOB, nullable: true)]
private $summary = null;
#[ORM\OneToMany(mappedBy: 'posts', targetEntity: Post::class)]
private Collection $posts;
}
联接是 OneToMany,其中每个用户可以有多个帖子,每个帖子只能有一个用户。
User::$summary 是数据库中的一个 blob,因此我有一个流标准化器,用于在通过 json 响应进行标准化时将 PHP 流资源转换为字符串。这只是通过调用 is_resource($data) 检查要求标准化的 $data 是否是流资源。如果为 true,则可以通过此类对其进行标准化。
class StreamNormalizer implements NormalizerInterface
{
public function __construct(
) {
}
public function normalize( $topic, string $format = null, array $context = [])
{
$data = stream_get_contents($topic);
return $data;
}
public function supportsNormalization($data, string $format = null, array $context = []): bool
{
return is_resource($data);
}
}
我用来获取帖子数据的 Post 控制器中的路由是:
#[Route('/feed', name: 'app_post_feed', methods: 'GET')]
public function feed(EntityManagerInterface $entityManager): Response
{
$posts = $entityManager->getRepository(Post::class)->findAll();
return $this->json($posts);
}
这按预期工作,除非用户发布了多个帖子,然后该用户对象的所有后续出现的 $summary 为空:
[
{
"id": 1,
"user": {
"id": 1,
"summary": "This is a summary",
"email": "[email protected]",
"userIdentifier": "[email protected]",
"verified": false
}
},
{
"id": 2,
"user": {
"id": 1,
"summary": "",
"email": "[email protected]",
"userIdentifier": "[email protected]",
"verified": false
}
}
}
如您所见,我有 2 个帖子,都是同一用户的。但仅设置了第一个帖子的用户的摘要,第二个帖子的用户缺少其摘要值,即使他们是同一用户!
我猜这可能是有意的行为,为了性能而不多次重新规范化对象?但我希望同一实体的所有出现的数据都是相同的?
我尝试调整我的标准化器,以防它试图重新标准化已经标准化的对象,但这没有什么区别:
class StreamNormalizer implements NormalizerInterface
{
public function __construct(
) {
}
public function normalize( $topic, string $format = null, array $context = [])
{
$data = is_resource($topic) ? stream_get_contents($topic) : $topic;
return $data;
}
public function supportsNormalization($data, string $format = null, array $context = []): bool
{
return is_resource($data);
}
}
根据@Dylan的建议,将吸气剂调整为以下内容仍然没有解决问题:
public function getSummary()
{
return is_resource($this->summary) ? stream_get_contents($this->summary) : $this->summary;
}
我已经四处搜索,但由于我不确定如何表达这个问题,所以我没有找到与我面临的问题类似的内容。如果这个问题已经在某个地方得到了回答,那么我们将不胜感激!
如果有人知道如何调整它,以便它为所有重复对象的出现返回相同的结果,那将很有帮助!
在另一个网站上的回答: https://github.com/symfony/symfony/discussions/51430
事实证明,我需要在获取流的内容后倒回流,否则指针(我假设?)仍然位于流的末尾,因此之后没有任何值。
我的新 StreamNormalizer:
class StreamNormalizer implements NormalizerInterface
{
public function __construct(
) {
}
public function normalize( $topic, string $format = null, array $context = [])
{
//get stream contents
$data = stream_get_contents($topic);
//rewind stream to revert the pointer to the start when this stream is read again
rewind($topic);
return $data;
}
public function supportsNormalization($data, string $format = null, array $context = []): bool
{
return is_resource($data);
}
}