2017 © Pedro Peláez
 

library doctrine

Add some features and fix to doctrine, without forking it

image

huttopia/doctrine

Add some features and fix to doctrine, without forking it

  • Friday, June 29, 2018
  • by huttopia
  • Repository
  • 4 Watchers
  • 0 Stars
  • 819 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 0 Forks
  • 0 Open issues
  • 13 Versions
  • 16 % Grown

The README.md

version symfony symfony symfony Lines Total Downloads, (*1)

huttopia/doctrine

Doctrine is a really good ORM, with nice features, we love it !, (*2)

But, to be honest, no major version since 2 april 2015 (2.6 is here, but too much bugs for now), several bugs are not fixed and it takes too much time to create patch version when you create a PR to fix something., (*3)

So, we decided to create huttopia/doctrine, to fix what we need, without waiting for a release. We can add features too., (*4)

We decide to not fork Doctrine, because we want to follow Doctrine releases. Forking it now is nice and amazing, but in 2 years..., (*5)

When we need to override a class, we do it with steevanb/composer-overload-class. That's a good way when you need it, without renaming namespace everywhere (we can't, that's not a fork ;))., (*6)

Changelog, (*7)

Installation

Add it to your composer.json :, (*8)

composer require huttopia/doctrine ^1.3.2

Register HuttopiaDoctrineBundle :, (*9)

# app/AppKernel.php

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

        return $bundles;
    }
}

Change Doctrine configuration :, (*10)

# app/config/config.yml

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

Configuration :, (*11)

# app/config/config.yml

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

Doctrine bugs

Bugs who are fixed or not fixed by Doctrine, for some reasons : - fixed by steevanb/doctrine-events Fix a Doctrine UnitOfwork bug with extraUpdates, who are not removed when you add and remove your entity before calling flush() - #6042 (not fixed) getId() lazy load entity if getId() is in trait : not fixed, just to remember why we don't use trait for getId() - #6110 (fixed) Clear $this->collection even when empty, to reset keys - #6509 (fixed here) PersistentCollection::clear() and removeElement() with orphanRemoval will remove your entity, although you don't want, (*12)

For now, we fix 2.5.6 for doctrine/orm dependency : >2.5.6 and 2.6 has wrong tag (some dependencies are on dev-master, whithout version), some BC etc., (*13)

We will change it when 2.6 will be more tested., (*14)

Repositories as service

Yes, you need it too ;) Repositories as service is one of the biggest improvement., (*15)

Now, we can define your repository as service, with huttopia.repository tag :, (*16)

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

You need to change extends Doctrine\ORM\EntityRepository by extends Huttopia\Doctrine\Orm\EntityRepository in your repositories., (*17)

Take care, our repository remove magic methods (findOneById() for example)., (*18)

But it add a lot of methods : - 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), (*19)

Difference between find() and get(), and findOneBy() and getOneBy() : when entity is not found, find() will return null, as get() will throw an exception., (*20)

When you use PARTIAL, you can call createQueryBuilderWithoutSelect() instead of createQueryBuilder(), who will not select all root entity fields., (*21)

Remove useless discriminator in SQL for single table inheritance

With SINGLE_TABLE_INHERITANCE entities, Doctrine add discriminator columns into all SQL queries., (*22)

But if you want to query all entities, Doctrine add useless WHERE clause with discriminator : not really good for performances ;), (*23)

Huttopia\Doctrine\SqlWalker\IgnoreDiscriminator override Doctrine SqlWalker, to add WHERE clause only when needed., (*24)

Add it for a single query :, (*25)

use Huttopia\Doctrine\SqlWalker\IgnoreDiscriminator

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

Add it for all queries :, (*26)

# 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 Fix PersistentCollection orphanRemoval management

When you call remove(), removeElement() or clear() on PersistentCollection, and your manyToOne configuration define orphanRemoval as true, PersistentCollection will add your deleted entity in UnitOfWork::$orphanRemovals., (*27)

flush() will read UnitOfWork::$orphanRemovals, and delete all entities, although they are deleted then added., (*28)

So, if you remove an entity, then add it again, then flush(), finally, your entity will be deleted., (*29)

To fix it, we override PersistentCollection, and unschedule orphanRemovals when we add entity to PersistentCollection., (*30)

See ComposerOverloadClass installation., (*31)

Override PersistentCollection to fix it :, (*32)

{
    "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
            }
        }
    }
}

Enable steevanb/doctrine-events

It will replace EntityManager, to add some events : onCreateEntityOverrideLocalValues, onCreateEntityDefineFieldValues, onNewEntityInstance etc., (*33)

See Installation to install it., (*34)

Enable steevanb/doctrine-entity-merger

When you use PARTIAL in DQL, you retrieve only fields you need, instead of all Entity fields., (*35)

But, if you execute 2 PARTIAL on same entity, but not same fields, your final entity will not have second PARTIAL data, only first one is hydrated., (*36)

See Installation to install it., (*37)

Enable steevanb/doctrine-read-only-hydrator

See Benchmark, you will understand why we use ReadOnlyHydrator ;), (*38)

See Installation to install it., (*39)

Enable steevanb/doctrine-stats

steevanb/doctrine-stats add lot of statistics about queries, hydration time, lazy loaded entities, etc., (*40)

See Installation to install it., (*41)

The Versions

24/05 2018

1.3.3

1.3.3.0

Add some features and fix to doctrine, without forking it

  Sources   Download

MIT

The Requires

 

The Development Requires

24/05 2018

dev-fork-doctrine-entity-merger

dev-fork-doctrine-entity-merger

Add some features and fix to doctrine, without forking it

  Sources   Download

MIT

The Requires

 

The Development Requires