phoenix
phoenix copied to clipboard
ORM Mapping - map from multiple directories
We need to add extra support to map entities from multiple directories, like this:
doctrine:
orm:
mappings:
default:
AcmeDemoBundle:
type: "annotation"
dir: ["Entity", "DefaultEntityImplementations"]
test:
AcmeDemoBundle:
type: "annotation"
dir: ["Entity", "TestEntityImplementations", "SomeOtherDirWIthEntities"]
because sometimes entities can be in different directories, but there is no support of this. This is a duplicate of the issue in the Symfony issues
If you look at the full config of a mapping, you will see that it is quite hard to support several folders: if they are in different folders, they are unlikely to have the same namespace prefix. And they won't be able to use the same namespace alias if they don't have the same prefix. This means that your proposal will be broken in most cases.
I have abstract entities and to test them (and how do they work with the repository) I need to create concrete entities, but only for test purposes (e.g. only test environment). If I will create my test folders inside default "Entity" directory they will be installed also inside dev environment, but I don't need it.
Using multiple directories seemed to me as I good idea, but if its hard to implement and use, then can you suggest how do I do in my case?
Workaround
- In extension define some param with path to your bundle
- In mappings use is_bundle: false and path with param prepended
Any updates on this?
I have a DDD style directory structure, and for example, i have one entity in the path App\Person\User\Domain\Model\User and another in the path App\Person\Employee\Domain\Model\Employee. So I decided to create a common directory (with common prefix as well):
$configurator->extension('doctrine', [
'orm' => [
'mappings' => [
'Person' => [
'is_bundle' => false,
'type' => 'xml',
'dir' => '%kernel.project_dir%/config/mapping/Person',
'prefix' => 'App\Person',
'alias' => 'Person'
],
//...
]
]
]);
And just specified the folders they are located in the name of the .orm.xml file.
User.Domain.Model.User.orm.xml
Employee.Domain.Model.Employee.orm.xml
If you don't choose a prefix, you should be able to navigate the entire src folder on the filename.
It's a hacky way of doing it, but it works quite well.
#Fixed!
Hi! I just tried to do the same:
doctrine:
orm:
entity_managers:
default:
mappings:
App:
is_bundle: false
type: attribute
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
FancyPants:
type: attribute
dir: '%kernel.project_dir%/src/Domain/FancyPants/Entity'
prefix: 'FancyPants\Entity'
alias: FancyPants
is_bundle: false
But the Entities in '%kernel.project_dir%/src/Domain/FancyPants/Entity' is not found when running bin/console doctrine:mapping:info.... Is any other config required?
For completness, I also have ApiPlatform operations on the same entities, and they work nicely:
api_platform:
mapping:
paths:
- '%kernel.project_dir%/src/Entity'
- '%kernel.project_dir%/src/Domain/FancyPants/Entity'
[EDIT] I also flushed all redis cache, and deleted var/cache just in case...
[EDIT2] Prefix must be the whole namespace, so changing it to prefix: 'App\Domain\FancyPants\Entity' solved my issue :) Leaving it here in case other stumbles upon it!
I'm also doing this on one of my projects like
doctrine:
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
Alias1:
dir: '%kernel.project_dir%/src/Namespace1/Entity
prefix: App\Namespace1\Entity
Alias2:
dir: '%kernel.project_dir%/src/Namespace2/Entity
prefix: App\Namespace2\Entity
So I don't think there is anything to be done here?
@dmaicher It's a maintenance nightmare with a DDD-like structure. Surely something could be done to ease the burden?
Workaround:
use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\DoctrineOrmMappingsPass;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
protected function build(ContainerBuilder $container): void
{
$this->registerMapping($container);
}
private function registerMapping(ContainerBuilder $container): void
{
$finder = Finder::create();
$finder
->in(__DIR__)
->name('Entity')
->directories()
;
$namespaces = [];
$directories = [];
foreach ($finder as $dir) {
$namespace = str_replace('/', '\\', sprintf('%s\%s', __NAMESPACE__, $dir->getRelativePathname()));
$namespaces[] = $namespace;
$directories[] = $dir->getPathname();
}
$container->addCompilerPass(DoctrineOrmMappingsPass::createAttributeMappingDriver(
$namespaces,
$directories,
));
}
}
I have a dream
mapping:
paths: [ '%kernel.project_dir%/src/*/Infrastructures/ApiMapping' ]
Maybe in ApiPlatform 4 ? ;)