Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ODM double properties for ORM mapping #750

Closed
ghost opened this issue Jun 17, 2013 · 14 comments
Closed

ODM double properties for ORM mapping #750

ghost opened this issue Jun 17, 2013 · 14 comments
Labels

Comments

@ghost
Copy link

ghost commented Jun 17, 2013

Hi,

This is not a bug but a possible improvement :

  • I have a User Document who has a Customer Entity reference. Code is like this :

    /**
     * @var Customer
     * @Gedmo\ReferenceOne(type="entity", class="Customer", identifier="customerId")
     */
    protected $customer;
    
    /**
     * @ODM\Field(type="int")
     */
    protected $customerId;
    

I don't understand why i have to create two properties for that. When i set $customer, i have to set $customerId with the good value to avoid difference. The plugin should be able to map $customer with mongo property customerId without use document property $customerId. Same working as native orm mapping :)

I repeat me : it's not critical, it's perhaps hard to do, but i think it's better.

Thanks

@stof
Copy link
Contributor

stof commented Jun 17, 2013

The difference is that you have a mapped field stored in mongo (customerId), which need to exist in your class so that the Doctrine ODM can track it, and a different property for the object fetched on load by the extensions.

Doing cross-data-mapper references cannot be achieved exactly like references handled by the data-mapper itself. It would require to implement hooks deep inside Doctrine loading and change-tracking logic (which would be a huge performance killer for something used only in a few specific use cases)

@webdevilopers
Copy link

I tried your code @Devlopnet . But persisting the Document does not set the mapped field.

I guess I am missing some kind of configuration to make my server aware of the reference extension resp. listener. Can you help me @stof ?

@webdevilopers
Copy link

Here is my full example using the Gedmo\ReferenceOne annotation:

Is any PR related to this issue and able to solve it resp. call the preUpdate event even though a non-odm-mapped field is updated?

@rewotec
Copy link

rewotec commented Oct 9, 2015

👍

@stof
Copy link
Contributor

stof commented Oct 9, 2015

@webdevilopers no it cannot. Doctrine only looks at mapped fields to decide whether the event listener is called or not when flushing

@webdevilopers
Copy link

About your answer here @stof : #750 (comment)

I'm currently maintaining a project strictly following Domain Model policy in Domain-driven design.
The prototypes of the Domain Model don't care about persistence when being written.
That's why adding an additional field like customerId instead of keeping customer only feels like polluting the Domain Model.

Is it possible to use a Listener in these cases that could indeed work with the same field?
E.g. customer is an integer ODM field but when calling getCustomer() or customer() the listener returns the object?

@webdevilopers
Copy link

As you can see @stof I was able to create a listener that uses the same field $customer for storing the customerId and for mapping the Customer Entity.

Though this works if I understand you right this will cause problems when persisting changes?
#750 (comment)

@stof
Copy link
Contributor

stof commented Apr 26, 2016

@webdevilopers using the same property is a bad idea, as the ORM will see a change in the property. Having the same property storing 2 different data over time is not a clean design

@webdevilopers
Copy link

Of course that makes sense @stof. Not sure if you had the time to follow our discussion here:
webdevilopers/php-ddd#2 (comment)

I guess then the only alternative is to use some kind of Doctrine Wrapper around clean DomainModels. What are your thoughts on this? Feel free to join on the related issue. Thanks in advance!

@stof
Copy link
Contributor

stof commented Apr 26, 2016

@webdevilopers another solution would be to design your model in a way acknowledging that customers and orders live in different stores and so cannot be accessed from each other directly. Your order would then contain a customerId property holding a CustomerId value object (which is just wrapping an id or a uuid or whatever else you want), and then code wanting to get full info about the customer would ask the customer repository to give it the customer for this id.
This would avoid the need to blend the ORM and the ODM entirely, which cannot be fully hidden.

In the case you describe in the issue, I may even have a Customer object in the order, which would be responsible for holding the customer from the PoV of the order context, i.e. the id I talked above as well as the address and name stored in mongo (the historical data), as this is really a Customer object here, which is different from the one you have in mysql (even if they share an id linking them together).

@webdevilopers
Copy link

I see @stof we have similar ideas of different approaches. My first workaround indeed was using embedOne references taking a snapshot / historical data of the Customer including the billingAddress for instance:
webdevilopers/php-ddd#2 (comment)

The Document was then called OrderCustomer and would become an own Aggregate with the CustomerId value object.

I'm still afraid of a "native" call / use case on a DomainModel where the Developer expects a simple "getter" to work w/o any repository involved. Hard to explain.

@webdevilopers
Copy link

webdevilopers commented Apr 26, 2016

For instance a simple DomainModel native method call $customer->orders() would work if both were Doctrine ORM mapped Entities but not if the Orders would come from ODM, right?

P.S. @stof :
Do you have an example of a working XML mapping for Gedmo References? I never got it working on the Document side - don't know if the XML mapping is complete anyway:

http://atlantic18.github.io/DoctrineExtensions/schemas/orm/doctrine-extensions-3.0.xsd

namespace Acme\AppBundle\Entity;

class Customer
{
    /**
     * @Gedmo\ReferenceMany(type="document", class="Acme\DomainModel\Order", mappedBy="customer")
     */
    private $orders;
}
        <field fieldName="customerId" type="integer" />
        <gedmo:reference type="entity"
             class="Acme\AppBundle\Entity\Customer"
             inversed-by="orders" identifier="customerId" />
namespace Acme\DomainModel;

class Order
{
    private $customer;
    private $customerId;
}

@svscorp
Copy link

svscorp commented Nov 7, 2016

@stof @webdevilopers

What would be an analog for ReferenceMany in case a document has many ORM entities relation?

Not sure if it should look like this (doesn't work)

// class product

    /**
     * @Gedmo\ReferenceMany(type="entity", class="Category", inversedBy="products", identifier="categoryIds")
     */
    protected $categories;

    /**
     * @MongoDB\Collection
     */
    protected $categoryIds = array();

Is there a way you can tell doctrine to load referenced ORM collection?

@github-actions
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants