I have an independent Symfony bundle (installed with Composer) with entities and repositories to share between my applications that connect same database.
Entities are attached to every applications using configuration (yml shown):
doctrine:
orm:
mappings:
acme:
type: annotation
dir: %kernel.root_dir%/../vendor/acme/entities/src/Entities
prefix: Acme\Entities
alias: Acme
Well, it was the easiest way to include external entities in application, but looks a bit ugly.
Whenever I get repository from entity manager:
$entityManager->getRepository('Acme:User');
I get either preconfigured repository (in entity configuration) or default Doctrine\ORM\EntityRepository
.
Now I want to override bundled (or default) repository class for a single entity. Is there any chance to do it with some configuration/extension/etc?
I think, the best looking way is something like:
doctrine:
orm:
....:
Acme\Entities\User:
repositoryClass: My\Super\Repository
Or with tags:
my.super.repository:
class: My\Super\Repository
tags:
- { name: doctrine.custom.repository, entity: Acme\Entities\User }
The easiest way to "override" a bundle's routing is to never import it at all. Instead of importing a third-party bundle's routing, copy that routing file into your application, modify it, and import it instead.
A Symfony bundle is a collection of files and folders organized in a specific structure. The bundles are modeled in such a way that it can be reused in multiple applications. The main application itself is packaged as a bundle and it is generally called AppBundle.
You can use LoadClassMetadata event:
class LoadClassMetadataSubscriber implements EventSubscriber
{
/**
* @inheritdoc
*/
public function getSubscribedEvents()
{
return [
Events::loadClassMetadata
];
}
/**
* @param LoadClassMetadataEventArgs $eventArgs
*/
public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
{
/**
* @var \Doctrine\ORM\Mapping\ClassMetadata $classMetadata
*/
$classMetadata = $eventArgs->getClassMetadata();
if ($classMetadata->getName() !== 'Acme\Entities\User') {
return;
}
$classMetadata->customRepositoryClassName = 'My\Super\Repository';
}
}
Doctrine Events
Entities are attached to every applications using configuration (yml shown): Well, it was the easiest way to include external entities in application, but looks a bit ugly.
You can enable auto_mapping
In addition to Artur Vesker answer I've found another way: override global repository_factory
.
config.yml:
doctrine:
orm:
repository_factory: new.doctrine.repository_factory
services.yml:
new.doctrine.repository_factory:
class: My\Super\RepositoryFactory
Repository Factory:
namespace My\Super;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Repository\DefaultRepositoryFactory;
class RepositoryFactory extends DefaultRepositoryFactory
{
/**
* @inheritdoc
*/
protected function createRepository(EntityManagerInterface $entityManager, $entityName)
{
if ($entityName === Acme\Entities\User::class) {
$metadata = $entityManager->getClassMetadata($entityName);
return new ApplicationRepository($entityManager, $metadata);
}
return parent::createRepository($entityManager, $entityName);
}
}
No doubt implementing LoadClassMetadataSubscriber
is a better way.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With