模型中的Symfony2 entityManager

Ale*_*kin 11 model-view-controller doctrine entitymanager symfony

我将在我的模型中使用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();
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有在模型部分使用entity_manager服务的方法?

Jer*_*rne 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);
Run Code Online (Sandbox Code Playgroud)

默认情况下,无需编写任何代码,存储库会为实体中的每个字段定义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);
    }

}
Run Code Online (Sandbox Code Playgroud)

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

其他人会提倡使用一个Manager对象,然后该对象不会与Entity/ORM绑定,但我认为这是一个不必要的复杂问题.

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


Jak*_*las 8

实体类中的查询

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

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

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

存储库模式

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

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

仍然,遵循存储库模式似乎是一个更好的选择.

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

测试

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

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