huttopia/doctrine

为doctrine添加一些特性并修复bug,而不需要创建分支

1.3.2 2017-10-06 09:25 UTC

This package is auto-updated.

Last update: 2024-09-07 21:16:04 UTC


README

version symfony symfony symfony Lines Total Downloads

huttopia/doctrine

Doctrine是一个非常优秀的ORM,功能齐全,我们非常喜欢它!

但是,说实话,自2015年4月2日以来没有发布过任何主要版本(2.6已经发布,但现在bug太多),一些bug还没有修复,当你提交一个修复bug的PR时,创建补丁版本需要花费太多的时间。

因此,我们决定创建,以便修复我们需要的功能,而无需等待发布。我们还可以添加一些功能。

我们决定不创建Doctrine的分支,因为我们想跟随Doctrine的发布。现在创建分支可能很好,但两年后...

当我们需要覆盖一个类时,我们使用steevanb/composer-overload-class。当你需要这样做时,这是一个好方法,而不需要在所有地方重命名命名空间(我们不能,这不是一个分支;))。

变更日志

安装

将其添加到您的composer.json文件中

composer require huttopia/doctrine ^1.3.2

注册HuttopiaDoctrineBundle

# app/AppKernel.php

class AppKernel extends Kernel
{
    public function registerBundles(): array
    {
        $bundles = [
            new Huttopia\Doctrine\Bridge\Symfony3\HuttopiaDoctrineBundle()
        ];

        return $bundles;
    }
}

更改Doctrine配置

# app/config/config.yml

doctrine:
    orm:
        repository_factory: huttopia.doctrine.repository_factory
        default_repository_class: Huttopia\Doctrine\Orm\EntityRepository

配置

# app/config/config.yml

huttopia_doctrine:
    repository_factory_service: huttopia.doctrine.repository_factory # this is default value

Doctrine bugs

由于某些原因,Doctrine未修复或未修复的bug

  • fixed by steevanb/doctrine-events 使用extraUpdates修复Doctrine UnitOfwork的bug,这些更新在调用flush()之前添加和删除实体时不会被删除
  • #6042(未修复) getId()懒加载实体,如果getId()在trait中:未修复,只是为了提醒为什么我们不用trait来实现getId()
  • #6110(已修复) 清除 $this->collection 即使它为空,以重置键值
  • #6509(在此修复) PersistentCollection::clear() 和 removeElement() 与 orphanRemoval 一起会删除你的实体,即使你不想这样做

目前,我们修复了doctrine/orm依赖项的2.5.6版本:>2.5.6,2.6的标签错误(一些依赖项位于dev-master,没有版本),一些BC等。

当2.6版本经过更多测试时,我们将更改它。

作为服务存储库

是的,你也需要它;)存储库作为服务是最大的改进之一。

现在,我们可以使用huttopia.repository标签将您的存储库定义为服务

services:
    bar_repository:
        class: Foo\Repository\BarRepository
        arguments: ['@service', '%parameter%']
        tags:
            - { name: huttopia.repository, entity: Foo\Bar }

您需要在您的存储库中将 extends Doctrine\ORM\EntityRepository 改为 extends Huttopia\Doctrine\Orm\EntityRepository

请注意,我们的存储库移除了魔术方法(例如findOneById())。

但它添加了许多方法

  • getClassName(): string
  • getClassTableName(): string
  • createQueryBuilderWithoutSelect(string $alias, string $indexBy = null): QueryBuilder
  • get(int $id): Entity
  • getOneBy(array $criteria, array $orderBy = null): Entity
  • countAll(): int
  • countBy(array $params): int
  • findReadOnlyBy(array $criteria, array $fields = null, array $orderBy = null, $limit = null, $offset = null): array
  • getPartialReference(int $id)

find()和get(),以及findOneBy()和getOneBy()之间的区别:当实体不存在时,find()将返回null,而get()将抛出异常。

当您使用PARTIAL时,您可以使用createQueryBuilderWithoutSelect()而不是createQueryBuilder(),后者不会选择所有根实体字段。

删除单表继承中的无用的discriminator

对于SINGLE_TABLE_INHERITANCE实体,Doctrine会在所有SQL查询中添加discriminator列。

但是,如果您想查询所有实体,Doctrine 会添加不必要的 WHERE 子句,带有鉴别器:这并不利于性能;)

Huttopia\Doctrine\SqlWalker\IgnoreDiscriminator 修改了 Doctrine SqlWalker,仅在需要时添加 WHERE 子句。

为单个查询添加它

use Huttopia\Doctrine\SqlWalker\IgnoreDiscriminator

$queryBuilder
    ->getQuery()
    ->setHint(Query::HINT_CUSTOM_OUTPUT_WALKER, IgnoreDiscriminator::class);

为所有查询添加它

# app/AppKernel.php

class AppKernel
{
    public function boot(): void
    {
        parent::boot();

        foreach ($this->getContainer()->get('doctrine')->getManagers() as $manager) {
            if ($manager instanceof EntityManagerInterface) {
                $manager->getConfiguration()->setDefaultQueryHint(
                    Query::HINT_CUSTOM_OUTPUT_WALKER,
                    IgnoreDiscriminator::class
                );
            }
        }
    }
}

#6509 修复 PersistentCollection 的 orphanRemoval 管理

当您在 PersistentCollection 上调用 remove()removeElement()clear(),并且您的 manyToOne 配置将 orphanRemoval 设置为 true 时,PersistentCollection 将将您删除的实体添加到 UnitOfWork::$orphanRemovals 中。

flush() 将读取 UnitOfWork::$orphanRemovals,并删除所有实体,尽管它们被删除后又被添加。

因此,如果您删除一个实体,然后再次添加它,然后 flush(),最终,您的实体将被删除。

为了修复它,我们覆盖了 PersistentCollection,并在将实体添加到 PersistentCollection 时取消孤儿删除的调度。

请参阅 ComposerOverloadClass 安装

覆盖 PersistentCollection 来修复它

{
    "extra": {
        "composer-overload-class": {
            "Doctrine\\ORM\\PersistentCollection": {
                "original-file": "vendor/doctrine/orm/lib/Doctrine/ORM/PersistentCollection.php",
                "overload-file": "vendor/huttopia/doctrine/ComposerOverloadClass/Orm/PersistentCollection.php",
                "replace": true
            }
        }
    }
}

启用 steevanb/doctrine-events

它将替换 EntityManager,以添加一些事件:onCreateEntityOverrideLocalValues、onCreateEntityDefineFieldValues、onNewEntityInstance 等。

请参阅 安装 以进行安装。

启用 steevanb/doctrine-entity-merger

当您在 DQL 中使用 PARTIAL 时,您只检索所需的字段,而不是所有实体字段。

但是,如果您对同一实体执行 2 个 PARTIAL,但字段不同,最终实体将不会包含第二个 PARTIAL 的数据,只有第一个被填充。

请参阅 安装 以进行安装。

启用 steevanb/doctrine-read-only-hydrator

请参阅 基准测试,您将了解为什么我们使用 ReadOnlyHydrator;)

请参阅 安装 以进行安装。

启用 steevanb/doctrine-stats

steevanb/doctrine-stats 添加了大量关于查询、填充时间、延迟加载实体等的统计信息。

请参阅 安装 以进行安装。