Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
D
doctrine-dbal
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Tomáš Trávníček
doctrine-dbal
Commits
31892fb4
Commit
31892fb4
authored
Jul 02, 2009
by
romanb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[2.0] Fixed cascading issue (#2307). Fixed many-many object hydration issue.
parent
3f4cd46b
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
109 additions
and
123 deletions
+109
-123
ObjectHydrator.php
lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
+13
-7
PersistentCollection.php
lib/Doctrine/ORM/PersistentCollection.php
+52
-78
UnitOfWork.php
lib/Doctrine/ORM/UnitOfWork.php
+6
-8
CmsArticle.php
tests/Doctrine/Tests/Models/CMS/CmsArticle.php
+4
-0
CmsPhonenumber.php
tests/Doctrine/Tests/Models/CMS/CmsPhonenumber.php
+5
-3
CmsUser.php
tests/Doctrine/Tests/Models/CMS/CmsUser.php
+2
-6
ECommerceFeature.php
tests/Doctrine/Tests/Models/ECommerce/ECommerceFeature.php
+1
-4
AbstractManyToManyAssociationTestCase.php
.../ORM/Functional/AbstractManyToManyAssociationTestCase.php
+2
-1
ManyToManyBidirectionalAssociationTest.php
...ORM/Functional/ManyToManyBidirectionalAssociationTest.php
+19
-8
ManyToManyUnidirectionalAssociationTest.php
...RM/Functional/ManyToManyUnidirectionalAssociationTest.php
+4
-8
OrmFunctionalTestCase.php
tests/Doctrine/Tests/OrmFunctionalTestCase.php
+1
-0
No files found.
lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
View file @
31892fb4
...
...
@@ -123,7 +123,6 @@ class ObjectHydrator extends AbstractHydrator
// Take snapshots from all initialized collections
foreach
(
$this
->
_collections
as
$coll
)
{
$coll
->
takeSnapshot
();
$coll
->
setHydrationFlag
(
false
);
}
// Clean up
...
...
@@ -344,7 +343,7 @@ class ObjectHydrator extends AbstractHydrator
if
(
!
$relation
->
isOneToOne
())
{
if
(
isset
(
$nonemptyComponents
[
$dqlAlias
]))
{
if
(
!
isset
(
$this
->
_initializedRelations
[
spl_object_hash
(
$baseElement
)][
$relationAlias
]))
{
$this
->
initRelatedCollection
(
$baseElement
,
$relationAlias
)
->
setHydrationFlag
(
true
)
;
$this
->
initRelatedCollection
(
$baseElement
,
$relationAlias
);
}
$path
=
$parent
.
'.'
.
$dqlAlias
;
...
...
@@ -357,12 +356,19 @@ class ObjectHydrator extends AbstractHydrator
// If it's a bi-directional many-to-many, also initialize the reverse collection.
if
(
$relation
->
isManyToMany
())
{
if
(
$relation
->
isOwningSide
&&
isset
(
$this
->
_ce
[
$entityName
]
->
inverseMappings
[
$relationAlias
]))
{
$inverseFieldName
=
$this
->
_ce
[
$entityName
]
->
inverseMappings
[
$relationAlias
]
->
sourceFieldName
;
// Only initialize reverse collection if it is not yet initialized.
if
(
!
isset
(
$this
->
_initializedRelations
[
spl_object_hash
(
$element
)][
$inverseFieldName
]))
{
$this
->
initRelatedCollection
(
$element
,
$this
->
_ce
[
$entityName
]
->
inverseMappings
[
$relationAlias
]
->
sourceFieldName
);
}
}
else
if
(
$relation
->
mappedByFieldName
)
{
// Only initialize reverse collection if it is not yet initialized.
if
(
!
isset
(
$this
->
_initializedRelations
[
spl_object_hash
(
$element
)][
$relation
->
mappedByFieldName
]))
{
$this
->
initRelatedCollection
(
$element
,
$relation
->
mappedByFieldName
);
}
}
}
if
(
$field
=
$this
->
_getCustomIndexField
(
$dqlAlias
))
{
$indexValue
=
$this
->
_ce
[
$entityName
]
...
...
@@ -371,12 +377,12 @@ class ObjectHydrator extends AbstractHydrator
$this
->
_ce
[
$parentClass
]
->
reflFields
[
$relationAlias
]
->
getValue
(
$baseElement
)
->
s
et
(
$indexValue
,
$element
);
->
hydrateS
et
(
$indexValue
,
$element
);
}
else
{
$this
->
_ce
[
$parentClass
]
->
reflFields
[
$relationAlias
]
->
getValue
(
$baseElement
)
->
a
dd
(
$element
);
->
hydrateA
dd
(
$element
);
}
$this
->
_identifierMap
[
$path
][
$id
[
$parent
]][
$id
[
$dqlAlias
]]
=
$this
->
getLastKey
(
$this
->
_ce
[
$parentClass
]
...
...
lib/Doctrine/ORM/PersistentCollection.php
View file @
31892fb4
...
...
@@ -96,14 +96,6 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
*/
private
$_backRefFieldName
;
/**
* Hydration flag.
*
* @var boolean
* @see setHydrationFlag()
*/
private
$_hydrationFlag
=
false
;
/**
* The class descriptor of the owning entity.
*/
...
...
@@ -170,8 +162,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
$targetClass
=
$this
->
_em
->
getClassMetadata
(
$assoc
->
targetEntityName
);
if
(
isset
(
$targetClass
->
inverseMappings
[
$assoc
->
sourceFieldName
]))
{
// Bi-directional
$this
->
_backRefFieldName
=
$targetClass
->
inverseMappings
[
$assoc
->
sourceFieldName
]
->
sourceFieldName
;
$this
->
_backRefFieldName
=
$targetClass
->
inverseMappings
[
$assoc
->
sourceFieldName
]
->
sourceFieldName
;
}
}
}
...
...
@@ -228,10 +219,8 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public
function
set
(
$key
,
$value
)
{
parent
::
set
(
$key
,
$value
);
if
(
!
$this
->
_hydrationFlag
)
{
$this
->
_changed
();
}
}
/**
* Adds an element to the collection.
...
...
@@ -244,11 +233,23 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public
function
add
(
$value
)
{
parent
::
add
(
$value
);
$this
->
_changed
();
return
true
;
}
if
(
$this
->
_hydrationFlag
)
{
/**
* INTERNAL:
* Adds an element to a collection during hydration.
*
* @param mixed $value The element to add.
*/
public
function
hydrateAdd
(
$value
)
{
parent
::
add
(
$value
);
if
(
$this
->
_backRefFieldName
)
{
// Set back reference to owner
if
(
$this
->
_association
->
isOneToMany
())
{
// OneToMany
$this
->
_typeClass
->
getReflectionProperty
(
$this
->
_backRefFieldName
)
->
setValue
(
$value
,
$this
->
_owner
);
}
else
{
...
...
@@ -257,26 +258,18 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
->
getValue
(
$value
)
->
add
(
$this
->
_owner
);
}
}
}
else
{
$this
->
_changed
();
}
return
true
;
}
/**
* Adds all elements of the other collection to this collection.
* INTERNAL:
* Sets a keyed element in the collection during hydration.
*
* @param object $otherCollection
* @todo Impl
* @override
* @param mixed $key The key to set.
* $param mixed $value The element to set.
*/
public
function
addAll
(
$otherCollection
)
public
function
hydrateSet
(
$key
,
$value
)
{
parent
::
addAll
(
$otherCollection
);
//...
//TODO: Register collection as dirty with the UoW if necessary
//$this->_changed();
parent
::
set
(
$key
,
$value
);
}
/**
...
...
@@ -314,25 +307,6 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
}
/**
* INTERNAL:
* Sets a flag that indicates whether the collection is currently being hydrated.
*
* If the flag is set to TRUE, this has the following consequences:
*
* 1) During hydration, bidirectional associations are completed automatically
* by setting the back reference.
* 2) During hydration no change notifications are reported to the UnitOfWork.
* That means add() etc. do not cause the collection to be scheduled
* for an update.
*
* @param boolean $bool
*/
public
function
setHydrationFlag
(
$bool
)
{
$this
->
_hydrationFlag
=
$bool
;
}
/**
* INTERNAL:
* Tells this collection to take a snapshot of its current state.
...
...
lib/Doctrine/ORM/UnitOfWork.php
View file @
31892fb4
...
...
@@ -1148,11 +1148,11 @@ class UnitOfWork implements PropertyChangedListener
}
$relatedEntities
=
$class
->
reflFields
[
$assocMapping
->
getSourceFieldName
()]
->
getValue
(
$entity
);
if
(
(
$relatedEntities
instanceof
Collection
)
&&
count
(
$relatedEntities
)
>
0
)
{
if
(
$relatedEntities
instanceof
Collection
)
{
foreach
(
$relatedEntities
as
$relatedEntity
)
{
$this
->
_doMerge
(
$relatedEntity
,
$visited
,
$managedCopy
,
$assocMapping
);
}
}
else
if
(
is_object
(
$relatedEntities
)
)
{
}
else
if
(
$relatedEntities
!==
null
)
{
$this
->
_doMerge
(
$relatedEntities
,
$visited
,
$managedCopy
,
$assocMapping
);
}
}
...
...
@@ -1173,12 +1173,11 @@ class UnitOfWork implements PropertyChangedListener
continue
;
}
$relatedEntities
=
$class
->
reflFields
[
$assocMapping
->
sourceFieldName
]
->
getValue
(
$entity
);
if
((
$relatedEntities
instanceof
Collection
||
is_array
(
$relatedEntities
))
&&
count
(
$relatedEntities
)
>
0
)
{
if
((
$relatedEntities
instanceof
Collection
||
is_array
(
$relatedEntities
)))
{
foreach
(
$relatedEntities
as
$relatedEntity
)
{
$this
->
_doSave
(
$relatedEntity
,
$visited
,
$insertNow
);
}
}
else
if
(
is_object
(
$relatedEntities
)
)
{
}
else
if
(
$relatedEntities
!==
null
)
{
$this
->
_doSave
(
$relatedEntities
,
$visited
,
$insertNow
);
}
}
...
...
@@ -1199,12 +1198,11 @@ class UnitOfWork implements PropertyChangedListener
}
$relatedEntities
=
$class
->
reflFields
[
$assocMapping
->
sourceFieldName
]
->
getValue
(
$entity
);
if
(
$relatedEntities
instanceof
Collection
||
is_array
(
$relatedEntities
)
&&
count
(
$relatedEntities
)
>
0
)
{
if
(
$relatedEntities
instanceof
Collection
||
is_array
(
$relatedEntities
))
{
foreach
(
$relatedEntities
as
$relatedEntity
)
{
$this
->
_doDelete
(
$relatedEntity
,
$visited
);
}
}
else
if
(
is_object
(
$relatedEntities
)
)
{
}
else
if
(
$relatedEntities
!==
null
)
{
$this
->
_doDelete
(
$relatedEntities
,
$visited
);
}
}
...
...
tests/Doctrine/Tests/Models/CMS/CmsArticle.php
View file @
31892fb4
...
...
@@ -31,4 +31,8 @@ class CmsArticle
* @OneToMany(targetEntity="CmsComment", mappedBy="article")
*/
public
$comments
;
public
function
setAuthor
(
CmsUser
$author
)
{
$this
->
user
=
$author
;
}
}
tests/Doctrine/Tests/Models/CMS/CmsPhonenumber.php
View file @
31892fb4
...
...
@@ -9,8 +9,7 @@ namespace Doctrine\Tests\Models\CMS;
class
CmsPhonenumber
{
/**
* @Column(type="string", length=50)
* @Id
* @Id @Column(type="string", length=50)
*/
public
$phonenumber
;
/**
...
...
@@ -21,6 +20,9 @@ class CmsPhonenumber
public
function
setUser
(
CmsUser
$user
)
{
$this
->
user
=
$user
;
$user
->
addPhonenumber
(
$this
);
}
public
function
getUser
()
{
return
$this
->
user
;
}
}
tests/Doctrine/Tests/Models/CMS/CmsUser.php
View file @
31892fb4
...
...
@@ -68,9 +68,7 @@ class CmsUser
*/
public
function
addPhonenumber
(
CmsPhonenumber
$phone
)
{
$this
->
phonenumbers
[]
=
$phone
;
if
(
$phone
->
user
!==
$this
)
{
$phone
->
user
=
$this
;
}
$phone
->
setUser
(
$this
);
}
public
function
getPhonenumbers
()
{
...
...
@@ -79,9 +77,7 @@ class CmsUser
public
function
addArticle
(
CmsArticle
$article
)
{
$this
->
articles
[]
=
$article
;
if
(
$article
->
user
!==
$this
)
{
$article
->
user
=
$this
;
}
$article
->
setAuthor
(
$this
);
}
public
function
addGroup
(
CmsGroup
$group
)
{
...
...
tests/Doctrine/Tests/Models/ECommerce/ECommerceFeature.php
View file @
31892fb4
...
...
@@ -42,10 +42,7 @@ class ECommerceFeature
}
public
function
setProduct
(
ECommerceProduct
$product
)
{
if
(
$this
->
product
!==
$product
)
{
$this
->
product
=
$product
;
$product
->
addFeature
(
$this
);
}
}
public
function
removeProduct
()
{
...
...
tests/Doctrine/Tests/ORM/Functional/AbstractManyToManyAssociationTestCase.php
View file @
31892fb4
...
...
@@ -32,7 +32,8 @@ class AbstractManyToManyAssociationTestCase extends \Doctrine\Tests\OrmFunctiona
FROM
{
$this
->
_table
}
WHERE
{
$this
->
_firstField
}
=?
AND
{
$this
->
_secondField
}
=?"
,
array
(
$firstId
,
$secondId
)));
array
(
$firstId
,
$secondId
))
->
fetchAll
());
}
public
function
assertCollectionEquals
(
Collection
$first
,
Collection
$second
)
...
...
tests/Doctrine/Tests/ORM/Functional/ManyToManyBidirectionalAssociationTest.php
View file @
31892fb4
...
...
@@ -14,9 +14,9 @@ require_once __DIR__ . '/../../TestInit.php';
*/
class
ManyToManyBidirectionalAssociationTest
extends
AbstractManyToManyAssociationTestCase
{
protected
$_firstField
=
'
car
t_id'
;
protected
$_secondField
=
'
product
_id'
;
protected
$_table
=
'ecommerce_
carts_product
s'
;
protected
$_firstField
=
'
produc
t_id'
;
protected
$_secondField
=
'
category
_id'
;
protected
$_table
=
'ecommerce_
products_categorie
s'
;
private
$firstProduct
;
private
$secondProduct
;
private
$firstCategory
;
...
...
@@ -77,12 +77,23 @@ class ManyToManyBidirectionalAssociationTest extends AbstractManyToManyAssociati
{
$this
->
_createLoadingFixture
();
list
(
$firstProduct
,
$secondProduct
)
=
$this
->
_findProducts
();
$this
->
assertEquals
(
2
,
count
(
$firstProduct
->
getCategories
()));
$this
->
assertEquals
(
2
,
count
(
$secondProduct
->
getCategories
()));
$categories
=
$firstProduct
->
getCategories
();
$products
=
$categories
[
0
]
->
getProducts
();
$firstCategoryProducts
=
$categories
[
0
]
->
getProducts
();
$secondCategoryProducts
=
$categories
[
1
]
->
getProducts
();
$this
->
assertEquals
(
2
,
count
(
$firstCategoryProducts
));
$this
->
assertEquals
(
2
,
count
(
$secondCategoryProducts
));
$this
->
assertTrue
(
$firstCategoryProducts
[
0
]
instanceof
ECommerceProduct
);
$this
->
assertTrue
(
$firstCategoryProducts
[
1
]
instanceof
ECommerceProduct
);
$this
->
assertTrue
(
$secondCategoryProducts
[
0
]
instanceof
ECommerceProduct
);
$this
->
assertTrue
(
$secondCategoryProducts
[
1
]
instanceof
ECommerceProduct
);
$this
->
assertTrue
(
$products
[
0
]
instanceof
ECommerceProduct
);
$this
->
assertTrue
(
$products
[
1
]
instanceof
ECommerceProduct
);
$this
->
assertCollectionEquals
(
$products
,
$categories
[
1
]
->
getProducts
());
$this
->
assertCollectionEquals
(
$firstCategoryProducts
,
$secondCategoryProducts
);
}
protected
function
_createLoadingFixture
()
...
...
tests/Doctrine/Tests/ORM/Functional/ManyToManyUnidirectionalAssociationTest.php
View file @
31892fb4
...
...
@@ -41,10 +41,8 @@ class ManyToManyUnidirectionalAssociationTest extends AbstractManyToManyAssociat
$this
->
_em
->
save
(
$this
->
firstCart
);
$this
->
_em
->
flush
();
$this
->
assertForeignKeysContain
(
$this
->
firstCart
->
getId
(),
$this
->
firstProduct
->
getId
());
$this
->
assertForeignKeysContain
(
$this
->
firstCart
->
getId
(),
$this
->
secondProduct
->
getId
());
$this
->
assertForeignKeysContain
(
$this
->
firstCart
->
getId
(),
$this
->
firstProduct
->
getId
());
$this
->
assertForeignKeysContain
(
$this
->
firstCart
->
getId
(),
$this
->
secondProduct
->
getId
());
}
public
function
testRemovesAManyToManyAssociation
()
...
...
@@ -56,10 +54,8 @@ class ManyToManyUnidirectionalAssociationTest extends AbstractManyToManyAssociat
$this
->
_em
->
flush
();
$this
->
assertForeignKeysNotContain
(
$this
->
firstCart
->
getId
(),
$this
->
firstProduct
->
getId
());
$this
->
assertForeignKeysContain
(
$this
->
firstCart
->
getId
(),
$this
->
secondProduct
->
getId
());
$this
->
assertForeignKeysNotContain
(
$this
->
firstCart
->
getId
(),
$this
->
firstProduct
->
getId
());
$this
->
assertForeignKeysContain
(
$this
->
firstCart
->
getId
(),
$this
->
secondProduct
->
getId
());
}
public
function
testEagerLoad
()
...
...
tests/Doctrine/Tests/OrmFunctionalTestCase.php
View file @
31892fb4
...
...
@@ -83,6 +83,7 @@ class OrmFunctionalTestCase extends OrmTestCase
$conn
->
exec
(
'DELETE FROM ecommerce_shippings'
);
$conn
->
exec
(
'DELETE FROM ecommerce_features'
);
$conn
->
exec
(
'DELETE FROM ecommerce_categories'
);
$conn
->
exec
(
'DELETE FROM ecommerce_products_categories'
);
}
if
(
isset
(
$this
->
_usedModelSets
[
'company'
]))
{
$conn
->
exec
(
'DELETE FROM company_persons_friends'
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment