11

我将在我的模型中使用 entity_manager。但 entity_manager 仅在 controller: 中可用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 服务吗?

4

2 回答 2

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 对象,然后该对象不会与实体/ORM 绑定,但我认为在这种情况下这是不必要的复杂化。

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

于 2011-05-27T06:17:29.153 回答
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 类中使​​用查询方法,则必须将 Entity Manager 传递给它。

测试

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

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

于 2011-02-10T15:16:53.370 回答