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
62446f0f
Commit
62446f0f
authored
Jul 28, 2009
by
romanb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[2.0] Cleanup for changeset #6172.
parent
82c41668
Changes
12
Show whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
278 additions
and
217 deletions
+278
-217
ObjectHydrator.php
lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
+50
-29
AssociationMapping.php
lib/Doctrine/ORM/Mapping/AssociationMapping.php
+1
-2
ClassMetadata.php
lib/Doctrine/ORM/Mapping/ClassMetadata.php
+3
-3
ManyToManyMapping.php
lib/Doctrine/ORM/Mapping/ManyToManyMapping.php
+14
-12
OneToManyMapping.php
lib/Doctrine/ORM/Mapping/OneToManyMapping.php
+12
-3
PersistentCollection.php
lib/Doctrine/ORM/PersistentCollection.php
+82
-141
JoinedSubclassPersister.php
lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php
+1
-1
StandardEntityPersister.php
lib/Doctrine/ORM/Persisters/StandardEntityPersister.php
+80
-9
SqlWalker.php
lib/Doctrine/ORM/Query/SqlWalker.php
+2
-5
CmsUser.php
tests/Doctrine/Tests/Models/CMS/CmsUser.php
+11
-2
ManyToManyBidirectionalAssociationTest.php
...ORM/Functional/ManyToManyBidirectionalAssociationTest.php
+19
-7
SelectSqlGenerationTest.php
tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
+3
-3
No files found.
lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php
View file @
62446f0f
...
...
@@ -37,7 +37,7 @@ class ObjectHydrator extends AbstractHydrator
/*
* These two properties maintain their values between hydration runs.
*/
/*
Class entries
*/
/*
Local ClassMetadata cache to avoid going to the EntityManager all the time.
*/
private
$_ce
=
array
();
private
$_discriminatorMap
=
array
();
/*
...
...
@@ -48,9 +48,9 @@ class ObjectHydrator extends AbstractHydrator
private
$_identifierMap
=
array
();
private
$_resultPointers
=
array
();
private
$_idTemplate
=
array
();
private
$_resultCounter
=
0
;
private
$_resultCounter
;
private
$_rootAliases
=
array
();
private
$_fetchedAssociations
=
array
()
;
private
$_fetchedAssociations
;
/* TODO: Consider unifying _collections and _initializedRelations */
/** Collections initialized by the hydrator */
private
$_collections
=
array
();
...
...
@@ -63,11 +63,12 @@ class ObjectHydrator extends AbstractHydrator
$this
->
_isSimpleQuery
=
count
(
$this
->
_rsm
->
aliasMap
)
<=
1
;
$this
->
_allowPartialObjects
=
$this
->
_em
->
getConfiguration
()
->
getAllowPartialObjects
()
||
isset
(
$this
->
_hints
[
Query
::
HINT_FORCE_PARTIAL_LOAD
]);
$this
->
_identifierMap
=
array
();
$this
->
_
resultPointers
=
array
();
$this
->
_
idTemplate
=
array
();
$this
->
_
resultCounter
=
0
;
$this
->
_
identifierMap
=
$this
->
_
resultPointers
=
$this
->
_
idTemplate
=
$this
->
_fetchedAssociations
=
array
();
$this
->
_resultCounter
=
0
;
foreach
(
$this
->
_rsm
->
aliasMap
as
$dqlAlias
=>
$className
)
{
$this
->
_identifierMap
[
$dqlAlias
]
=
array
();
...
...
@@ -172,25 +173,26 @@ class ObjectHydrator extends AbstractHydrator
*
* @param object $entity The entity to which the collection belongs.
* @param string $name The name of the field on the entity that holds the collection.
* @return PersistentCollection
*/
private
function
initRelatedCollection
(
$entity
,
$name
)
{
$oid
=
spl_object_hash
(
$entity
);
$class
Metadata
=
$this
->
_ce
[
get_class
(
$entity
)];
$class
=
$this
->
_ce
[
get_class
(
$entity
)];
$relation
=
$classMetadata
->
associationMappings
[
$name
];
if
(
!
isset
(
$this
->
_ce
[
$relation
->
targetEntityName
]))
{
$this
->
_ce
[
$relation
->
targetEntityName
]
=
$this
->
_em
->
getClassMetadata
(
$relation
->
targetEntityName
);
}
$coll
=
new
PersistentCollection
(
$this
->
_em
,
$this
->
_ce
[
$relation
->
targetEntityName
]);
$this
->
_collections
[]
=
$coll
;
$coll
->
setOwner
(
$entity
,
$relation
);
$relation
=
$class
->
associationMappings
[
$name
];
$classMetadata
->
reflFields
[
$name
]
->
setValue
(
$entity
,
$coll
);
$this
->
_uow
->
setOriginalEntityProperty
(
$oid
,
$name
,
$coll
);
//$coll = $class->reflFields[$name]->getValue($entity);
//if ( ! $coll) {
// $coll = new Collection;
//}
$pColl
=
new
PersistentCollection
(
$this
->
_em
,
$this
->
_getClassMetadata
(
$relation
->
targetEntityName
));
$this
->
_collections
[]
=
$pColl
;
$pColl
->
setOwner
(
$entity
,
$relation
);
$class
->
reflFields
[
$name
]
->
setValue
(
$entity
,
$pColl
);
$this
->
_uow
->
setOriginalEntityProperty
(
$oid
,
$name
,
$pColl
);
$this
->
_initializedRelations
[
$oid
][
$name
]
=
true
;
return
$coll
;
}
/**
...
...
@@ -210,10 +212,10 @@ class ObjectHydrator extends AbstractHydrator
}
/**
* Gets the last key of a collection/array.
*
* @param <type> $coll
* @return <type>
* @todo Consider inlining this method, introducing $coll->lastKey().
* @param Collection|array $coll
* @return string|integer
*/
private
function
getLastKey
(
$coll
)
{
...
...
@@ -248,6 +250,7 @@ class ObjectHydrator extends AbstractHydrator
// Properly initialize any unfetched associations, if partial objects are not allowed.
if
(
!
$this
->
_allowPartialObjects
)
{
foreach
(
$this
->
_ce
[
$className
]
->
associationMappings
as
$field
=>
$assoc
)
{
// Check if the association is not among the fetch-joined associatons already.
if
(
!
isset
(
$this
->
_fetchedAssociations
[
$className
][
$field
]))
{
if
(
$assoc
->
isOneToOne
())
{
$joinColumns
=
array
();
...
...
@@ -257,7 +260,8 @@ class ObjectHydrator extends AbstractHydrator
if
(
$assoc
->
isLazilyFetched
())
{
// Inject proxy
$this
->
_ce
[
$className
]
->
reflFields
[
$field
]
->
setValue
(
$entity
,
$this
->
_em
->
getProxyFactory
()
->
getAssociationProxy
(
$entity
,
$assoc
,
$joinColumns
));
$this
->
_em
->
getProxyFactory
()
->
getAssociationProxy
(
$entity
,
$assoc
,
$joinColumns
)
);
}
else
{
// Eager load
//TODO: Allow more efficient and configurable batching of these loads
...
...
@@ -265,12 +269,14 @@ class ObjectHydrator extends AbstractHydrator
}
}
else
{
// Inject collection
$
collection
=
$this
->
initRelatedCollection
(
$entity
,
$field
);
if
(
$assoc
->
isLazilyFetched
())
{
$collection
->
setLazyInitialization
(
);
}
else
{
$
pColl
=
new
PersistentCollection
(
$this
->
_em
,
$this
->
_getClassMetadata
(
$assoc
->
targetEntityName
)
);
$pColl
->
setOwner
(
$entity
,
$assoc
);
$this
->
_ce
[
$className
]
->
reflFields
[
$field
]
->
setValue
(
$entity
,
$pColl
);
if
(
!
$assoc
->
isLazilyFetched
())
{
//TODO: Allow more efficient and configurable batching of these loads
$assoc
->
load
(
$entity
,
$collection
,
$this
->
_em
);
$assoc
->
load
(
$entity
,
$pColl
,
$this
->
_em
);
}
else
{
$pColl
->
setInitialized
(
false
);
}
}
}
...
...
@@ -280,6 +286,22 @@ class ObjectHydrator extends AbstractHydrator
return
$entity
;
}
/**
* Gets a ClassMetadata instance from the local cache.
* If the instance is not yet in the local cache, it is loaded into the
* local cache.
*
* @param string $className The name of the class.
* @return ClassMetadata
*/
private
function
_getClassMetadata
(
$className
)
{
if
(
!
isset
(
$this
->
_ce
[
$className
]))
{
$this
->
_ce
[
$className
]
=
$this
->
_em
->
getClassMetadata
(
$className
);
}
return
$this
->
_ce
[
$className
];
}
/**
* Sets a related element.
*
...
...
@@ -463,7 +485,6 @@ class ObjectHydrator extends AbstractHydrator
$index
=
$this
->
_identifierMap
[
$dqlAlias
][
$id
[
$dqlAlias
]];
}
$this
->
updateResultPointer
(
$result
,
$index
,
$dqlAlias
);
//unset($rowData[$dqlAlias]);
}
}
...
...
lib/Doctrine/ORM/Mapping/AssociationMapping.php
View file @
62446f0f
...
...
@@ -412,7 +412,6 @@ abstract class AssociationMapping
*/
protected
function
_getPrivateValue
(
ClassMetadata
$class
,
$entity
,
$column
)
{
$reflField
=
$class
->
getReflectionProperty
(
$class
->
getFieldName
(
$column
));
return
$reflField
->
getValue
(
$entity
);
return
$class
->
reflFields
[
$class
->
fieldNames
[
$column
]]
->
getValue
(
$entity
);
}
}
lib/Doctrine/ORM/Mapping/ClassMetadata.php
View file @
62446f0f
...
...
@@ -405,10 +405,10 @@ final class ClassMetadata
public
function
__construct
(
$entityName
)
{
$this
->
name
=
$entityName
;
$this
->
namespace
=
substr
(
$entityName
,
0
,
strrpos
(
$entityName
,
'\\'
));
$this
->
primaryTable
[
'name'
]
=
str_replace
(
$this
->
namespace
.
'\\'
,
''
,
$this
->
name
);
$this
->
rootEntityName
=
$entityName
;
$this
->
reflClass
=
new
\ReflectionClass
(
$entityName
);
$this
->
namespace
=
$this
->
reflClass
->
getNamespaceName
();
$this
->
primaryTable
[
'name'
]
=
$this
->
reflClass
->
getShortName
();
$this
->
rootEntityName
=
$entityName
;
}
/**
...
...
lib/Doctrine/ORM/Mapping/ManyToManyMapping.php
View file @
62446f0f
...
...
@@ -70,7 +70,7 @@ class ManyToManyMapping extends AssociationMapping
/**
* Initializes a new ManyToManyMapping.
*
* @param array $mapping
The mapping informa
tion.
* @param array $mapping
The mapping defini
tion.
*/
public
function
__construct
(
array
$mapping
)
{
...
...
@@ -86,7 +86,7 @@ class ManyToManyMapping extends AssociationMapping
protected
function
_validateAndCompleteMapping
(
array
$mapping
)
{
parent
::
_validateAndCompleteMapping
(
$mapping
);
if
(
$this
->
isOwningSide
()
)
{
if
(
$this
->
isOwningSide
)
{
// owning side MUST have a join table
if
(
!
isset
(
$mapping
[
'joinTable'
]))
{
throw
MappingException
::
joinTableRequired
(
$mapping
[
'fieldName'
]);
...
...
@@ -143,15 +143,19 @@ class ManyToManyMapping extends AssociationMapping
* Loads entities in $targetCollection using $em.
* The data of $sourceEntity are used to restrict the collection
* via the join table.
*
* @param object The owner of the collection.
* @param object The collection to populate.
* @param array
*/
public
function
load
(
$sourceEntity
,
$targetCollection
,
$em
,
array
$joinColumnValues
=
array
())
{
$sourceClass
=
$em
->
getClassMetadata
(
$this
->
sourceEntityName
);
$joinTableConditions
=
array
();
if
(
$this
->
isOwningSide
())
{
$joinTable
=
$this
->
getJoinTable
()
;
$joinClauses
=
$this
->
getTargetToRelationKeyColumns
()
;
foreach
(
$this
->
getSourceToRelationKeyColumns
()
as
$sourceKeyColumn
=>
$relationKeyColumn
)
{
$joinTable
=
$this
->
joinTable
;
$joinClauses
=
$this
->
targetToRelationKeyColumns
;
foreach
(
$this
->
sourceToRelationKeyColumns
as
$sourceKeyColumn
=>
$relationKeyColumn
)
{
// getting id
if
(
isset
(
$sourceClass
->
reflFields
[
$sourceKeyColumn
]))
{
$joinTableConditions
[
$relationKeyColumn
]
=
$this
->
_getPrivateValue
(
$sourceClass
,
$sourceEntity
,
$sourceKeyColumn
);
...
...
@@ -160,11 +164,11 @@ class ManyToManyMapping extends AssociationMapping
}
}
}
else
{
$owningAssoc
=
$em
->
getClassMetadata
(
$this
->
targetEntityName
)
->
getAssociationMapping
(
$this
->
mappedByFieldName
)
;
$joinTable
=
$owningAssoc
->
getJoinTable
()
;
$owningAssoc
=
$em
->
getClassMetadata
(
$this
->
targetEntityName
)
->
associationMappings
[
$this
->
mappedByFieldName
]
;
$joinTable
=
$owningAssoc
->
joinTable
;
// TRICKY: since the association is inverted source and target are flipped
$joinClauses
=
$owningAssoc
->
getSourceToRelationKeyColumns
()
;
foreach
(
$owningAssoc
->
getTargetToRelationKeyColumns
()
as
$sourceKeyColumn
=>
$relationKeyColumn
)
{
$joinClauses
=
$owningAssoc
->
sourceToRelationKeyColumns
;
foreach
(
$owningAssoc
->
targetToRelationKeyColumns
as
$sourceKeyColumn
=>
$relationKeyColumn
)
{
// getting id
if
(
isset
(
$sourceClass
->
reflFields
[
$sourceKeyColumn
]))
{
$joinTableConditions
[
$relationKeyColumn
]
=
$this
->
_getPrivateValue
(
$sourceClass
,
$sourceEntity
,
$sourceKeyColumn
);
...
...
@@ -179,13 +183,11 @@ class ManyToManyMapping extends AssociationMapping
'criteria'
=>
$joinTableConditions
);
$persister
=
$em
->
getUnitOfWork
()
->
getEntityPersister
(
$this
->
targetEntityName
);
$persister
->
loadCollection
(
array
(
$joinTableCriteria
),
$targetCollection
);
$persister
->
load
ManyToMany
Collection
(
array
(
$joinTableCriteria
),
$targetCollection
);
}
/**
* {@inheritdoc}
*
* @override
*/
public
function
isManyToMany
()
{
...
...
lib/Doctrine/ORM/Mapping/OneToManyMapping.php
View file @
62446f0f
...
...
@@ -105,12 +105,21 @@ class OneToManyMapping extends AssociationMapping
return
true
;
}
/**
*
*
* @param $sourceEntity
* @param $targetCollection
* @param $em
* @param $joinColumnValues
* @return unknown_type
*/
public
function
load
(
$sourceEntity
,
$targetCollection
,
$em
,
array
$joinColumnValues
=
array
())
{
$persister
=
$em
->
getUnitOfWork
()
->
getEntityPersister
(
$this
->
targetEntityName
);
// a one-to-many is always inverse (does not have foreign key)
$sourceClass
=
$em
->
getClassMetadata
(
$this
->
sourceEntityName
);
$owningAssoc
=
$em
->
getClassMetadata
(
$this
->
targetEntityName
)
->
getAssociationMapping
(
$this
->
mappedByFieldName
)
;
$owningAssoc
=
$em
->
getClassMetadata
(
$this
->
targetEntityName
)
->
associationMappings
[
$this
->
mappedByFieldName
]
;
// TRICKY: since the association is specular source and target are flipped
foreach
(
$owningAssoc
->
getTargetToSourceKeyColumns
()
as
$sourceKeyColumn
=>
$targetKeyColumn
)
{
// getting id
...
...
@@ -121,6 +130,6 @@ class OneToManyMapping extends AssociationMapping
}
}
$persister
->
loadCollection
(
$conditions
,
$targetCollection
);
$persister
->
load
OneToMany
Collection
(
$conditions
,
$targetCollection
);
}
}
lib/Doctrine/ORM/PersistentCollection.php
View file @
62446f0f
...
...
@@ -46,13 +46,6 @@ use \Closure;
*/
final
class
PersistentCollection
extends
\Doctrine\Common\Collections\Collection
{
/**
* The base type of the collection.
*
* @var string
*/
private
$_type
;
/**
* A snapshot of the collection at the moment it was fetched from the database.
* This is used to create a diff of the collection at commit time.
...
...
@@ -76,13 +69,6 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
*/
private
$_association
;
/**
* The name of the field that is used for collection indexing.
*
* @var string
*/
private
$_keyField
;
/**
* The EntityManager that manages the persistence of the collection.
*
...
...
@@ -112,7 +98,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
private
$_isDirty
=
false
;
/** Whether the collection has already been initialized. */
pr
otected
$_initialized
=
true
;
pr
ivate
$_initialized
=
true
;
/**
* Creates a new persistent collection.
...
...
@@ -120,32 +106,10 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
public
function
__construct
(
EntityManager
$em
,
$class
,
array
$data
=
array
())
{
parent
::
__construct
(
$data
);
$this
->
_type
=
$class
->
name
;
$this
->
_em
=
$em
;
$this
->
_typeClass
=
$class
;
}
/**
* INTERNAL: Sets the key column for this collection
*
* @param string $column
* @return Doctrine_Collection
*/
public
function
setKeyField
(
$fieldName
)
{
$this
->
_keyField
=
$fieldName
;
}
/**
* INTERNAL: returns the name of the key column
*
* @return string
*/
public
function
getKeyField
()
{
return
$this
->
_keyField
;
}
/**
* INTERNAL:
* Sets the collection owner. Used (only?) during hydration.
...
...
@@ -157,6 +121,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
{
$this
->
_owner
=
$entity
;
$this
->
_association
=
$assoc
;
// Check for bidirectionality
if
(
$assoc
->
isInverseSide
())
{
// For sure bi-directional
$this
->
_backRefFieldName
=
$assoc
->
mappedByFieldName
;
...
...
@@ -190,23 +155,18 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
return
$this
->
_typeClass
;
}
public
function
setLazyInitialization
()
{
$this
->
_initialized
=
false
;
}
/**
* INTERNAL:
* Adds an element to a collection during hydration, if it not already set.
* This control is performed to avoid infinite recursion during hydration
* of bidirectional many-to-many collections.
* Adds an element to a collection during hydration.
*
* @param mixed $element The element to add.
*/
public
function
hydrateAdd
(
$element
,
$setBackRef
=
true
)
public
function
hydrateAdd
(
$element
)
{
parent
::
add
(
$element
);
if
(
$this
->
_backRefFieldName
and
$setBackRef
)
{
// If _backRefFieldName is set, then the association is bidirectional
// and we need to set the back reference.
if
(
$this
->
_backRefFieldName
)
{
// Set back reference to owner
if
(
$this
->
_association
->
isOneToMany
())
{
// OneToMany
...
...
@@ -214,9 +174,8 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
->
setValue
(
$element
,
$this
->
_owner
);
}
else
{
// ManyToMany
$otherCollection
=
$this
->
_typeClass
->
reflFields
[
$this
->
_backRefFieldName
]
->
getValue
(
$element
);
$otherCollection
->
hydrateAdd
(
$this
->
_owner
,
false
);
$this
->
_typeClass
->
reflFields
[
$this
->
_backRefFieldName
]
->
getValue
(
$element
)
->
add
(
$this
->
_owner
);
}
}
}
...
...
@@ -234,12 +193,12 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
}
/**
* Initializes the collection by loading its contents from the database.
* Initializes the collection by loading its contents from the database
* if the collection is not yet initialized.
*/
private
function
_initialize
()
{
if
(
!
$this
->
_initialized
)
{
parent
::
clear
();
if
(
!
$this
->
_initialized
)
{
$this
->
_association
->
load
(
$this
->
_owner
,
$this
,
$this
->
_em
);
$this
->
_initialized
=
true
;
}
...
...
@@ -346,53 +305,32 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
$this
->
_initialized
=
$bool
;
}
/* Serializable implementation */
/**
* Called by PHP when this collection is serialized. Ensures that only the
* elements are properly serialized.
* Checks whether this collection has been initialized.
*
* @internal Tried to implement Serializable first but that did not work well
* with circular references. This solution seems simpler and works well.
*/
public
function
__sleep
()
{
return
array
(
'_elements'
,
'_initialized'
);
}
/**
* Decorated Collection methods.
* @return boolean
*/
public
function
unwrap
()
public
function
isInitialized
()
{
$this
->
_initialize
();
return
parent
::
unwrap
();
return
$this
->
_initialized
;
}
/** {@inheritdoc} */
public
function
first
()
{
$this
->
_initialize
();
return
parent
::
first
();
}
/** {@inheritdoc} */
public
function
last
()
{
$this
->
_initialize
();
return
parent
::
last
();
}
public
function
key
()
{
$this
->
_initialize
();
return
parent
::
key
();
}
/**
* Removes an element from the collection.
*
* @param mixed $key
* @return boolean
* @override
* {@inheritdoc}
*/
public
function
remove
(
$key
)
{
...
...
@@ -408,6 +346,9 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
return
$removed
;
}
/**
* {@inheritdoc}
*/
public
function
removeElement
(
$element
)
{
$this
->
_initialize
();
...
...
@@ -416,34 +357,9 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
return
$result
;
}
public
function
offsetExists
(
$offset
)
{
$this
->
_initialize
();
return
parent
::
offsetExists
(
$offset
);
}
public
function
offsetGet
(
$offset
)
{
$this
->
_initialize
();
return
parent
::
offsetGet
(
$offset
);
}
public
function
offsetSet
(
$offset
,
$value
)
{
$this
->
_initialize
();
$result
=
parent
::
offsetSet
(
$offset
,
$value
);
$this
->
_changed
();
return
$result
;
}
public
function
offsetUnset
(
$offset
)
{
$this
->
_initialize
();
$result
=
parent
::
offsetUnset
(
$offset
);
$this
->
_changed
();
return
$result
;
}
/**
* {@inheritdoc}
*/
public
function
containsKey
(
$key
)
{
$this
->
_initialize
();
...
...
@@ -451,8 +367,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
}
/**
* Checks whether an element is contained in the collection.
* This is an O(n) operation.
* {@inheritdoc}
*/
public
function
contains
(
$element
)
{
...
...
@@ -460,30 +375,45 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
return
parent
::
contains
(
$element
);
}
/**
* {@inheritdoc}
*/
public
function
exists
(
Closure
$p
)
{
$this
->
_initialize
();
return
parent
::
exists
(
$p
);
}
/**
* {@inheritdoc}
*/
public
function
search
(
$element
)
{
$this
->
_initialize
();
return
parent
::
search
(
$element
);
}
/**
* {@inheritdoc}
*/
public
function
get
(
$key
)
{
$this
->
_initialize
();
return
parent
::
get
(
$key
);
}
/**
* {@inheritdoc}
*/
public
function
getKeys
()
{
$this
->
_initialize
();
return
parent
::
getKeys
();
}
/**
* {@inheritdoc}
*/
public
function
getElements
()
{
$this
->
_initialize
();
...
...
@@ -491,7 +421,7 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
}
/**
*
@override
*
{@inheritdoc}
*/
public
function
count
()
{
...
...
@@ -500,49 +430,45 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
}
/**
* When the collection is used as a Map this is like put(key,value)/add(key,value).
* When the collection is used as a List this is like add(position,value).
*
* @param integer $key
* @param mixed $value
* @override
* {@inheritdoc}
*/
public
function
set
(
$key
,
$value
)
{
$this
->
_initialize
();
$result
=
parent
::
set
(
$key
,
$value
);
parent
::
set
(
$key
,
$value
);
$this
->
_changed
();
return
$result
;
}
/**
* Adds an element to the collection.
*
* @param mixed $value
* @param string $key
* @return boolean Always TRUE.
* @override
* {@inheritdoc}
*/
public
function
add
(
$value
)
{
$this
->
_initialize
();
$result
=
parent
::
add
(
$value
);
parent
::
add
(
$value
);
$this
->
_changed
();
return
$result
;
return
true
;
}
/**
* {@inheritdoc}
*/
public
function
isEmpty
()
{
$this
->
_initialize
();
return
parent
::
isEmpty
();
}
/**
* {@inheritdoc}
*/
public
function
getIterator
()
{
$this
->
_initialize
();
return
parent
::
getIterator
();
}
/**
* {@inheritdoc}
*/
public
function
map
(
Closure
$func
)
{
$this
->
_initialize
();
...
...
@@ -551,18 +477,27 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
return
$result
;
}
/**
* {@inheritdoc}
*/
public
function
filter
(
Closure
$p
)
{
$this
->
_initialize
();
return
parent
::
filter
(
$p
);
}
/**
* {@inheritdoc}
*/
public
function
forAll
(
Closure
$p
)
{
$this
->
_initialize
();
return
parent
::
forAll
(
$p
);
}
/**
* {@inheritdoc}
*/
public
function
partition
(
Closure
$p
)
{
$this
->
_initialize
();
...
...
@@ -570,23 +505,29 @@ final class PersistentCollection extends \Doctrine\Common\Collections\Collection
}
/**
*
Clears the collection.
*
{@inheritdoc}
*/
public
function
clear
()
{
$this
->
_initialize
();
//TODO: Register collection as dirty with the UoW if necessary
//TODO: If oneToMany() && shouldDeleteOrphan() delete entities
/*if ($this->_association->isOneToMany() && $this->_association->shouldDeleteOrphans) {
foreach ($this->_data as $entity) {
$this->_em->remove($entity);
}
}*/
$result
=
parent
::
clear
();
if
(
$this
->
_association
->
isOwningSide
)
{
$this
->
_changed
();
$this
->
_em
->
getUnitOfWork
()
->
scheduleCollectionDeletion
(
$this
);
}
return
$result
;
}
/**
* Called by PHP when this collection is serialized. Ensures that only the
* elements are properly serialized.
*
* @internal Tried to implement Serializable first but that did not work well
* with circular references. This solution seems simpler and works well.
*/
public
function
__sleep
()
{
return
array
(
'_elements'
);
}
}
lib/Doctrine/ORM/Persisters/JoinedSubclassPersister.php
View file @
62446f0f
...
...
@@ -273,7 +273,7 @@ class JoinedSubclassPersister extends StandardEntityPersister
* @todo Quote identifier.
* @override
*/
protected
function
_getSelect
SingleEntity
Sql
(
array
&
$criteria
)
protected
function
_getSelect
Entities
Sql
(
array
&
$criteria
)
{
$tableAliases
=
array
();
$aliasIndex
=
1
;
...
...
lib/Doctrine/ORM/Persisters/StandardEntityPersister.php
View file @
62446f0f
...
...
@@ -395,16 +395,20 @@ class StandardEntityPersister
*/
public
function
load
(
array
$criteria
,
$entity
=
null
)
{
$stmt
=
$this
->
_conn
->
prepare
(
$this
->
_getSelect
SingleEntity
Sql
(
$criteria
));
$stmt
=
$this
->
_conn
->
prepare
(
$this
->
_getSelect
Entities
Sql
(
$criteria
));
$stmt
->
execute
(
array_values
(
$criteria
));
$result
=
$stmt
->
fetch
(
Connection
::
FETCH_ASSOC
);
$stmt
->
closeCursor
();
return
$this
->
_createEntity
(
$result
,
$entity
);
}
public
function
loadCollection
(
array
$criteria
,
PersistentCollection
$collection
)
/**
*
*
*/
public
function
loadOneToManyCollection
(
array
$criteria
,
PersistentCollection
$collection
)
{
$sql
=
$this
->
_getSelect
SingleEntity
Sql
(
$criteria
);
$sql
=
$this
->
_getSelect
Entities
Sql
(
$criteria
);
$stmt
=
$this
->
_conn
->
prepare
(
$sql
);
$stmt
->
execute
(
array_values
(
$criteria
));
while
(
$result
=
$stmt
->
fetch
(
Connection
::
FETCH_ASSOC
))
{
...
...
@@ -413,6 +417,27 @@ class StandardEntityPersister
$stmt
->
closeCursor
();
}
/**
*
*
*/
public
function
loadManyToManyCollection
(
array
$criteria
,
PersistentCollection
$collection
)
{
$sql
=
$this
->
_getSelectManyToManyEntityCollectionSql
(
$criteria
);
$stmt
=
$this
->
_conn
->
prepare
(
$sql
);
$stmt
->
execute
(
array_values
(
$criteria
));
while
(
$result
=
$stmt
->
fetch
(
Connection
::
FETCH_ASSOC
))
{
$collection
->
add
(
$this
->
_createEntity
(
$result
));
}
$stmt
->
closeCursor
();
}
/**
*
* @param $result
* @param $entity
* @return object
*/
private
function
_createEntity
(
$result
,
$entity
=
null
)
{
$data
=
array
();
...
...
@@ -469,7 +494,7 @@ class StandardEntityPersister
$coll
->
setOwner
(
$entity
,
$assoc
);
$this
->
_class
->
reflFields
[
$field
]
->
setValue
(
$entity
,
$coll
);
if
(
$assoc
->
isLazilyFetched
())
{
$coll
->
set
LazyInitialization
(
);
$coll
->
set
Initialized
(
false
);
}
else
{
//TODO: Allow more efficient and configurable batching of these loads
$assoc
->
load
(
$entity
,
$coll
,
$this
->
_em
);
...
...
@@ -490,7 +515,7 @@ class StandardEntityPersister
* JoinClauses are used to restrict the result returned but only columns of this entity are selected (@see _getJoinSql()).
* @return string The SQL.
*/
protected
function
_getSelect
SingleEntity
Sql
(
array
&
$criteria
)
protected
function
_getSelect
Entities
Sql
(
array
&
$criteria
)
{
$columnList
=
''
;
foreach
(
$this
->
_class
->
columnNames
as
$column
)
{
...
...
@@ -527,6 +552,7 @@ class StandardEntityPersister
unset
(
$criteria
[
$field
]);
continue
;
}
if
(
isset
(
$this
->
_class
->
columnNames
[
$field
]))
{
$columnName
=
$this
->
_class
->
columnNames
[
$field
];
}
else
if
(
in_array
(
$field
,
$joinColumnNames
))
{
...
...
@@ -544,7 +570,52 @@ class StandardEntityPersister
}
/**
* Builds a LEFT JOIN sql query part using $joinClause
* Gets the SQL to select a collection of entities in a many-many association.
*
* @return string
*/
protected
function
_getSelectManyToManyEntityCollectionSql
(
array
&
$criteria
)
{
$columnList
=
''
;
foreach
(
$this
->
_class
->
columnNames
as
$column
)
{
if
(
$columnList
!=
''
)
$columnList
.=
', '
;
$columnList
.=
$this
->
_conn
->
quoteIdentifier
(
$column
);
}
if
(
!
$this
->
_em
->
getConfiguration
()
->
getAllowPartialObjects
())
{
foreach
(
$this
->
_class
->
associationMappings
as
$assoc
)
{
if
(
$assoc
->
isOwningSide
&&
$assoc
->
isOneToOne
())
{
foreach
(
$assoc
->
targetToSourceKeyColumns
as
$srcColumn
)
{
$columnList
.=
', '
.
$this
->
_conn
->
quoteIdentifier
(
$srcColumn
);
}
}
}
}
$joinSql
=
''
;
$conditionSql
=
''
;
foreach
(
$criteria
as
$field
=>
$value
)
{
if
(
$conditionSql
!=
''
)
{
$conditionSql
.=
' AND '
;
}
$joinSql
.=
$this
->
_getJoinSql
(
$value
);
foreach
(
$value
[
'criteria'
]
as
$nestedField
=>
$nestedValue
)
{
$columnName
=
"
{
$value
[
'table'
]
}
.
{
$nestedField
}
"
;
$conditionSql
.=
$this
->
_conn
->
quoteIdentifier
(
$columnName
)
.
' = ?'
;
$criteria
[
$columnName
]
=
$nestedValue
;
}
unset
(
$criteria
[
$field
]);
}
return
'SELECT '
.
$columnList
.
' FROM '
.
$this
->
_class
->
primaryTable
[
'name'
]
.
$joinSql
.
' WHERE '
.
$conditionSql
;
}
/**
* Builds an INNER JOIN sql query part using $joinClause.
*
* @param array $joinClause keys are:
* 'table' => table to join
* 'join' => array of [sourceField => joinTableField]
...
...
@@ -558,6 +629,6 @@ class StandardEntityPersister
$clauses
[]
=
$this
->
_class
->
getTableName
()
.
".
{
$sourceField
}
= "
.
"
{
$joinClause
[
'table'
]
}
.
{
$joinTableField
}
"
;
}
return
" LEFT JOIN
{
$joinClause
[
'table'
]
}
ON "
.
implode
(
' AND '
,
$clauses
);
return
' INNER JOIN '
.
$joinClause
[
'table'
]
.
' ON '
.
implode
(
' AND '
,
$clauses
);
}
}
lib/Doctrine/ORM/Query/SqlWalker.php
View file @
62446f0f
...
...
@@ -248,11 +248,8 @@ class SqlWalker implements TreeWalker
$qComp
=
$this
->
_queryComponents
[
$dqlAlias
];
$columnName
=
$qComp
[
'metadata'
]
->
getColumnName
(
$parts
[
0
]);
$sql
=
$this
->
getSqlTableAlias
(
$qComp
[
'metadata'
]
->
getTableName
(),
$dqlAlias
)
.
'.'
.
$columnName
;
if
(
$orderByItem
->
isAsc
())
{
$sql
.=
' ASC '
;
}
else
if
(
$orderByItem
->
isDesc
())
{
$sql
.=
' DESC '
;
}
$sql
.=
$orderByItem
->
isDesc
()
?
' DESC'
:
' ASC'
;
return
$sql
;
}
...
...
tests/Doctrine/Tests/Models/CMS/CmsUser.php
View file @
62446f0f
...
...
@@ -2,6 +2,8 @@
namespace
Doctrine\Tests\Models\CMS
;
use
Doctrine\Common\Collections\Collection
;
/**
* @Entity
* @Table(name="cms_users")
...
...
@@ -40,11 +42,18 @@ class CmsUser
/**
* @ManyToMany(targetEntity="CmsGroup", cascade={"persist"})
* @JoinTable(name="cms_users_groups",
joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")},
inverseJoinColumns={@JoinColumn(name="group_id", referencedColumnName="id")})
* joinColumns={@JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@JoinColumn(name="group_id", referencedColumnName="id")}
* )
*/
public
$groups
;
public
function
__construct
()
{
$this
->
phonenumbers
=
new
Collection
;
$this
->
articles
=
new
Collection
;
$this
->
groups
=
new
Collection
;
}
public
function
getId
()
{
return
$this
->
id
;
}
...
...
tests/Doctrine/Tests/ORM/Functional/ManyToManyBidirectionalAssociationTest.php
View file @
62446f0f
...
...
@@ -28,7 +28,9 @@ class ManyToManyBidirectionalAssociationTest extends AbstractManyToManyAssociati
$this
->
useModelSet
(
'ecommerce'
);
parent
::
setUp
();
$this
->
firstProduct
=
new
ECommerceProduct
();
$this
->
firstProduct
->
setName
(
"First Product"
);
$this
->
secondProduct
=
new
ECommerceProduct
();
$this
->
secondProduct
->
setName
(
"Second Product"
);
$this
->
firstCategory
=
new
ECommerceCategory
();
$this
->
firstCategory
->
setName
(
"Business"
);
$this
->
secondCategory
=
new
ECommerceCategory
();
...
...
@@ -102,6 +104,11 @@ class ManyToManyBidirectionalAssociationTest extends AbstractManyToManyAssociati
$query
=
$this
->
_em
->
createQuery
(
'SELECT p FROM Doctrine\Tests\Models\ECommerce\ECommerceProduct p order by p.id'
);
$products
=
$query
->
getResultList
();
$this
->
assertEquals
(
2
,
count
(
$products
));
$this
->
assertEquals
(
0
,
count
(
$products
[
0
]
->
getCategories
()
->
unwrap
()));
$this
->
assertEquals
(
0
,
count
(
$products
[
1
]
->
getCategories
()
->
unwrap
()));
$this
->
assertLoadingOfOwningSide
(
$products
);
}
...
...
@@ -128,12 +135,17 @@ class ManyToManyBidirectionalAssociationTest extends AbstractManyToManyAssociati
public
function
assertLoadingOfOwningSide
(
$products
)
{
list
(
$firstProduct
,
$secondProduct
)
=
$products
;
$this
->
assertEquals
(
2
,
count
(
$firstProduct
->
getCategories
()));
$this
->
assertEquals
(
2
,
count
(
$secondProduct
->
getCategories
()));
$categories
=
$firstProduct
->
getCategories
();
$firstCategoryProducts
=
$categories
[
0
]
->
getProducts
();
$secondCategoryProducts
=
$categories
[
1
]
->
getProducts
();
$firstProductCategories
=
$firstProduct
->
getCategories
();
$secondProductCategories
=
$secondProduct
->
getCategories
();
$this
->
assertEquals
(
2
,
count
(
$firstProductCategories
));
$this
->
assertEquals
(
2
,
count
(
$secondProductCategories
));
$this
->
assertTrue
(
$firstProductCategories
[
0
]
===
$secondProductCategories
[
0
]);
$this
->
assertTrue
(
$firstProductCategories
[
1
]
===
$secondProductCategories
[
1
]);
$firstCategoryProducts
=
$firstProductCategories
[
0
]
->
getProducts
();
$secondCategoryProducts
=
$firstProductCategories
[
1
]
->
getProducts
();
$this
->
assertEquals
(
2
,
count
(
$firstCategoryProducts
));
$this
->
assertEquals
(
2
,
count
(
$secondCategoryProducts
));
...
...
tests/Doctrine/Tests/ORM/Query/SelectSqlGenerationTest.php
View file @
62446f0f
...
...
@@ -70,7 +70,7 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{
$this
->
assertSqlGeneration
(
'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u ORDER BY u.id'
,
'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ ORDER BY f0_.id ASC
'
'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ ORDER BY f0_.id ASC'
);
}
...
...
@@ -78,14 +78,14 @@ class SelectSqlGenerationTest extends \Doctrine\Tests\OrmTestCase
{
$this
->
assertSqlGeneration
(
'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u ORDER BY u.id asc'
,
'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ ORDER BY f0_.id ASC
'
'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ ORDER BY f0_.id ASC'
);
}
public
function
testSupportsOrderByDesc
()
{
$this
->
assertSqlGeneration
(
'SELECT u FROM Doctrine\Tests\Models\Forum\ForumUser u ORDER BY u.id desc'
,
'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ ORDER BY f0_.id DESC
'
'SELECT f0_.id AS id0, f0_.username AS username1 FROM forum_users f0_ ORDER BY f0_.id DESC'
);
}
...
...
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