-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
[WIP] Value objects #634
[WIP] Value objects #634
Conversation
… to make parsing work.
…lectionProxy object, bypassing changes to UnitOfWork, Persisters and Hydrators.
Hello, thank you for positing this Pull Request. I have automatically opened an issue on our Jira Bug Tracker for you with the details of this Pull-Request. See the Link: |
private $childProperty; | ||
private $class; | ||
|
||
public function __construct($parentProperty, $childProperty, $class) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should typehint the ReflectionProperty arguments
Does this implement still compare the embedded objects by reference or does it track changes in them ? |
@stof i didn't take care of change tracking yet. Currently it compares the values of the objects as if they were scalars on the |
I have to admit, that I skimmed through the code, but I didn't find how the object gets serialized. |
@mvrhov The object doesnt get serialized, there is a table "DDC93Person (id, name, street, zip, city)", that means the columns are in the person table. Doctrine 2.* will always be >= PHP 5.3.3, so no raising requirements here. |
@mvrhov If you want some JSON serialization, use a custom DBAL type for it, and no change in the ORM. The goal of embeddable is to store it in fields so that the queries can do what they want with the fields. |
I've already done that in the project I needed a historical data appended. |
@mvrhov It is not a separate table. It is extra fields in the table where you embed it. To store them in a separate table, use |
As discussed on IRC, I've patched up something to allow this version of embeddables to be used for identifiers: Ocramius/doctrine2@doctrine:ValueObjects...Ocramius:feature/vo-as-id It's just a PoC and I don't think it's clean, so for now I'm just pasting the link to the branch. EDIT: probably won't be included - I guess VOs as identifiers is not needed right now :) |
…L test with Object and Array Hydration.
@guilhermeblanco @FabioBatSilva anything? |
$persons = $this->_em->createQuery($dql)->getArrayResult(); | ||
|
||
foreach ($persons as $person) { | ||
$this->assertEquals('Tree', $person['address.street']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You think it's possible to hydrate as $person['address']['street']
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly. This is what I highlighted on previous comment. It'd be pretty hard to handle this on DQL parser and also hydrator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I doubt its much more to handle in DQL parser than the explicit approach, and as for hydrator, this is array hydration, the object hydration already works without a single change. I think we can argue that slightly complicating array hydration and in turn not even touching object hydration is a much better solution than changing everything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
$person['address']['street']
sounds much better.
It looks pretty good, I'd like to sugest |
@beberlei do you actually think this can be sneaked into 2.4 or is it way too risky? |
@Ocramius not in 2.4 - i want to find out the implications @FabioBatSilva |
How about just |
If @Embedded/@embeddable is good for Hibernate I don't see why it should be different in Doctrine. IMHO same naming convention is beneficial for end users who migrated from Java... if any:-) |
As we discussed before, @EmbedOne kind of makes sense, but @EmbedMany is impossible. That said, we should stick to JPA convention since differing between One to Many is not valid. I vote for @embeddable. @beberlei gonna review this tonight I think |
I didn't know that about Hibernate. JPA convention is preferable in my On Mon, Apr 1, 2013 at 5:35 PM, Guilherme Blanco
|
@@ -136,6 +136,11 @@ protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonS | |||
$this->completeIdGeneratorMapping($class); | |||
} | |||
|
|||
foreach ($class->embeddedClasses as $property => $embeddableClass) { | |||
$embeddableMetadata = $this->getMetadataFor($embeddableClass); | |||
$class->inlineEmbeddable($property, $embeddableMetadata); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing line break
I understand the problem now, ty for explaining. I suggest not making mistake with value objects, they really should be compared by value, otherwise they are not value objects (in my last comment i stated they should be compared with "===", my intention was "=="). |
The PR is not about ValueObjects, DDC-93 just calls them this way. We introduce embeddables, which are not necessarily value objects. Its up to the user to decide how they implement them. This is indeed inconsistent to how types work, but that is a performance constraint |
When this feature will be able to make it into stable version of Doctrine? |
@ondrejmirtes probably 2.5 |
Regarding embeddable/datetime comparison, would it be possible to introduce additional parameter to choose which way we want to compare instances? Eg: This way embeddables would be safe to use for both beginners (naive embeddable classes) and advanced users (value objects, immutables...) Same could be applied for DateTime objects |
Not really, since there is native DateTimeImmutable now. :)
That's sad, it would be very nice addition to otherwise featureless 2.4. |
Not 100% sure AFAIK (many want it delayed to another version since it's not correctly implemented) |
It has been reimplemented to not use inheritance but to be siblings and use a shared interface DateTimeInterface, see this commit: php/php-src@68a7fec. It's going to be part of 5.5 (actually, it already is in 5.5.0beta3). |
@gseric The embeddables will be writable by default and cannot be compared by reference the way this feature is implemented right now. A different implementation would be much larger and definately not make it into 2.5. It might be possible to do something like However the way you described it is too expensive to implement at the moment and will be delayed to a future 3.0, where we can rewrite larger chunks of the ClassMetadata API. |
Nice! Thanks for relaying the good news ;) |
@beberlei: What is the status of this feature? |
@mvrhov it is scheduled for Doctrine 2.5. the focus right now is to stabilize 2.4 to release it as we are in beta |
I was asking because I have the use case (storing a snapshot the data on invoice/order line at the time it was created). Right now I'm serializing that data into a json and unserializing it on demand behind the scene... |
This is one of the most wanted feature in Doctrine currently IMO. A quick search on Google for "doctrine value object" results in a lot of entries. I hope to see it here soon. |
Can someone please explain to me how this gonna work with Symfony2 forms ? What will be the expected behavior if the entity has value objects where each of them encapsulates its own validation rules? |
@sherifsabry20000: That is off-topic, you should probably ask on a different, more appropriate place. |
Is this still alive? I'd love to see this feature land in the next release! |
@beberlei what is the state of this PR ? |
Great to see that you've also thought of that feature. I wanted to propose some improvements to current approach. In order to have multiple embedables of the same type embeded in entity I believe you need to define column prefix, like this
and this should map to
also please consider updating DQL syntax with something like this:
and make it possible for embedable to embed another embedable:
|
@devhelp: That's good point. There should be some possibility to override column (name etc.) definitions, like with using columns defined on traits or like association overrides. |
@Majkl578 as for Address you may be right - let's put just Price class there and use it in context of 'sellingPrice' & 'purchasePrice' of Merchandise class and we're good |
Superseded by #835 |
This pull request takes a different approach than GH-265 to implement ValueObjects. Instead of changing most of the code in every layer, we just inline embedded object class metadata into an entities metadata and then use a reflection proxy that looks like "ReflectionProperty" to do the rewiring.
The idea is inspired from Symfony Forms 'property_path' option, where you can write and read values to different parts of an object graph.
This is a WIP, there have been no further tests made about the consequences of this approach. The implementation is up for discussion.