模型中的Symfony2 entityManager

时间:2011-02-10 04:22:49

标签: model-view-controller symfony doctrine entitymanager

我将在我的模型中使用entity_manager。但是entity_manager仅在控制器中可用:throw $em = $this->get('doctrine.orm.entity_manager')。所以,我必须使用$em参数定义模型方法。这使得phpUnit测试非常困难并且违反了应用程序结构。例如:

class Settings
{
    public static function getParam( $em, $key )
    {
        $em->createQuery("
            SELECT s
            FROM FrontendBundle:Settings s
            WHERE s.param = {$key}
        ");
        return $em->getResult();
    }
}

在模型部分中是否有使用entity_manager服务的方法?

2 个答案:

答案 0 :(得分:14)

首先,一个起始注释:按照惯例,你的Entity类应该是单数。所以,设置,而不是设置。您可以认为“设置”作为一组相关设置可以被视为一个实体。仍然需要记住一些事情。

在Doctrine2中,您将使用存储库来进行此类查询。在您打算调用Settings::getParam的代码中,您将获取存储库并进行查询。在symfony2中,说:

// $em is your entitymanager, as you were going to pass to your method above
// $key is the key you were going to pass to your method above
$repository = $em->getRepository('\FrontendBundle\Settings');
$setting = $repository->getByParam($key);

默认情况下,在不编写任何代码的情况下,存储库会为您实体中的每个字段定义getByXXXX。

如果要进行更复杂的查询,可以扩展存储库。

use Doctrine\ORM\EntityRepository;

class SettingsRepository extends EntityRepository 
{
    public function getBySomeComplicatedQuery() {
        $sort_order = $this->getEntityManager()
            ->createQuery('SELECT count(s) FROM FrontendBundle\Settings s WHERE s.value > 32')
            ->getResult(Query::HYDRATE_SINGLE_SCALAR);
    }

}

然后你会以同样的方式调用该方法。

其他人会提倡使用一个Manager对象,这个对象不会与Entity / ORM绑定,但我认为这是一个不必要的并发症。

Doctrine2专门设计为不允许您在实体文件中使用查询;实体和实体管理器实际上是标准模型层的两个方面,分开以实施最佳实践。请参阅此文章:http://symfony2basics.jkw.co.nz/get-symfony2-working/entities/

答案 1 :(得分:8)

实体类中的查询

将查询放入您的实体对我来说似乎很奇怪。与在Doctrine 1中将查询放入模型类的方式相同,这不是一个好习惯。实体类应该很轻。

我实际上正在学习Doctrine2并且正在考虑类似的问题:在哪里放置查询?

在Doctrine 1中有特殊的Table类,我在Doctrine 2中期待类似的东西。

存储库模式

今天我了解到Doctrine 2正在使用存储库模式:http://www.doctrine-project.org/docs/orm/2.0/en/reference/working-with-objects.html#custom-repositories

但是,要检索存储库类的实例,您需要使用实体管理器。无论如何,你需要它。

但是,遵循存储库模式似乎是更好的选择。

在我看来,如果你坚持在你的Entity类中使用查询方法,你必须将实体管理器传递给它。

<强>测试

为什么需要传递实体经理会让人难以测试?根据我的经验,显式依赖项使测试变得更容易,因为您可以在测试中控制它们(例如,模拟它们)。

另一方面,将实体管理器传递给每个方法也不是正确的选择。在这种情况下,我必须强制使用依赖项并将其添加到构造函数中。