【问题标题】:Difference between $em->find(..) and $em->getRepository(..)->find(..)$em->find(..) 和 $em->getRepository(..)->find(..) 之间的区别
【发布时间】:2015-10-03 03:49:53
【问题描述】:

有实体

/**
 * @ORM\Entity(repositoryClass="Some\Namspace\CustomRepository")
 * @ORM\Table(name="image_type")
 */
class MyEntity{...}

并且 CustomRepository 扩展了 EntityRepository 以覆盖一些方法,例如 findfindAll

文档说:

// $em instanceof EntityManager
$user = $em->find('MyProject\Domain\User', $id);

本质上,EntityManager#find() 只是以下操作的快捷方式:

$user = $em->getRepository('MyProject\Domain\User')->find($id);

link:doctrine-orm.readthedocs.org

但我的 CustomRepository 仅适用于 $em->getRepository('Entities\MyEntity')->find($id)

使用$em->find('Entities\MyEntity',$id); 忽略我在CustomRepository 中覆盖的方法


  • 这是一个错误吗?
  • 或者这种结构之间有区别?
  • 如何在不覆盖 EntityManager 的情况下覆盖我的实体的 find,finAll,... 方法?

编辑 (1)

使用作曲家:

"require": {
    "doctrine/orm": "~2.4"
},

find代码:

public function find($entityName, $id, $lockMode = null, $lockVersion = null)
{
    $class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));

    if ( ! is_array($id)) {
        if ($class->isIdentifierComposite) {
            throw ORMInvalidArgumentException::invalidCompositeIdentifier();
        }

        $id = array($class->identifier[0] => $id);
    }
    ........... other ~100 lines
}

【问题讨论】:

    标签: php symfony orm doctrine-orm


    【解决方案1】:

    在学说 2.2 中,它似乎没有任何不同 - 实际上只是 getRepository()->find() 的传递/捷径

    http://www.doctrine-project.org/api/orm/2.2/source-class-Doctrine.ORM.EntityManager.html#348

    public function find($entityName, $identifier, $lockMode = LockMode::NONE, $lockVersion = null)
    {
        return $this->getRepository($entityName)->find($identifier, $lockMode, $lockVersion);
    }
    

    想法:

    • 什么版本的学说?
    • 您是否有自定义的 EntityManager?

    【讨论】:

    • 使用 composer: "require": {"doctrine/orm": "~2.4"},得到其他代码(我会马上更新我的问题)
    • Doctrine ORM =2.3 的代码不同,但基本上它反转了行为,使其由 EntityManager 而不是 repo 完成。
    【解决方案2】:

    注意:此处解释的行为适用于 Doctrine ORM 2.3+。 在 2.2 及之前的版本中,它是“反向”的。

    这是一个错误吗?

    不,这只是在不加载存储库的情况下“更快”使用实体管理器的一种方式。但在后面,存储库会加载 EntityManager 来执行find 方法。

    或者这两种结构之间有区别?

    表演,也许,但实际上可能需要一个替补席。 但基本上,它完全一样

    $em->find(...) 做了什么: 按主键加载单个实体。

    $em->getRepository(...)->find(...) 做了什么:
    它运行:return $this->_em->find($this->_entityName, $id, $lockMode, $lockVersion);.
    所以它加载了$em->find(...) 方法。
    所以它是一样的:)

    如何在不覆盖 EntityManager 的情况下覆盖我的实体的 find,findAll, ... 方法?

    为每个实体创建一个自定义存储库。

    如果您对每个实体执行此操作,则必须在“@Entity”注释中添加“repositoryClass”选项,并在其中指定 Repository 类,这样您就可以仅覆盖每个方法这个实体。

    See the docs to know more about custom repository use

    您也可以在全局范围内执行此操作。创建您自己的 EntityRepository,使其扩展 Doctrine\ORM\EntityRepository 类,您可以覆盖不同的功能。
    这是一个 EntityRepository 的示例,它在 Orbitale/ToolsBundle:BaseEntityRepository.php 上覆盖了 Doctrine 的默认存储库,但如果您想这样做,您必须更改 ORM 配置中的“默认存储库类名称”。

    您不必重写 EntityManager,它的功能足够强大,可以直接按原样使用,并且它在内部执行了许多在重写它时做模糊的事情时不应该被破坏的事情。

    【讨论】:

    • 我正在使用RepositoryClass 并且不想更改基础存储库类名称。只想使用我自己的 EntityManager find,... 方法。这个问题是指我的另一个问题,我正在尝试解决我的问题:link
    • 你想在EntityManager::find 方法中覆盖什么样的东西?基本上你应该能够在存储库中做到这一点。如果您想为每个存储库执行此操作,请通过创建自定义实体存储库并覆盖doctrine: { orm: { default_repository_class: "" } } yml 参数来全局执行此操作
    • 在上面的链接中,我正在制作库,该库可以使用库中的MappedSuperclass 扩展用户定义的实体。 MappedSuperclass 命名为 GraphNode,提供图中节点之间的连接。我想创建使用节点和链接的简单方法,所以我不知道用户 EntityManager::find()EntityManager::getRepository()::find() 使用什么方法,但我需要覆盖方法 find 和其他方法来预加载所有图形数据和链接在从 EntityManager 或我的自定义存储库返回用户实体之前,相互节点以获得更好的性能。
    猜你喜欢
    • 2011-03-20
    • 2013-07-07
    • 2015-08-19
    • 1970-01-01
    • 2014-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-14
    相关资源
    最近更新 更多