Persisting entities with cross-schema relationships between multiple entity managers #5472

Closed
opened 2026-01-22 15:08:32 +01:00 by admin · 31 comments
Owner

Originally created by @brandinchiu on GitHub (Mar 20, 2017).

Originally assigned to: @Ocramius on GitHub.

I am looking for any up-to-date documentation on Doctrine ORM's ability to handle cross-schema relationships between entities. This currently doesn't appear to be possible, as the entity manager of the persisting entity does not understand the state of entity being managed by the other manager.

This leads to confusing states where an ORMInvalidArgumentException is thrown (due to an unfulfilled cascade), or a MySQL unique constraint fails (Doctrine tries to persist the related entity, but it's clearly already in the DB).

Is there a specific way to handle this via Doctrine config, or is this still an unsupported feature?

Will it ever be a supported feature, or is there an official stance Doctrine has on this use-case?

Thanks!

Originally created by @brandinchiu on GitHub (Mar 20, 2017). Originally assigned to: @Ocramius on GitHub. I am looking for any up-to-date documentation on Doctrine ORM's ability to handle cross-schema relationships between entities. This currently doesn't appear to be possible, as the entity manager of the persisting entity does not understand the state of entity being managed by the other manager. This leads to confusing states where an ORMInvalidArgumentException is thrown (due to an unfulfilled cascade), or a MySQL unique constraint fails (Doctrine tries to persist the related entity, but it's clearly already in the DB). Is there a specific way to handle this via Doctrine config, or is this still an unsupported feature? Will it _ever_ be a supported feature, or is there an official stance Doctrine has on this use-case? Thanks!
admin added the Won't FixCan't FixQuestion labels 2026-01-22 15:08:32 +01:00
admin closed this issue 2026-01-22 15:08:33 +01:00
Author
Owner

@Ocramius commented on GitHub (Mar 21, 2017):

Sharing entities across multiple EntityManager instances is not supported,
and will need a separate managed entity copy instead.

On 20 Mar 2017 19:11, "Brandin Chiu" notifications@github.com wrote:

I am looking for any up-to-date documentation on Doctrine ORM's ability to
handle cross-schema relationships between entities. This currently doesn't
appear to be possible, as the entity manager of the persisting entity does
not understand the state of entity being managed by the other manager.

This leads to confusing states where an ORMInvalidArgumentException is
thrown (due to an unfulfilled cascade), or a MySQL unique constraint fails
(Doctrine tries to persist the related entity, but it's clearly already in
the DB).

Is there a specific way to handle this via Doctrine config, or is this
still an unsupported feature?

Will it ever be a supported feature, or is there an official stance
Doctrine has on this use-case?

Thanks!


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/doctrine/doctrine2/issues/6350, or mute the thread
https://github.com/notifications/unsubscribe-auth/AAJakKKAt-HQR41SnwAi6NeAeN6giG2Aks5rnsEzgaJpZM4Mi0AR
.

@Ocramius commented on GitHub (Mar 21, 2017): Sharing entities across multiple EntityManager instances is not supported, and will need a separate managed entity copy instead. On 20 Mar 2017 19:11, "Brandin Chiu" <notifications@github.com> wrote: > I am looking for any up-to-date documentation on Doctrine ORM's ability to > handle cross-schema relationships between entities. This currently doesn't > appear to be possible, as the entity manager of the persisting entity does > not understand the state of entity being managed by the other manager. > > This leads to confusing states where an ORMInvalidArgumentException is > thrown (due to an unfulfilled cascade), or a MySQL unique constraint fails > (Doctrine tries to persist the related entity, but it's clearly already in > the DB). > > Is there a specific way to handle this via Doctrine config, or is this > still an unsupported feature? > > Will it *ever* be a supported feature, or is there an official stance > Doctrine has on this use-case? > > Thanks! > > — > You are receiving this because you are subscribed to this thread. > Reply to this email directly, view it on GitHub > <https://github.com/doctrine/doctrine2/issues/6350>, or mute the thread > <https://github.com/notifications/unsubscribe-auth/AAJakKKAt-HQR41SnwAi6NeAeN6giG2Aks5rnsEzgaJpZM4Mi0AR> > . >
Author
Owner

@brandinchiu commented on GitHub (Mar 21, 2017):

@Ocramius: could you point me in the direction of how I would accomplish this?

@brandinchiu commented on GitHub (Mar 21, 2017): @Ocramius: could you point me in the direction of how I would accomplish this?
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

If you never did this before, you can edit the files directly from the
github UI and send them back for inclusion in our repository.

On 21 Mar 2017 2:06 p.m., "Brandin Chiu" notifications@github.com wrote:

@Ocramius https://github.com/Ocramius: could you point me in the
direction of how I would accomplish this?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/doctrine/doctrine2/issues/6350#issuecomment-288072105,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAJakJnitXTx5lsaUnRws8ESolVUe3ueks5rn8tJgaJpZM4Mi0AR
.

@Ocramius commented on GitHub (Mar 22, 2017): If you never did this before, you can edit the files directly from the github UI and send them back for inclusion in our repository. On 21 Mar 2017 2:06 p.m., "Brandin Chiu" <notifications@github.com> wrote: > @Ocramius <https://github.com/Ocramius>: could you point me in the > direction of how I would accomplish this? > > — > You are receiving this because you were mentioned. > Reply to this email directly, view it on GitHub > <https://github.com/doctrine/doctrine2/issues/6350#issuecomment-288072105>, > or mute the thread > <https://github.com/notifications/unsubscribe-auth/AAJakJnitXTx5lsaUnRws8ESolVUe3ueks5rn8tJgaJpZM4Mi0AR> > . >
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

My mistake, I thought this was existent functionality that I just wasn't utilising. My familiarity with the guts of Doctrine is pretty minimal, and I'm not sure how effective a PR from me would be -- but I'll take a gander and see what I can come up with.

@brandinchiu commented on GitHub (Mar 22, 2017): My mistake, I thought this was existent functionality that I just wasn't utilising. My familiarity with the guts of Doctrine is pretty minimal, and I'm not sure how effective a PR from me would be -- but I'll take a gander and see what I can come up with.
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

@brandinchiu you just need to replace that ::class with a string reference (FQN)

@Ocramius commented on GitHub (Mar 22, 2017): @brandinchiu you just need to replace that `::class` with a string reference (FQN)
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

I'm afraid I'm not clear on which ::class reference you are referring to.

@brandinchiu commented on GitHub (Mar 22, 2017): I'm afraid I'm not clear on which ::class reference you are referring to.
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

@brandinchiu urgh, sorry, totally mixed up. My replies should have gone to a different thread. Sorry! :-(

Backtracking a bit:

@Ocramius: could you point me in the direction of how I would accomplish this?

You would need to communicate across the separate entity managers via identifiers only:

$service1->doSomethingOnService2($service2, $someEntity);

Would translate to something like:

public function doSomethingOnService2(Service2 $service, SomeEntity $entity)
{
    $service->doSomething($entity->someId());
}
@Ocramius commented on GitHub (Mar 22, 2017): @brandinchiu urgh, sorry, totally mixed up. My replies should have gone to a different thread. Sorry! :-( Backtracking a bit: > @Ocramius: could you point me in the direction of how I would accomplish this? You would need to communicate across the separate entity managers via identifiers only: ```php $service1->doSomethingOnService2($service2, $someEntity); ``` Would translate to something like: ```php public function doSomethingOnService2(Service2 $service, SomeEntity $entity) { $service->doSomething($entity->someId()); } ```
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

In this example, are these services entity managers, or my own custom logic running on top of them? I already have something like this that is managing the entities on my end, the problems I'm running into are at the last leg, when I need the entities persisted.

Fetching objects has been no problem, including the ones with the cross-schema relations.

I've played around with some changes to the underlying Doctrine code, and I've managed to get as far (in testing) as to prevent the EM1 from trying to cascade-persist the foreign entity from the other schema.

The problem I run into after that is that Entity1, managed by EM1, doesn't maintain the ID from Entity2(foreign)/EM2, even though EM1 knows about the entity. When it gets to the point where it needs to actually write Entity1, the foreign key is null. I haven't found an intelligent way to reconcile that yet, mostly because I'm still trying to figure out how Doctrine handles the in-memory storage of foreign entities.

@brandinchiu commented on GitHub (Mar 22, 2017): In this example, are these services entity managers, or my own custom logic running on top of them? I already have something like this that is managing the entities on my end, the problems I'm running into are at the last leg, when I need the entities persisted. Fetching objects has been no problem, including the ones with the cross-schema relations. I've played around with some changes to the underlying Doctrine code, and I've managed to get as far (in testing) as to prevent the EM1 from trying to cascade-persist the foreign entity from the other schema. The problem I run into after that is that Entity1, managed by EM1, doesn't maintain the ID from Entity2(foreign)/EM2, even though EM1 knows about the entity. When it gets to the point where it needs to actually write Entity1, the foreign key is null. I haven't found an intelligent way to reconcile that yet, mostly because I'm still trying to figure out how Doctrine handles the in-memory storage of foreign entities.
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

The problem I run into after that is that Entity1, managed by EM1, doesn't maintain the ID from Entity2(foreign)/EM2, even though EM1 knows about the entity. When it gets to the point where it needs to actually write Entity1, the foreign key is null. I haven't found an intelligent way to reconcile that yet, mostly because I'm still trying to figure out how Doctrine handles the in-memory storage of foreign entities.

I would need a piece of code that reproduces your issue in isolation to get you to a workaround. Can't help just by imagining what you are doing, sorry...

@Ocramius commented on GitHub (Mar 22, 2017): > The problem I run into after that is that Entity1, managed by EM1, doesn't maintain the ID from Entity2(foreign)/EM2, even though EM1 knows about the entity. When it gets to the point where it needs to actually write Entity1, the foreign key is null. I haven't found an intelligent way to reconcile that yet, mostly because I'm still trying to figure out how Doctrine handles the in-memory storage of foreign entities. I would need a piece of code that reproduces your issue in isolation to get you to a workaround. Can't help just by imagining what you are doing, sorry...
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

Of course; here's a more concrete example of what I'm attempting to do:

Assume I have 3 schemas:

  • data_1
  • data_2
  • data_index

data_1/2 are application databases storing relevant information for two clients. It stores user, financial, and other information for those clients.

data_index is an array of enum-like tables, which consist of ID->Name pairs. These are more or less non-transactional, static values. Things like roles, types, languages and countries.

My individual database servers will consist of multiple data_n schemas, and ideally, one data_index schema, shared across them.

The example I am currently working with is persisting new users to a data_n schema, which requires a valid role ID from data_index.role.

What I've attempted to do for testing is to introduce a new cascade option: ignore. I've modified the list of acceptable cascade parameters, and modified the foreach loop in UnitOfWork:735, to not compute association changes if $assoc['isCascadeIgnore'].

This obviously prevents entity manager managing *data_n.user * from trying to persist the role entity from the foreign schema. However, once the entity manager tries to actually persist the user, it confusingly doesn't know the role ID, even though Entity\User->getRole()->getId() is not null.

Would you like the actual compilation of my changes, or is this enough to suggest a course of action?

@brandinchiu commented on GitHub (Mar 22, 2017): Of course; here's a more concrete example of what I'm attempting to do: Assume I have 3 schemas: * data_1 * data_2 * data_index data_1/2 are application databases storing relevant information for two clients. It stores user, financial, and other information for those clients. data_index is an array of enum-like tables, which consist of ID->Name pairs. These are more or less non-transactional, static values. Things like roles, types, languages and countries. My individual database servers will consist of multiple data_n schemas, and _ideally_, **one** data_index schema, shared across them. The example I am currently working with is persisting new users to a data_n schema, which requires a valid role ID from data_index.role. What I've attempted to do for testing is to introduce a new cascade option: **ignore**. I've modified the list of acceptable cascade parameters, and modified the foreach loop in UnitOfWork:735, to not compute association changes if $assoc['isCascadeIgnore']. This obviously prevents entity manager managing *data_n.user * from trying to persist the role entity from the foreign schema. However, once the entity manager tries to actually persist the user, it confusingly doesn't know the role ID, even though Entity\User->getRole()->getId() is not null. Would you like the actual compilation of my changes, or is this enough to suggest a course of action?
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

I'm asking for an actual code example.

@Ocramius commented on GitHub (Mar 22, 2017): I'm asking for an actual code example.
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

Entity Metadata

MisfitPixel\Bundle\CoreBundle\Entity\User:
    type: entity
    table: user
    indexes:
        FKEY_user_status_id_idx:
            columns:
                - status_id
        FKEY_user_tier_id_idx:
            columns:
                - tier_id
        FKEY_user_role_id_idx:
            columns:
                - role_id
    uniqueConstraints:
        email_UNIQUE:
            columns:
                - email
...
manyToOne:
        role:
            targetEntity: Role
            cascade: [ "ignore" ]
            fetch: LAZY
            mappedBy: null
            inversedBy: null
            joinColumns:
                role_id:
                    referencedColumnName: id
            orphanRemoval: false
...

\Doctrine\ORM\Mapping\MappingException:776 (added new cascade option to exception message)

return new self(sprintf(
            "You have specified invalid cascade options for %s::$%s: %s; available options: 'remove', 'persist', 'refresh', 'merge', 'detach', and 'ignore'",
            $className,
            $propertyName,
            $cascades
        ));

\Doctrine\ORM\Mapping\ClassMetadataInfo:1517 (added new cascade option to array_intersect and added new mapping index 'isCascadeIgnore')

if (count($cascades) !== count(array_intersect($cascades, array('remove', 'persist', 'refresh', 'merge', 'detach', 'ignore')))) {
            throw MappingException::invalidCascadeOption(
                array_diff($cascades, array_intersect($cascades, array('remove', 'persist', 'refresh', 'merge', 'detach', 'ignore'))),
                $this->name,
                $mapping['fieldName']
            );
        }
...
$mapping['isCascadeIgnore'] = in_array('ignore',  $cascades);

\Doctrine\ORM\UnitOfWork:735 (prevent $this->computeAssociationChanges from running if isCascadeIgnore)

foreach ($class->associationMappings as $field => $assoc) {

            if (($val = $class->reflFields[$field]->getValue($entity)) === null) {
                continue;
            }

            if ($assoc['isCascadeIgnore']){
                continue;
            }
...
}

Is this better? Or do you want an actual PR?

@brandinchiu commented on GitHub (Mar 22, 2017): **Entity Metadata** ```yaml MisfitPixel\Bundle\CoreBundle\Entity\User: type: entity table: user indexes: FKEY_user_status_id_idx: columns: - status_id FKEY_user_tier_id_idx: columns: - tier_id FKEY_user_role_id_idx: columns: - role_id uniqueConstraints: email_UNIQUE: columns: - email ... manyToOne: role: targetEntity: Role cascade: [ "ignore" ] fetch: LAZY mappedBy: null inversedBy: null joinColumns: role_id: referencedColumnName: id orphanRemoval: false ... ``` **\Doctrine\ORM\Mapping\MappingException:776** (added new cascade option to exception message) ```php return new self(sprintf( "You have specified invalid cascade options for %s::$%s: %s; available options: 'remove', 'persist', 'refresh', 'merge', 'detach', and 'ignore'", $className, $propertyName, $cascades )); ``` **\Doctrine\ORM\Mapping\ClassMetadataInfo:1517** (added new cascade option to array_intersect and added new mapping index 'isCascadeIgnore') ```php if (count($cascades) !== count(array_intersect($cascades, array('remove', 'persist', 'refresh', 'merge', 'detach', 'ignore')))) { throw MappingException::invalidCascadeOption( array_diff($cascades, array_intersect($cascades, array('remove', 'persist', 'refresh', 'merge', 'detach', 'ignore'))), $this->name, $mapping['fieldName'] ); } ... $mapping['isCascadeIgnore'] = in_array('ignore', $cascades); ``` **\Doctrine\ORM\UnitOfWork:735** (prevent $this->computeAssociationChanges from running if isCascadeIgnore) ```php foreach ($class->associationMappings as $field => $assoc) { if (($val = $class->reflFields[$field]->getValue($entity)) === null) { continue; } if ($assoc['isCascadeIgnore']){ continue; } ... } ``` Is this better? Or do you want an actual PR?
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

No, I'm asking where you are sharing an entity reference... :-\

@Ocramius commented on GitHub (Mar 22, 2017): No, I'm asking where you are sharing an entity reference... :-\
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

Like, where I'm instantiating the user entity and then setting the role?

@brandinchiu commented on GitHub (Mar 22, 2017): Like, where I'm instantiating the user entity and then setting the role?
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

Yes: without going into ORM internals, how are you using the ORM API? Can you make an example that, using multiple entity managers, reproduces your issue?

@Ocramius commented on GitHub (Mar 22, 2017): Yes: without going into ORM internals, how are you using the ORM API? Can you make an example that, using multiple entity managers, reproduces your issue?
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

I'm working with Symfony, and have heavily abstracted out how I work with ORM. I work with controller classes that wrap around entities to provide functionality.

$user = new Core\Account\UserController();
$user->setEmail('brandinchiu@gmail.com')
    ->setTier(Core\Account\TierController::getDefaultTier())
    ->setRole(Core\Index\RoleController::getRole(Enum\Role::ROLE_USER))
    ->setPassword('plantextpassword')
    ->setFirstName('brandin')
    ->setLastName('chiu')
    ->setBirthdate(new \DateTime(date('Y-m-d', '1991-05-17')))
    ->save()
;

UserController::save() basically just runs $em->persist and $em->flush on the wrapped entity.

Core\Index\RoleController::getRole(Enum\Role::ROLE_USER) just returns an instance of RoleController with a preloaded $entity property based on the passed enum.

The UserController->setRole() method takes a RoleController and updates the underlying user entity with that of the RoleController:

public function setRole(Core\Index\RoleController $role)
   {
       $this->getEntity()->setRole($role->getEntity());

       return $this;
   }

UserController::__construct()

    public function __construct($entity = null)
    {
        $this->entityName = $this->getClass();
        $this->entityManager = $this->getContainer()->get('doctrine')->getManager($this->getControllerNamespace());

        /**
         * load the controller from an existing entity;
         * or set properties to null.
         */
        if($entity !== null){
            $this->setEntity($entity);

        } else {
            $this->setEntity($this->nullEntity());
        }
    }

UserController::getClass() returns the expected name of the user entity, in this case, User.
UserController::getControllerNamespace() returns the expected name of the entity manager, either 'index', or 'account'.
UserController::nullEntity() returns an instance of the entity above, with null properties.
UserController::set sets the underlying entity properties.

The result of the topmost section is a UserController, with a ..\Entity\User marked as new by UserController::getEntityManager(), with all the property values that were set above. If I dump UserController->getEntity()->getRole()->getId, I get the same value as Enum\Role::ROLE_USER.

This is the doctrine config:

doctrine:
    dbal:
        default_connection: index
        connections:
            index:
                driver:   pdo_mysql
                host:     "%database_host_index%"
                port:     "%database_port_index%"
                dbname:   "%database_name_index%"
                user:     "%database_user_index%"
                password: "%database_password_index%"
                charset:  UTF8
            account:
                driver:   pdo_mysql
                host:     "%database_host_account%"
                port:     "%database_port_account%"
                dbname:   "%database_name_account%"
                user:     "%database_user_account%"
                password: "%database_password_account%"
                charset:  UTF8

    orm:
        auto_generate_proxy_classes: "%kernel.debug%"
        default_entity_manager: account
        entity_managers:
            index:
                naming_strategy: doctrine.orm.naming_strategy.underscore
                auto_mapping: false
                connection: index
                mappings:
                    CoreBundle:
                        mapping: true
                        type: yml
                        dir: Resources/config/doctrine
                        prefix: CoreBundle\Entity
            account:
                naming_strategy: doctrine.orm.naming_strategy.underscore
                auto_mapping: true
                connection: account
                mappings:
                    CoreBundle:
                        mapping: true
                        type: yml
                        dir: Resources/config/doctrine
                        prefix: CoreBundle\Entity

I dunno how helpful this is to you ... unless you want me to dump my whole project somewhere for you to swim through ...

@brandinchiu commented on GitHub (Mar 22, 2017): I'm working with Symfony, and have heavily abstracted out how I work with ORM. I work with controller classes that wrap around entities to provide functionality. ```php $user = new Core\Account\UserController(); $user->setEmail('brandinchiu@gmail.com') ->setTier(Core\Account\TierController::getDefaultTier()) ->setRole(Core\Index\RoleController::getRole(Enum\Role::ROLE_USER)) ->setPassword('plantextpassword') ->setFirstName('brandin') ->setLastName('chiu') ->setBirthdate(new \DateTime(date('Y-m-d', '1991-05-17'))) ->save() ; ``` UserController::save() basically just runs $em->persist and $em->flush on the wrapped entity. Core\Index\RoleController::getRole(Enum\Role::ROLE_USER) just returns an instance of RoleController with a preloaded $entity property based on the passed enum. The UserController->setRole() method takes a RoleController and updates the underlying user entity with that of the RoleController: ```php public function setRole(Core\Index\RoleController $role) { $this->getEntity()->setRole($role->getEntity()); return $this; } ``` **UserController::__construct()** ```php public function __construct($entity = null) { $this->entityName = $this->getClass(); $this->entityManager = $this->getContainer()->get('doctrine')->getManager($this->getControllerNamespace()); /** * load the controller from an existing entity; * or set properties to null. */ if($entity !== null){ $this->setEntity($entity); } else { $this->setEntity($this->nullEntity()); } } ``` UserController::getClass() returns the expected name of the user entity, in this case, _User_. UserController::getControllerNamespace() returns the expected name of the entity manager, either _'index'_, or _'account'_. UserController::nullEntity() returns an instance of the entity above, with null properties. UserController::set<Foo> sets the underlying entity properties. The result of the topmost section is a UserController, with a ..\Entity\User marked as new by UserController::getEntityManager(), with all the property values that were set above. If I dump UserController->getEntity()->getRole()->getId, I get the same value as Enum\Role::ROLE_USER. This is the doctrine config: ```yaml doctrine: dbal: default_connection: index connections: index: driver: pdo_mysql host: "%database_host_index%" port: "%database_port_index%" dbname: "%database_name_index%" user: "%database_user_index%" password: "%database_password_index%" charset: UTF8 account: driver: pdo_mysql host: "%database_host_account%" port: "%database_port_account%" dbname: "%database_name_account%" user: "%database_user_account%" password: "%database_password_account%" charset: UTF8 orm: auto_generate_proxy_classes: "%kernel.debug%" default_entity_manager: account entity_managers: index: naming_strategy: doctrine.orm.naming_strategy.underscore auto_mapping: false connection: index mappings: CoreBundle: mapping: true type: yml dir: Resources/config/doctrine prefix: CoreBundle\Entity account: naming_strategy: doctrine.orm.naming_strategy.underscore auto_mapping: true connection: account mappings: CoreBundle: mapping: true type: yml dir: Resources/config/doctrine prefix: CoreBundle\Entity ``` I dunno how helpful this is to you ... unless you want me to dump my whole project somewhere for you to swim through ...
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

unless you want me to dump my whole project somewhere for you to swim through ...

No, that's not going to be useful, but generally:

$entity = $em1->find(Foo::class, 123);
$em2->persist($entity);

Will lead to a mess (and just fail).

The result of the topmost section is a UserController, with a ..\Entity\User marked as new by UserController::getEntityManager(), with all the property values that were set above. If I dump UserController->getEntity()->getRole()->getId, I get the same value as Enum\Role::ROLE_USER.

Yes, but where is the entity passed across multiple entity managers? As far as I can see, your current controllers all work with one entity and one entity manager...

Is this the interaction?

   public function setRole(Core\Index\RoleController $role)
   {
       $this->getEntity()->setRole($role->getEntity());

       return $this;
   }
@Ocramius commented on GitHub (Mar 22, 2017): > unless you want me to dump my whole project somewhere for you to swim through ... No, that's not going to be useful, but generally: ```php $entity = $em1->find(Foo::class, 123); $em2->persist($entity); ``` Will lead to a mess (and just fail). > The result of the topmost section is a UserController, with a ..\Entity\User marked as new by UserController::getEntityManager(), with all the property values that were set above. If I dump UserController->getEntity()->getRole()->getId, I get the same value as Enum\Role::ROLE_USER. Yes, but where is the entity passed across multiple entity managers? As far as I can see, your current controllers all work with one entity and one entity manager... Is this the interaction? ```php public function setRole(Core\Index\RoleController $role) { $this->getEntity()->setRole($role->getEntity()); return $this; } ```
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

What's essentially happening is:

$user = new CoreBundle\Entity\User();
$role = $this->getContainer()->get('doctrine')->getRepository(CoreBundle:Role, 'index')->find($id);
$user->setRole($role);

$em1->persist($user);
$em1->flush();
@brandinchiu commented on GitHub (Mar 22, 2017): What's essentially happening is: ```php $user = new CoreBundle\Entity\User(); $role = $this->getContainer()->get('doctrine')->getRepository(CoreBundle:Role, 'index')->find($id); $user->setRole($role); $em1->persist($user); $em1->flush(); ```
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

Right, that's never going to happen. You will need to get a fresh copy of $role from $em1.

@Ocramius commented on GitHub (Mar 22, 2017): Right, that's never going to happen. You will need to get a fresh copy of `$role` from `$em1`.
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

Is this even possible? How can $em1 know about a Role when it points to a different database?

@brandinchiu commented on GitHub (Mar 22, 2017): Is this even possible? How can $em1 know about a Role when it points to a different database?
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

Then you need to break the association, and use a scalar field for that association:

$user->setRoleId($role->getId());
@Ocramius commented on GitHub (Mar 22, 2017): Then you need to break the association, and use a scalar field for that association: ```php $user->setRoleId($role->getId()); ```
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

So there's no reasonable way Doctrine would ever support this kind of behaviour?

Moving to a scalar, non-entity(object) relationship was the next thing on my list to try.

@brandinchiu commented on GitHub (Mar 22, 2017): So there's no reasonable way Doctrine would ever support this kind of behaviour? Moving to a scalar, non-entity(object) relationship was the next thing on my list to try.
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

So there's no reasonable way Doctrine would ever support this kind of behaviour?

No, you'd need a single EntityManager that connects to multiple DBs instead.

@Ocramius commented on GitHub (Mar 22, 2017): > So there's no reasonable way Doctrine would ever support this kind of behaviour? No, you'd need a single `EntityManager` that connects to multiple DBs instead.
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

And that's currently not possible, correct?

@brandinchiu commented on GitHub (Mar 22, 2017): And that's currently not possible, correct?
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

@brandinchiu depends on RDBMS. For instance, in Postgres/MySQL, you can span across different schema with a single DB connection.

Otherwise, an alternate solution is to write a Doctrine\DBAL\Connection class that is able to select which DB to send a query to, depending on the SQL statement. That is NOT a simple task (estimating weeks of work).

@Ocramius commented on GitHub (Mar 22, 2017): @brandinchiu depends on RDBMS. For instance, in Postgres/MySQL, you can span across different schema with a single DB connection. Otherwise, an alternate solution is to write a `Doctrine\DBAL\Connection` class that is able to select which DB to send a query to, depending on the SQL statement. That is NOT a simple task (estimating weeks of work).
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

I'm using MySQL. Can you point me in the direction of the documentation outlining how to configure a single entity manager to interact with two different databases/schema?

EDIT: or explain that here, if it's easier/faster.

@brandinchiu commented on GitHub (Mar 22, 2017): I'm using MySQL. Can you point me in the direction of the documentation outlining how to configure a single entity manager to interact with two different databases/schema? EDIT: or explain that here, if it's easier/faster.
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

@brandinchiu you can just use a single DB connection, and map the entities with @Table(name="foo", schema="bar")

@Ocramius commented on GitHub (Mar 22, 2017): @brandinchiu you can just use a single DB connection, and map the entities with `@Table(name="foo", schema="bar")`
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

How would I accomplish this with yaml configuration?

@brandinchiu commented on GitHub (Mar 22, 2017): How would I accomplish this with yaml configuration?
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

@brandinchiu no clue: see http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/yaml-mapping.html

@Ocramius commented on GitHub (Mar 22, 2017): @brandinchiu no clue: see http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/yaml-mapping.html
Author
Owner

@Ocramius commented on GitHub (Mar 22, 2017):

Closing here, as the issue is resolved.

@Ocramius commented on GitHub (Mar 22, 2017): Closing here, as the issue is resolved.
Author
Owner

@brandinchiu commented on GitHub (Mar 22, 2017):

I appreciate the assistance.

@brandinchiu commented on GitHub (Mar 22, 2017): I appreciate the assistance.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#5472