Value objects (Based on #634) #835

Merged
merged 33 commits into from Feb 8, 2014

Conversation

Projects
None yet
Member

schmittjoh commented Nov 1, 2013

This is PR #634 with the following additional changes:

  • Merged into master (fixed some conflict in Metadata classes)
  • Support for DQL queries on fields of embedded objects

Why don't we raise the requirements and also drive up the php 5.5 adaption?

Member

stof replied Mar 27, 2013

@mvrhov bumping the requirement to 5.5 would be a BC break (what about people which cannot use 5.5 yet ?).
And doing this bump only to make the testsuite a bit more convenient would be weird IMO

Contributor

mvrhov replied Mar 27, 2013

If this is required just for the test, then I don't care. However if I need to provide this additionally in each of my classes, then it's a shame.
I've also listed my reasoning behind why it should be a good idea.

Member

stof replied Mar 27, 2013

This is just a convenience for tests to avoid writing the class name as a string when doing a $em->find call, making it easier to move fixture classes. See line 34.

Hello,

thank you for creating this pull request. I have automatically opened an issue
on our Jira Bug Tracker for you. See the issue link:

http://www.doctrine-project.org/jira/browse/DDC-2773

We use Jira to track the state of pull requests and the versions they got
included in.

+ $fieldMapping['declaredField'] = $property;
+ $fieldMapping['originalField'] = $fieldMapping['fieldName'];
+ $fieldMapping['fieldName'] = $property . "." . $fieldMapping['fieldName'];
+ $fieldMapping['columnName'] = $property . "_" . $fieldMapping['columnName'];
@beberlei

beberlei Nov 1, 2013

Owner

This probably needs to be delegated to the strategy handling automatic column generation instead of doing it inline here.

@schmittjoh

schmittjoh Nov 1, 2013

Member

You mean as an additional method?

@beberlei

beberlei Nov 1, 2013

Owner

No Doctrine\ORM\Mapping\NamingStrategy handles automatic naming of columns based on class and field names. However changing the interface is obviously a BC break. I think its small enough and easy enough to handle to make it, we need a mention in UPGRADE file though.

@schmittjoh

schmittjoh Nov 1, 2013

Member

done

On Fri, Nov 1, 2013 at 9:33 PM, Benjamin Eberlei
notifications@github.comwrote:

In lib/Doctrine/ORM/Mapping/ClassMetadataInfo.php:

  •    $this->embeddedClasses[$mapping['fieldName']] = $this->fullyQualifiedClassName($mapping['class']);
    
  • }
  • /**
  • \* Inline the embeddable class
    
  • *
    
  • \* @param string $property
    
  • \* @param ClassMetadataInfo $embeddable
    
  • */
    
  • public function inlineEmbeddable($property, ClassMetadataInfo $embeddable)
  • {
  •    foreach ($embeddable->fieldMappings as $fieldMapping) {
    
  •        $fieldMapping['declaredField'] = $property;
    
  •        $fieldMapping['originalField'] = $fieldMapping['fieldName'];
    
  •        $fieldMapping['fieldName'] = $property . "." . $fieldMapping['fieldName'];
    
  •        $fieldMapping['columnName'] = $property . "_" . $fieldMapping['columnName'];
    

No Doctrine\ORM\Mapping\NamingStrategy handles automatic naming of
columns based on class and field names. However changing the interface is
obviously a BC break. I think its small enough and easy enough to handle to
make it, we need a mention in UPGRADE file though.


Reply to this email directly or view it on GitHubhttps://github.com/doctrine/doctrine2/pull/835/files#r7380794
.

@@ -1065,6 +1065,12 @@ public function PathExpression($expectedTypes)
$this->match(Lexer::T_IDENTIFIER);
$field = $this->lexer->token['value'];
+
+ while ($this->lexer->isNextToken(Lexer::T_DOT)) {
@beberlei

beberlei Nov 1, 2013

Owner

Does this loop need validation of sorts? Or are there sane failures for it?

@schmittjoh

schmittjoh Nov 1, 2013

Member

If the field does not exist, there is a QueryException at some later point. I don't think that we need to add more validation here, or did you have anything specific in mind?

@beberlei

beberlei Nov 1, 2013

Owner

query exception is perfect, i was afraid it might notice out or something ugly.

@guilhermeblanco

guilhermeblanco Nov 14, 2013

Owner

This seems incomplete. We're relying on a breakage somewhere as a Query Exception else instead of properly throwing a Semantical or Parser exception properly.
I'd say that here we should properly add fields to PathExpression and then evaluating them on processDeferredPathExpressions.

@beberlei

beberlei Nov 14, 2013

Owner

Since this fields are saved as "foo.bar" in fieldMappings this is passed to deferred path expressions etc.

@schmittjoh

schmittjoh Nov 14, 2013

Member

The beauty of this implementation really is that almost all parts except the metadata drivers can be left completely unaware of embeddables. We now just allow field names to contain dots.

@guilhermeblanco

guilhermeblanco Nov 14, 2013

Owner

@beberlei but it's not properly validated. Is it "foo" or "bar" that is wrong? I describe some of my concerns below.

@schmittjoh I see a problem with this. There's no way to differ a field from an embedded (and this is a huge problem IMHO).
Also, "user.location.geo.latitude" doesn't seem to be supported.
Finally, Embeddeable ClassMetadata is created purely for 3rd-party consumers, but never consumed internally on DQL, Hydrator, Persister, etc.
It seems to me we're relying on an unintentional support to build a big feature which may bring a lot of headaches in the future.

@schmittjoh

schmittjoh Nov 14, 2013

Member

I can address some of these concerns at least:

  1. You can distinguish an embedded field vs a normal field by the fact that it contains dots. We can make the exception message more precise for these cases if deemed necessary.
  2. Embedded fields can work over multiple levels

I cannot address the other things. I really don't know whether this feature will cause headaches in the future. At this point, I don't see why, but I'm not a fortune teller :) however, the internal implementation could be changed for a Doctrine 3 release without breaking BC with the end-user facing part.

+
+ /**
+ * @expectedException Doctrine\ORM\Query\QueryException
+ * @expectedExceptionMessage no field or association named address.asdfasdf
@beberlei

beberlei Nov 1, 2013

Owner

We use $this->setExpectedException in the code by convention, can you change it to using the method?

@schmittjoh

schmittjoh Nov 1, 2013

Member

done.

On Fri, Nov 1, 2013 at 9:34 PM, Benjamin Eberlei
notifications@github.comwrote:

In tests/Doctrine/Tests/ORM/Functional/ValueObjectsTest.php:

  •    $this->_em->refresh($person);
    
  •    $this->assertEquals('Boo', $person->address->street);
    
  •    // DELETE
    
  •    $this->_em->createQuery("DELETE " . __NAMESPACE__ . "\DDC93Person p WHERE p.address.city = :city")
    
  •        ->setParameter('city', 'Karlsruhe')
    
  •        ->execute();
    
  •    $this->_em->clear();
    
  •    $this->assertNull($this->_em->find(__NAMESPACE__.'\DDC93Person', $person->id));
    
  • }
  • /**
  • \* @expectedException Doctrine\ORM\Query\QueryException
    
  • \* @expectedExceptionMessage no field or association named address.asdfasdf
    

We use $this->setExpectedException in the code by convention, can you
change it to using the method?


Reply to this email directly or view it on GitHubhttps://github.com/doctrine/doctrine2/pull/835/files#r7380815
.

+ *
+ * @return string
+ */
+ function embeddedFieldToColumnName($propertyName, $embeddedColumnName);
@FabioBatSilva

FabioBatSilva Nov 1, 2013

Owner

Would be nice to have $entityClass and $embeddedClass

@@ -53,6 +53,14 @@ public function propertyToColumnName($propertyName, $className = null)
+ /**
+ * {@inheritdoc}
+ */
+ public function embeddedFieldToColumnName($propertyName, $embeddedColumnName)
+ {
+ return $propertyName.ucfirst($embeddedColumnName);
@FabioBatSilva

FabioBatSilva Nov 1, 2013

Owner

IMO should be $propertyName . '_' . $embeddedColumnName;

+ $embeddedObject = $this->parentProperty->getValue($object);
+
+ if ($embeddedObject === null) {
+ $embeddedObject = new $this->class; // TODO
@schmittjoh

schmittjoh Nov 1, 2013

Member

How about changing this to use the unserialize trick, or did you have something else in mind?

Owner

beberlei commented Nov 12, 2013

@guilhermeblanco Feedback please, this is mergable from my POV.

Is there any docs already how this would work in userland code? I am really eager to see what this creates for new opportunities :)

Member

stof commented Nov 12, 2013

This is a very good point from @juriansluiman. The doc needs to be updated

+ if ( ! isset($embeddedClass['inherited']) && ! $parentClass->isMappedSuperclass) {
+ $embeddedClass['inherited'] = $parentClass->name;
+ }
+ if ( ! isset($embeddedClass['declared'])) {
@deeky666

deeky666 Nov 12, 2013

Member

Missing line break between IFs

@schmittjoh

schmittjoh Nov 12, 2013

Member

Hm, this looks the same like the code 10 lines above (you need to open the entire file).

@deeky666

deeky666 Nov 12, 2013

Member

Yes, but AFAIK this is wrong from a CS perspective. See doLoadMetadata(). But there are still no concrete CS specifications ;)

Owner

Ocramius commented Nov 12, 2013

@schmittjoh support for the other metadata drivers is still missing - should be added before merge and after this is actually approved as good (looking good though!)

@beberlei what about DQL support?

Owner

beberlei commented Nov 12, 2013

@Ocramius DQL is supported, it was a three liner that johannes added.

Owner

Ocramius commented Nov 12, 2013

Yeah, saw afterwards that there were tests for it, nice!

Member

stof commented Nov 12, 2013

@schmittjoh The first commit in the list (adding a new output format for the RunDqlCommand) looks weird. Is it an issue with a diverging branch after a rebase was done ?

@@ -884,6 +898,18 @@ public function wakeupReflection($reflService)
$this->reflClass = $reflService->getClass($this->name);
foreach ($this->fieldMappings as $field => $mapping) {
+ if (isset($mapping['declaredField'])) {
+ $declaringClass = isset($this->embeddedClasses[$mapping['declaredField']]['declared'])
+ ? $this->embeddedClasses[$mapping['declaredField']]['declared'] : $this->name;
@stof

stof Nov 12, 2013

Member

wrong indentation (should be 4 spaces per level)

+
+ $fieldMapping['columnName'] = ! empty($this->embeddedClasses[$property]['columnPrefix'])
+ ? $this->embeddedClasses[$property]['columnPrefix'] . $fieldMapping['columnName']
+ : $this->namingStrategy->embeddedFieldToColumnName($property, $fieldMapping['columnName'], $this->reflClass->name, $embeddable->reflClass->name);
@stof

stof Nov 12, 2013

Member

wrong indentation

@boite

boite Feb 8, 2014

$this->reflClass->name, $embeddable->reflClass->name cause PHP Notice: Trying to get property of non-object if either of the reflClass properties are null. Suggest something like:

if (! empty($this->embeddedClasses[$property]['columnPrefix'])) {
    $fieldMapping['columnName'] = $this->embeddedClasses[$property]['columnPrefix'] . $fieldMapping['columnName'];
} else {
    $className = $this->reflClass ? $this->reflClass->name : null;
    $embeddedClassName = $embeddable->reflClass ? $embeddable->reflClass->name : null;
    $fieldMapping['columnName'] = $this->namingStrategy->embeddedFieldToColumnName($property, $fieldMapping['columnName'], $className, $embeddedClassName);
}
+ $fieldMapping['fieldName'] = $property . "." . $fieldMapping['fieldName'];
+
+ $fieldMapping['columnName'] = ! empty($this->embeddedClasses[$property]['columnPrefix'])
+ ? $this->embeddedClasses[$property]['columnPrefix'] . $fieldMapping['columnName']
@stof

stof Nov 12, 2013

Member

souldn't this case be handled by the naming strategy too ?

@schmittjoh

schmittjoh Nov 12, 2013

Member

columnPrefix is always defined by the user.

@@ -247,6 +247,13 @@ class ClassMetadataInfo implements ClassMetadata
public $isMappedSuperclass = false;
+ /**
+ * READ-ONLY: Wheather this class describes the mapping of an embeddable class.
Member

schmittjoh commented Nov 12, 2013

I've now added some docs, the missing driver support and made some cs fixes.

Owner

FabioBatSilva commented Nov 13, 2013

@schmittjoh, instead of columnPrefix
I'd like to suggest the java/hibernate approach to allow multiple embeddables and override mappings : Embedded + AttributeOverride

As we already support @AttributeOverride to override parent atributes would be nice to keep the same approach here..

<?php
/** 
* @Embedded(class="Address") 
* @AttributeOverrides({
*   @AttributeOverride(name="street", column=@Column("street_billing")),
*   @AttributeOverride(name="zip", column=@Column("zip_billing"))
* })
*/
 public $billingAddress;

/** 
* @Embedded(class="Address") 
* @AttributeOverrides({
*   @AttributeOverride(name="street", column=@Column("street_delivery")),
*   @AttributeOverride(name="zip", column=@Column("zip_delivery"))
* })
*/
 public $deliveryAddress;
Member

Majkl578 commented Nov 13, 2013

@FabioBatSilva: That was already suggested a month ago in #634, but noone cared.

Member

schmittjoh commented Nov 13, 2013

I've considered this before adding support for columnPrefix.

I've come to the conclusion though that both approaches @AttributeOverride and columnPrefix are complementary, not mutually exclusive. If you would like to change a specific column name, then you can use @AttributeOverride (this is already supported, see below); however if you'd like to change all columns (which I think is a common operation), then columnPrefix makes this very easy.

The syntax for @AttributeOverride is as follows:


/**
 * @AttributeOverrides({
 *      @AttributeOverride(name = "address.street", column = @Column("....")),
 * })
 */
class User
{
    /** @Embedded */
    private $address;
}

gnutix commented Nov 13, 2013

http://docs.doctrine-project.org/en/latest/reference/limitations-and-known-issues.html#value-objects This page could then be updated as well. (chapter 26.1.3. Value Objects)

Member

stof commented Nov 13, 2013

@gnutix surely not this one as you are linking to the 2.0.x version of the doc :)
but the limitation should indeed be removed from the doc of the new version

+ $mapping = array(
+ 'fieldName' => (string) $embeddedMapping['name'],
+ 'class' => (string) $embeddedMapping['class'],
+ 'columnPrefix' => isset($embeddedMapping['class']) ? (string) $embeddedMapping['class'] : null,
@FabioBatSilva

FabioBatSilva Nov 13, 2013

Owner

$embeddedMapping['columnPrefix']

@@ -884,6 +898,18 @@ public function wakeupReflection($reflService)
$this->reflClass = $reflService->getClass($this->name);
foreach ($this->fieldMappings as $field => $mapping) {
+ if (isset($mapping['declaredField'])) {
+ $declaringClass = isset($this->embeddedClasses[$mapping['declaredField']]['declared'])
@FabioBatSilva

FabioBatSilva Nov 13, 2013

Owner
<?php
$declaringClass = isset($this->embeddedClasses[$mapping['declaredField']]['declared'])
    ? $this->embeddedClasses[$mapping['declaredField']]['declared'] 
    : $this->name;

gnutix commented Nov 14, 2013

@stof Indeed ! I've been tricked by the "Project Versions" selector on the left which was showing me "latest"... Link updated in my previous comment.

Owner

Ocramius commented Nov 14, 2013

@schmittjoh maybe a silly question, but does this also work with VOs as identifiers (obviously implementing __toString in the VO)?

Not a requirement, but just curious.

Member

schmittjoh commented Nov 14, 2013

I don't think it's supported right now.

Considering that Doctrine already supports composite primary keys though,
it should be easy to add support for it (not even requiring __toString).

On Thu, Nov 14, 2013 at 12:47 PM, Marco Pivetta notifications@github.comwrote:

@schmittjoh https://github.com/schmittjoh maybe a silly question, but
does this also work with VOs as identifiers (obviously implementing
__toString in the VO)?

Not a requirement, but just curious.


Reply to this email directly or view it on GitHubhttps://github.com/doctrine/doctrine2/pull/835#issuecomment-28477826
.

Owner

Ocramius commented Nov 14, 2013

Right, __toString is probably not needed thanks to the reflection hack

Member

schmittjoh commented Nov 14, 2013

I wouldn't even call that a "hack". It's just a different implementation,
hack sounds far too negative :)

On Thu, Nov 14, 2013 at 12:56 PM, Marco Pivetta notifications@github.comwrote:

Right, __toString is probably not needed thanks to the reflection hack


Reply to this email directly or view it on GitHubhttps://github.com/doctrine/doctrine2/pull/835#issuecomment-28478306
.

Member

stof commented Nov 14, 2013

I still see a drawback to this implementation: these "value objects" are tracked for changes property by property, while object (no other way here, and probably not so commonly used) and date/datetime fields are tracked by reference.
Setting a new datetime with the same value currently triggers an update in the DB (which is common when using Symfony forms as it returns a new DateTime instance after transforming the user input to avoid mutating the existing one), and mutating a datetime would not be saved. Both of these behaviors is inconsistent with the value object implementation (the case of mutating a DateTime is less an issue IMO as most code tries to avoid it to avoid weird side effects, hence the new immutable classes in PHP 5.5).

Owner

Ocramius commented Dec 12, 2013

@jankramer base the PR on it, I'd say...

Owner

beberlei commented Dec 16, 2013

@schmittjoh can you rebase this one? Then we can merge it as well.

Owner

beberlei commented Dec 18, 2013

I would throw an error for now on embeddeable ins embeddables to avoid the problem @jankramer describes.

@beberlei beberlei referenced this pull request Jan 2, 2014

Closed

[WIP] Value objects #634

Contributor

shustrik commented Jan 8, 2014

@beberlei what news about this PR?

Contributor

mvrhov commented Jan 15, 2014

hm is it just me or this really looks like a bad rebase? @schmittjoh

Member

schmittjoh commented Jan 15, 2014

What @beberlei was looking for was not actually a rebase, but merging the master branch.

Unfortunately, the second level cache PR which was merged earlier, now causes some tests to fail. Maybe @FabioBatSilva could help with this?

Owner

Ocramius commented Jan 15, 2014

Uhmm, not really - rebase is rebase - was it too messy to apply here? :|

Member

schmittjoh commented Jan 15, 2014

I didn't try it, but I know that I fixed some merge conflicts during the
course of this PR. I had talked with @beberlei on IRC about the rebase and
what he wanted is to use the merge button which works with a rebase, but
also with a merge.

At any rate, what we really need to focus on is fixing the tests. The new
failures are somehow related to the SLC additions.

Contributor

mvrhov commented Feb 5, 2014

@FabioBatSilva Could you help with failed tests. I'd really like to see this one merged into the 2.5

This is one of most wanted feature nowadays, IMHO.

Owner

FabioBatSilva commented Feb 5, 2014

The postgres failure is related to the default sort strategy, not related to SLC ... The build passes after restart..

+ }
+
+ /**
+ * @group dql
@FabioBatSilva

FabioBatSilva Feb 5, 2014

Owner

add @non-cacheable instead of markTestSkipped

JCMais commented Feb 5, 2014

Just a little question, only this PR is blocking the 2.5 beta?

Owner

guilhermeblanco commented Feb 5, 2014

@JCMais we also have custom persisters in the pipeline IIRC.

beberlei added a commit that referenced this pull request Feb 8, 2014

@beberlei beberlei merged commit 8a0901c into doctrine:master Feb 8, 2014

1 check passed

default The Travis CI build passed
Details
Owner

beberlei commented Feb 8, 2014

Done Done :) Thanks for picking up the torch @schmittjoh

alsar commented Feb 8, 2014

👏 Thank you for this.

Contributor

jankramer commented Feb 8, 2014

Great news, thanks guys!

Contributor

mvrhov commented Feb 8, 2014

Big big thanks for everyone working on this.

Contributor

shustrik commented Feb 8, 2014

Thank you!

Owner

Ocramius commented Feb 8, 2014

Awesome.

Contributor

docteurklein commented Feb 8, 2014

yay!

Contributor

1ed commented Feb 8, 2014

Great. Thank you!

Contributor

alanbem commented Feb 8, 2014

Great Job!!!!

2014-02-08 17:29 GMT+01:00 Florian Klein notifications@github.com:

yay!

Reply to this email directly or view it on GitHubhttps://github.com/doctrine/doctrine2/pull/835#issuecomment-34548260
.

Pozdrawiam,
Alan Bem
http://www.recovery.pl/

Contributor

tPl0ch commented Feb 8, 2014

+100000000000

Member

schmittjoh commented Feb 8, 2014

You're welcome :)

@schmittjoh schmittjoh deleted the schmittjoh:ValueObjects branch Feb 8, 2014

alsar commented Feb 8, 2014

I played around with the new functionality and encountered a problem with embeddables inside embeddables.
Is this behaviour not supported yet?

raul782 commented Feb 8, 2014

Thanks a lot guys.

@ghost

ghost commented Feb 8, 2014

Finally the feature was added :) Thank you all who contributed.

Maybe we can now look forward to adding support for mapping collections of embeddable objects
http://www.doctrine-project.org/jira/browse/DDC-2826

+ private $childProperty;
+ private $class;
+
+ public function __construct($parentProperty, $childProperty, $class)
@Taluu

Taluu Feb 9, 2014

Aren't these parameters missing some typehint ? As it is used as (possibly ?) ReflectionProperty afterwards...

@Ocramius

Ocramius Feb 9, 2014

Owner

@Taluu see standing TODO in the class header`.

Owner

beberlei commented Feb 9, 2014

@alsar Ah yes, i have to disable doing that for now. Its not yet supported.

Owner

beberlei commented Feb 9, 2014

@sherifsabry20000 a collection of embeddable objects is just a @OneToMany/@ManyToOne with {"cascade":"all"}

Thanks a lot guys.

Is it possible to use, for example, Address as both an entity and an embeddable? A contrived example, that has a basis in our application.

Let's say I have an entity Client that can have multiple Addresses (physical, mailing, etc). In that case Address needs to be a collection, and a OneToMany needs to be established.

In addition, each Client has a OneToMany for Facility. A Facility has one embedded Address.

Would we have to define two things with the basically the same definition (i.e., an Address entity and Address as embeddable), or can one definition serve both purposes?

Does that make sense? Or, am I thinking about the problem in entirely the wrong way?

Owner

Ocramius commented Feb 10, 2014

@mbadolato an entity has an ID, an embeddable doesn't, so I don't think it makes sense here. I'd also suggest moving these discussions to the mailing list

@Ocramius Re: having an id vs not having an id: Yep, hence my question. Address cannot be used in both contexts?

Contributor

mvrhov commented Feb 11, 2014

@mbadolato I thought that was possible. The use case would be an invoice and a customer associated with it. When you create an invoice almost full customer information should be persisted together with it.

Member

schmittjoh commented Feb 11, 2014

I don't think that is possible just yet as we just have a single metadata
instance per class. We would need something like the @elementcollection
mentioned earlier to make that work.

On Tue, Feb 11, 2014 at 11:14 AM, Miha Vrhovnik notifications@github.comwrote:

@mbadolato https://github.com/mbadolato I thought that was possible.
The use case would be an invoice and a customer associated with it. When
you create an invoice almost full customer information should be persisted
together with it.

Reply to this email directly or view it on GitHubhttps://github.com/doctrine/doctrine2/pull/835#issuecomment-34741113
.

That's what I was confirming. Thanks @schmittjoh.

@mvrhov Yes that is a good example of a use case for it.

@beberlei How can you use manyToOne relation between entities and embeddable element ?
I have used manyToOne but nothing happened when i've created the database.

Owner

Ocramius commented Mar 13, 2014

@fpaterno please open a new issue at http://www.doctrine-project.org/jira/browse/DDC or ask on the mailing list.

mkoubik commented Mar 23, 2014

@mvrhov then you should have @Embeddable CustomerData embedded both in Customer and in Invoice.

erik-am commented Jun 5, 2014

I'm quite enthousiastic about Embeddables being added to Doctrine, but it's a pity that true Value Objects, which are compared by their properties, are not supported yet.

Given a Value Object Address with properties street and house number that you can instantiate with new Address("High Street", 1).

The following is now supported:
DQL1: SELECT u FROM User u WHERE (u.address.street = :street AND u.address.nr = :number) with { 'street' => 'High Street', 'number' => 1 }.

But then you should know the internal properties when writing your query. That's not how Value Objects usually are compared.

Instead, I expect to be able to do this:
DQL2: SELECT u FROM User u WHERE (u.address = :address) with { 'address' => new Address("High Street", 1) }.
Internally, DQL2 could simply be transformed to the equivalent DQL1 by replacing the condition with conditions for each internal property. The advantage is that the one writing the query does not have to refer to the internal fields; the transformation is hidden.

A complicating factor is that Value Objects are Embeddables, but not every Embeddable is a Value Object. So there is always the question if objects need to be compared by reference or by their properties.

So, perhaps it's an idea to introduce a special operator ~ for comparing objects by their value to make the distinction explicit? Like so:
DQL3: SELECT u FROM User u WHERE (u.address ~ :address) with { 'address' => new Address("High Street", 1) }.

Finally, for those who would also like more support for Value Objects, please check out my pull request for Collections. It expresses the same ideas for in-memory collections and adds the ~ operator for criterias.

Just some thoughts and ideas. I'd love to hear some discussion on this as I think it would make Doctrine really powerful in supporting rich, expressive domain models.

Member

stof commented Jun 5, 2014

please open a ticket in the issue tracker for this feature request rather than commenting on a merged PR. Otherwise the discussion will get lost

mkoubik commented Jun 5, 2014

@erik-am 👍

erik-am commented Jun 5, 2014

@stof Thanks for pointing me to the right direction. I created an issue for it: http://www.doctrine-project.org/jira/browse/DDC-3154

This thread would probably be a good candidate for the new Github Conversation Lock

Owner

Ocramius commented Jun 11, 2014

@mbadolato I don't see any fights going on, though yes, if anyone else has anything to add, please do so with a new issue on our issue tracker at http://www.doctrine-project.org/jira/ or on the mailing list at https://groups.google.com/forum/#!search/doctrine-user

renan added a commit to renan/doctrine2 that referenced this pull request Jul 7, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment