基于Doctrine ORM的中间表mediaOrder排序及关联查询异常问题
解决步骤
1. 给中间实体字段添加序列化组
修改TemplateFacebookPostMediaItem实体,将关联的mediaItem和排序字段mediaOrder加入template-read序列化组,确保序列化时能输出这些数据:
<?php namespace App\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * @ORM\Entity() * @ORM\Table(name="template_facebook_post_media_item") */ class TemplateFacebookPostMediaItem { // 其他字段和方法保持不变 /** * @ORM\ManyToOne(targetEntity=MediaItem::class, inversedBy="templateFacebookPostMediaItems") * @ORM\JoinColumn(name="media_item_id", referencedColumnName="id") * @Groups({"template-read"}) */ private $mediaItem; /** * @ORM\Column(type="integer") * @Groups({"template-read"}) */ private $mediaOrder; // 其他方法保持不变 }
2. 配置关联排序并启用序列化
修改TemplateFacebookPost实体的OneToMany关联,添加排序规则并将关联字段加入序列化组,同时新增一个兼容原有接口的getMediaItems方法:
<?php namespace App\Entity; use ApiPlatform\Core\Annotation\ApiResource; use App\Repository\TemplateFacebookPostRepository; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Serializer\Annotation\Groups; /** * @ApiResource( * itemOperations={"get"}, * collectionOperations={} * ) * @ORM\Entity(repositoryClass=TemplateFacebookPostRepository::class) */ class TemplateFacebookPost { // 其他字段保持不变 /** * @ORM\OneToMany(targetEntity=TemplateFacebookPostMediaItem::class,mappedBy="templateFacebookPost", orphanRemoval=true, cascade={"persist"}) * @ORM\OrderBy({"mediaOrder" = "ASC"}) * @Groups({"template-read"}) */ private $templateFacebookPostMediaItems; // 初始化集合 public function __construct() { $this->templateFacebookPostMediaItems = new ArrayCollection(); } /** * 返回排序后的MediaItem数组(兼容原有接口字段) * @Groups({"template-read"}) */ public function getMediaItems(): Collection { return $this->templateFacebookPostMediaItems->map(function(TemplateFacebookPostMediaItem $item) { return $item->getMediaItem(); }); } // 其他方法保持不变 }
3. 优化查询避免懒加载问题
在TemplateFacebookPostRepository中添加查询方法,确保关联数据被预加载,避免N+1查询和懒加载导致的序列化空值:
<?php namespace App\Repository; use App\Entity\TemplateFacebookPost; use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; use Doctrine\Persistence\ManagerRegistry; class TemplateFacebookPostRepository extends ServiceEntityRepository { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, TemplateFacebookPost::class); } public function findWithSortedMediaItems(int $id): ?TemplateFacebookPost { return $this->createQueryBuilder('p') ->leftJoin('p.templateFacebookPostMediaItems', 'm') ->leftJoin('m.mediaItem', 'mi') ->addSelect('m', 'mi') ->where('p.id = :id') ->setParameter('id', $id) ->orderBy('m.mediaOrder', 'ASC') ->getQuery() ->getOneOrNullResult(); } }
4. 完善MediaItem反向关联(可选)
如果需要从MediaItem端查询关联的帖子,可在MediaItem实体中添加反向关联:
<?php namespace App\Entity; use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; class MediaItem { // 其他字段保持不变 /** * @ORM\OneToMany(targetEntity=TemplateFacebookPostMediaItem::class, mappedBy="mediaItem") */ private $templateFacebookPostMediaItems; public function __construct() { $this->templateFacebookPostMediaItems = new ArrayCollection(); } // 对应的getter/setter方法 public function getTemplateFacebookPostMediaItems(): Collection { return $this->templateFacebookPostMediaItems; } }
内容的提问来源于stack exchange,提问作者hassan softech
相关产品推荐
相关产品推荐

