如何使用 Symfony 5 EasyAdmin Bundle 基于多对多关系在列表中显示用户特定数据

How to show user specific data on the list based on a many to many relationship using Symfony 5 EasyAdmin Bundle

我对 EasyAdmin 包还很陌生。我试图在登录用户的列表中加载用户特定的内容。

这是我的 composer.json 文件:

{
"type": "project",
"license": "proprietary",
"require": {
    "php": "^7.2.5",
    "ext-ctype": "*",
    "ext-iconv": "*",
    "easycorp/easyadmin-bundle": "^2.3",
    "sensio/framework-extra-bundle": "^5.1",
    "symfony/asset": "5.0.*",
    "symfony/console": "5.0.*",
    "symfony/dotenv": "5.0.*",
    "symfony/expression-language": "5.0.*",
    "symfony/flex": "^1.3.1",
    "symfony/form": "5.0.*",
    "symfony/framework-bundle": "5.0.*",
    "symfony/http-client": "5.0.*",
    "symfony/intl": "5.0.*",
    "symfony/mailer": "5.0.*",
    "symfony/monolog-bundle": "^3.1",
    "symfony/notifier": "5.0.*",
    "symfony/orm-pack": "*",
    "symfony/process": "5.0.*",
    "symfony/security-bundle": "5.0.*",
    "symfony/serializer-pack": "*",
    "symfony/string": "5.0.*",
    "symfony/translation": "5.0.*",
    "symfony/twig-pack": "*",
    "symfony/validator": "5.0.*",
    "symfony/web-link": "5.0.*",
    "symfony/yaml": "5.0.*"
},

我有一个项目需求实体,它与用户实体有如下多对多关系:

/**
 * @var \Doctrine\Common\Collections\Collection
 *
 * @ORM\ManyToMany(targetEntity="User", inversedBy="projectRequirementsHasUserProjectRequirements")
 * @ORM\JoinTable(name="project_requirements_has_user",
 *   joinColumns={
 *     @ORM\JoinColumn(name="project_requirements_has_user_project_requirements_id", referencedColumnName="id")
 *   },
 *   inverseJoinColumns={
 *     @ORM\JoinColumn(name="project_requirements_has_user_user_id", referencedColumnName="id")
 *   }
 * )
 */
private $projectRequirementsHasUserUser;

/**
 * Constructor
 */
public function __construct()
{
    $this->projectRequirementsHasUserUser = new \Doctrine\Common\Collections\ArrayCollection();
}

所以在添加需求时我可以这样分配用户:

可以看到第一个需求已经分配给了2个用户:

现在我想显示已分配给登录用户的所有要求。

我开始知道我需要覆盖默认的 EasyAdminController,所以我在 config/packages/easy_admin.yaml:

中配置了我的实体
    # Project Planning
    ProjectRequirements:
      controller: App\Controller\ProjectRequirementsController
      class: App\Entity\ProjectRequirements

然后创建一个控制器,但不知道如何将过滤器或查询写入 select 只有已分配给登录用户的要求:

<?php
namespace App\Controller;

use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Controller\EasyAdminController;

class ProjectRequirementsController extends EasyAdminController {

protected function createListQueryBuilder($entityClass, $sortDirection, $sortField = null, $dqlFilter = null)
{

    /** @var QueryBuilder $result  */
    $result = parent::createListQueryBuilder($entityClass, $sortDirection, $sortField, $dqlFilter);




    return $result;

}

}

非常感谢任何帮助。

您似乎创建了 ManyToMany 单向连接。尝试使用 documentation.

中描述的双向映射

那么您应该可以通过用户实体中的数组集合轻松访问登录用户的分配。

经过大约 2 天的大量搜索,我终于明白了 EasyAdmin 和 Symfony QueryBuilder 是如何工作的。很高兴自己找到解决方案。所以这就是我想出的解决方案:

# App\Controller\ProjectRequirementsController.php

protected function createListQueryBuilder($entityClass, $sortDirection, $sortField = null, $dqlFilter = null)
{
    /** @var QueryBuilder $result  */
    $result = parent::createListQueryBuilder($entityClass, $sortDirection, $sortField, $dqlFilter);

    # Getting data User wise
    $result->leftJoin('entity.projectRequirementsHasUserUser', 'user')
    ->andWhere('user.id = :user')
    ->setParameter('user', $this->getUser());

    return $result;

}

希望这对以后的人有所帮助。

要在列表中显示用户特定数据,您需要在 $dqfilter 上添加一个参数。

// Creates the Doctrine query builder used to get all the items. 
// This will override the original method.
protected function createListQueryBuilder($entityClass, $sortDirection, $sortField = null, $dqlFilter = null)
{
     // If the parameter is equal to null, we set the parameter to user id
     if (null === $dqlFilter) {
         $dqlFilter = sprintf('entity.author = %s', $this->getUser()->getId());
     } else {

     // If the parameter is not null, we add a new parameter (user id) to the $dqfilter
         $dqlFilter .= sprintf(' AND entity.author = %s', $this->getUser()->getId());
     }
    
    return parent::createListQueryBuilder($entityClass, $sortDirection, $sortField, $dqlFilter);
}

// Creates the Doctrine query builder used to look for items according to the
// user's query. Override this method if you would not like that user can see other data after doing search query
protected function createSearchQueryBuilder($entityClass, $searchQuery, array $searchableFields, $sortField = null, $sortDirection = null, $dqlFilter = null)
{
   if (null === $dqlFilter) {
        $dqlFilter = sprintf('entity.author = %s', $this->getUser()->getId());
   } else {
        $dqlFilter .= sprintf(' AND entity.author = %s', $this->getUser()->getId());
   }

   return parent::createListQueryBuilder($entityClass, $sortDirection, $sortField, $dqlFilter);
}