首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Symfony2 / Doctrine -修改所有查询

Symfony2 / Doctrine -修改所有查询
EN

Stack Overflow用户
提问于 2012-11-28 07:24:05
回答 2查看 2.7K关注 0票数 4

是否可以通过某种类型的遍历程序运行所有sort查询,以便我可以根据当前用户的凭据修改查询?理想情况下,我不必在每次查询时显式调用自定义遍历程序的setHint,因为这会限制我将当前SecurityContext传递到遍历程序的能力。

此外,我不喜欢使用Doctrine筛选器,因为我不能使用筛选器修改连接条件,而且我会被迫使用"IN“子句,这将严重影响性能

目前,我正在使用一个基于用户凭据修改QueryBuilder的服务,但这变得单调乏味,因为我需要在每次创建新的QueryBuilder时调用该服务,并且在存储库开始使用时更加麻烦(因为我需要将该服务注入到每个需要修改查询的存储库中。

希望我已经解释得足够清楚了。感谢您的反馈!

EN

回答 2

Stack Overflow用户

发布于 2012-11-28 23:49:33

我想我已经解决了我自己的问题。如果其他人有更优雅的方法来实现这些结果,请随时解释。为了修改我的所有查询,我创建了一个自定义EntityManager和自定义EntityRepository。

在我的自定义EntityManager中,我已经覆盖了2个方法。create()和getRepository()

代码语言:javascript
复制
public static function create($conn, Configuration $config, EventManager $eventManager = null)
{
    if ( ! $config->getMetadataDriverImpl()) {
        throw ORMException::missingMappingDriverImpl();
    }

    switch (true) {
        case (is_array($conn)):
            $conn = \Doctrine\DBAL\DriverManager::getConnection(
                $conn, $config, ($eventManager ?: new EventManager())
            );
            break;

        case ($conn instanceof Connection):
            if ($eventManager !== null && $conn->getEventManager() !== $eventManager) {
                 throw ORMException::mismatchedEventManager();
            }
            break;

        default:
            throw new \InvalidArgumentException("Invalid argument: " . $conn);
    }

    return new MyCustomEntityManager($conn, $config, $conn->getEventManager());
}

此方法中唯一更改的是我返回了自己的EntityManger(MyCustomEntityManager).然后,我按如下方式覆盖了getRepository方法:

代码语言:javascript
复制
public function getRepository($entityName)
{
    $entityName = ltrim($entityName, '\\');

    if (isset($this->repositories[$entityName])) {
        return $this->repositories[$entityName];
    }

    $metadata = $this->getClassMetadata($entityName);
    $repositoryClassName = $metadata->customRepositoryClassName;

    if ($repositoryClassName === null) {
        $repositoryClassName = "Acme\DemoBundle\Doctrine\ORM\MyCustomEntityRepository";
    }

    $repository = new $repositoryClassName($this, $metadata);

    $this->repositories[$entityName] = $repository;

    return $repository;
}

在这里,我也只修改了一行。我指定了自己的默认存储库Acme\DemoBundle\Doctrine\ORM\MyCustomEntityRepository.,而不是依赖于DBAL配置来检索默认的$repositoryClassName

一旦您创建了自己的自定义EntityRepository,就没有限制了。您可以将服务注入到存储库中(我目前使用的是JMS注释,如下所述),或者对createQueryBuilder方法中的QueryBuilder执行自定义操作,如下所示:

代码语言:javascript
复制
use JMS\DiExtraBundle\Annotation as DI;

class MyCustomEntityRepository extends EntityRepository
{
    private $myService;

    public function createQueryBuilder($alias)
    {
         $queryBuilder = parent::createQueryBuilder($alias);

          /** INSERT CUSTOM CODE HERE **/

          return $queryBuilder;
    }

    /**
    * @DI\InjectParams({
    *     "myService" = @DI\Inject("my_service_id")
    * })
    */
    public function setMyService(MyServiceInterface $myService)
    {
        $this->myService = $myService;
    }
}

一旦创建了自己的EntityRepository,就应该让需要此自定义功能的所有存储库都扩展MyCustomEntityRepository。您甚至可以更进一步,创建自己的QueryBuilder来进一步扩展它。

票数 1
EN

Stack Overflow用户

发布于 2015-05-04 17:50:38

通过defaultQueryHint (Doctrin2.5新特性)配置选项,您可以编写一个custom AST Walker并设置您的应用程序,以便对所有查询使用此walker:

代码语言:javascript
复制
<?php
/** @var \Doctrine\ORM\EntityManager $em */
$em->getConfiguration()->setDefaultQueryHint(
    Query::HINT_CUSTOM_TREE_WALKERS,
    ['YourWalkerFQClassName']
)
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13595059

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档