Skip to main content
  1. About
  2. For Teams
Asked
Viewed 32k times
31

I am wondering if it is possible to create a relationship between two entities that reside in separate databases.

For example if we took the solution found here http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html and created a one to many relationship with Users in the customer database to Posts in the default database.

Is this something that is supported by Symfony2 and Doctrine?

2 Answers 2

56

Using different object managers (entity managers) doesn't allow the object graphs to intersect. That case is too complex and isn't managed by Doctrine ORM.

If you need such a case, keep the object graphs disconnected by saving the identifiers of the related objects (old style) instead of a reference to them, then manually get the objects through services. You can find a fairly good example of how this would work in an example of connection between Doctrine2 ORM and Doctrine2 MongoDB ODM. Alternatively, you could also use a @PostLoad event listener that populates data in your entities by creating the link through the repositories I've linked in the example. Same for @PostPersist (which should instead extract the identifiers for the related objects), but beware that this technique can become really messy.

Also, if your RDBMS supports cross-database operations on a single host, you can just use a single EntityManager and reference the other table with @ORM\Table(name="schemaname.tablename").

Sign up to request clarification or add additional context in comments.

if your RDBMS supports cross-database operations on a single host, you can just use a single EntityManager and reference the other table. Excellent advice. Thanks!
Found out that Doctrine only detects schema changes in the default_connection tables, when using only one entity manager and multiple databases. Any idea to workaround this?
@noisebleed from the docs: $ php app/console doctrine:schema:update --force --em=customer. read more here: symfony.com/doc/current/cookbook/doctrine/…
@DonCallisto there is no newer approach, as far as I know.
Yes, the "Table" annotation has a "schema" attribute since a few minor version of the ORM
4

This is very old question, but it is still linked by Symfony (now 6.2), so I will give it quick update as this cost me about month of fighting with two entities due to its impreciseness.

The solution to all my problems was this little thing:

#[ORM\Table(schema: 'name_of_database')]

add this attribute to your entity and voilà - it will now use this database name when generating SQL query for this entity. But this is basically hardcoding the name of database for this entity - it won't change in different environments (for example on tests or different setup).

To fix this I've added new listener to Doctrine event loadClassMetadata, which changes schema for selected entities when env variable is changes to test:

namespace App\EventListener;

use Doctrine\Bundle\DoctrineBundle\Attribute\AsDoctrineListener;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Events;

#[AsDoctrineListener(event: Events::loadClassMetadata, priority: 500)]
class DoctrineListener
{
    public function loadClassMetadata(LoadClassMetadataEventArgs $event): void
    {
        if ('test' !== ($_ENV['APP_ENV'] ?? false)) {
            return;
        }

        $meta = $event->getClassMetadata();
        if (property_exists($meta, 'table') && isset($meta->table['schema'])) {
            $meta->table['schema'] .= '_test';
        }

        if (!property_exists($meta, 'associationMappings')) {
            return;
        }

        // ManyToMany tables
        foreach ($meta->associationMappings as $i => $associationMapping) {
            if (!isset($associationMapping['joinTable']['schema'])) {
                continue;
            }

            $meta->associationMappings[$i]['joinTable']['schema'] .= '_test';
        }
    }
}

With this you could also have dynamic schema - change per setup if needed. Hope it helps.

Comments

Your Answer

Draft saved
Draft discarded

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.

lang-php
Morty Proxy This is a proxified and sanitized view of the page, visit original site.