在 Symfony 中使用 Querybuilder 创建更全面的关联

Creating more comprehensive associations with Querybuilder in Symfony

我正在构建一个查询,用于创建具有与用户相关联的项目的帖子列表,并在该结构中满足“tierAccess”的正确条件。

我的查询生成器:

$qb = $this->em->createQueryBuilder();

        foreach($subs as $sub)
        {
            if($sub->getDisabled() == true)
            {
                continue;
            }

            $qb->select('p')
               ->from('App\Entity\ProjectPost', 'p')
               ->where('project = '.$sub->getProject()->getId())
               ->andwhere('p.Published = true')
               ->andwhere('p.TierAccess = '.$sub->getProjectTier()->getId())
               ->orderBy('p.PostTime', 'DESC');


            $query = $qb->getQuery();

           $object[] = $query->execute();
        }

我的目标是添加用户订阅允许的 posts,并在该订阅中确保允许他们访问此 post(即:tierAccess)。

然后我 return 对象变量传递到我的 Twig 模板文件。

我收到的错误是:

[Semantical Error] line 0, col 45 near 'project = 3 AND': Error: 'project' is not defined.

我的 ProjectPost 实体:

class ProjectPost
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $PostTitle;

    /**
     * @ORM\Column(type="text", nullable=true)
     */
    private $PostHero;

    /**
     * @ORM\Column(type="string", length=255, nullable=false)
     */
    private $PostType;

    /**
     * @ORM\Column(type="text")
     */
    private $PostBody;

    /**
     * @ORM\ManyToOne(targetEntity=Project::class, inversedBy="projectPosts")
     * @ORM\JoinColumn(nullable=false)
     */
    private $Project;

    /**
     * @ORM\Column(type="array", nullable=true)
     */
    private $TierAccess = [];

    /**
     * @ORM\Column(type="datetimetz", nullable=true)
     */
    private $PostTime;

    /**
     * @ORM\ManyToOne(targetEntity=User::class, inversedBy="projectPosts")
     * @ORM\JoinColumn(nullable=true)
     */
    private $PostBy;

    /**
     * @ORM\Column(type="array", nullable=true)
     */
    private $PostCategories = [];

    /**
     * @ORM\Column(type="boolean")
     */
    private $Published;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $PostCover;

    /**
    * @ORM\Column(type="boolean")
    */
    private $PostSupporter = 0;
}

最基本的错误是这个:

->where('p.Project = '.$sub->getProject()->getId()) 

请注意,您将 p 声明为 Post 的别名,然后您不使用它。即使您将 属性 定义为 Project,您也试图将其用作 project


尽管如此,整个事情还是很可疑的。在循环中执行查询通常表明设计有问题。

一种更简单的方法,使用 WHERE IN 而不是循环和多重选择:

// get the "subs" ids in an array:
$subsIds = array_map(fn($s) => $s->getProject()->getId(), $subs); 

qb->select('p')
   ->from('App\Entity\ProjectPost', 'p')
   ->where('p.Project IN :subsIds')
   ->andwhere('p.Published = true')
   ->andwhere('p.TierAccess = '.$sub->getProjectTier()->getId())
   ->orderBy('p.PostTime', 'DESC')
   ->setParameter('subsIds', $subsIds)
;

$result = $qb->getQuery()->getResult;