关于php:在实体存储库或任何地方访问Symfony Config参数

Access Symfony Config Parameter in Entity Repository or Anywhere

我有很多配置设置,希望可以在整个应用程序中访问。例如,我有一个带有一些自定义查询的实体存储库。我想有一个全局参数,除非我特别更改,否则它将默认" limit "设置为类似10条记录的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class ViewVersionRepository extends EntityRepository {

    /**
     * Get all the versions for the specified view id, ordered by modification time.
     * @param integer $id
     * @param integer $limit
     * @param integer $offset default 0
     * @return array
     */

    public function findByViewIdLimit($id, $limit = NULL, $offset = 0) {

        // this won't work because we don't have access to the container... ;(
        $limit = ($limit != NULL) ? $limit : $this->container->getParameter('cms.limit');

        return $this->createQueryBuilder('v')
            ->where('v.viewId = :id')
            ->orderBy('v.timeMod', 'DESC')
            ->setParameter('id', $id)
            ->setFirstResult($offset)
            ->setMaxResults($limit)
            ->getQuery()
            ->getResult();
    }

}

在Symfony之前的生活中,我可以轻松地在我的parameter.yml中设置它:

1
cms.limit: 10

或在某些应用程序配置文件中为此创建一个常量:

1
define('cms.limit', 10);

但是在Symfony中,如果我使用参数,那么由于实体存储库中没有" container ",如何从实体存储库访问该参数?

人们说"将其作为参数传递",但是老实说,每次我调用查询时,这都是混乱且毫无意义的工作。如果您无法访问参数,那有什么意义呢!

其他人说,您必须构建一些全局服务模型(我也还不了解,并且似乎只是为了获取参数而进行的巨大工作)。

那么在任何上下文中(包括此处的一种)访问这样的全局参数的"最佳"方法是什么?

我不想访问内核,但是如果这是最后的选择,为什么从内核获取参数是"错误的",例如:

1
2
global $kernel;
$assetsManager = $kernel->getContainer()->get('acme_assets.assets_manager');a€?

我不敢相信很难访问全局参数。我了解需要明确说明依赖项的想法。但是在一个始终可以使用参数并且您总是想将其用作默认值的应用程序中,为什么这种标准和简单性不那么容易呢?

更新

根据以下答案,我已将ViewVersionRepository转换为服务(这是您的建议吗?)。

1
class ViewVersionRepository extends EntityRepository

{

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    // do not evidently need to set $this->viewVersion either
    // protected $viewVersion;
    protected $limit;

    /**
     * Allow limit to be set by parameter, injected by service definition
     * @param $limit
     */

    public function setLimit($limit) {
        $this->limit = $limit;
    }



    /**
     * Get all the versions for the specified view id, ordered by modification time.
     * @param integer $id
     * @param integer $limit default from global parameter
     * @param integer $offset default 0
     * @return array
     */

    public function findByViewIdLimit($id, $limit = NULL, $offset = 0) {

        $limit = (!empty($limit)) ? $limit : $this->limit;

        return $this->createQueryBuilder('v')
            ->where('v.viewId = :id')
            ->orderBy('v.timeMod', 'DESC')
            ->setParameter('id', $id)
            ->setFirstResult($offset)
            ->setMaxResults($limit)
            ->getQuery()
            ->getResult();
    }

}

添加服务:

1
2
3
4
5
6
7
8
gutensite_cms.view_version_repository:
    class: Gutensite\\CmsBundle\\Entity\\View\\ViewVersionRepository
    factory_service: 'doctrine.orm.default_entity_manager'
    factory_method: 'getRepository'
    arguments:
        - 'Gutensite\\CmsBundle\\Entity\\View\\ViewVersion'
    calls:
        - [setLimit, ['%cms.limit.list.admin%']]

这将导致错误,并抱怨factory_service定义:

1
You have requested a non-existent service"doctrine.orm.default_entity_manager". Did you mean one of these:"doctrine.orm.cms_entity_manager","doctrine.orm.billing_entity_manager"?

幸运的是,如果我将factory_service更改为建议的doctrine.orm.cms_entity_manager,它将起作用。有人可以解释为什么吗?

但是随后我又收到另一个错误,该错误与存储库中不存在的方法有关(因为存储库已损坏)。我以为在服务定义中包含参数,这意味着我需要向ViewVersionRepository添加__construct($viewVersion)方法以接受参数列表。但是,这导致了一个令人讨厌的错误,破坏了存储库。所以我删除了它,因为显然这必须在默认的Symfony EntityRepository中(我应该怎么知道?)。我确实保留了一个自定义setLimit()方法,用于将全局参数传递给调用。

所以现在该服务可以工作了……但是似乎需要大量工作,只是为了访问全局参数,如果没有参数传入该方法,则该全局参数应作为默认值。

在这种情况下,为什么我们不应该使用$ GLOBAL或配置文件中的常量来设置默认值?这不会破坏依赖关系模型,自定义变量仍可以传递到方法中,只有我们拥有全局应用范围的默认值。我不明白为什么对此不满意...


值得学习和理解如何创建存储库即服务。类似于:

1
2
3
4
5
6
7
8
view_version_repository:
    class:  My\\SomeBundle\\Entity\\ViewVersionRepository
    factory_service: 'doctrine.orm.default_entity_manager'
    factory_method:  'getRepository'
    arguments:  
        - 'My\\SomeBundle\\Entity\\ViewVersion'
    calls:
         - [setLimit, ['%limit_parameter%']]

在您的控制器中,您将执行以下操作:

1
$viewVersionRepository = $this->container->get('view_version_repository');

请参阅文档:http://symfony.com/doc/current/components/dependency_injection/factories.html

花费在学习如何使用服务上的努力将使自己获得很多倍的回报。


我个人使用了自定义配置类。您可以在任何需要的地方导入配置类-实体,存储库,控制器等。

要回答您的问题"为什么将其作为参数传递",只需研究依赖项注入模式即可。当您想长时间维护项目时,这确实是解决许多问题的一种灵活而酷炫的方法。