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
59cf1f74
Commit
59cf1f74
authored
Jul 18, 2009
by
romanb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[2.0] added entity lifecycle events.
parent
227667c9
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
268 additions
and
20 deletions
+268
-20
LifecycleEventArgs.php
lib/Doctrine/ORM/Event/LifecycleEventArgs.php
+1
-6
Events.php
lib/Doctrine/ORM/Events.php
+66
-3
AnnotationDriver.php
lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
+31
-1
DoctrineAnnotations.php
lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php
+1
-0
UnitOfWork.php
lib/Doctrine/ORM/UnitOfWork.php
+82
-10
AllTests.php
tests/Doctrine/Tests/ORM/Functional/AllTests.php
+1
-0
LifecycleCallbackTest.php
...s/Doctrine/Tests/ORM/Functional/LifecycleCallbackTest.php
+86
-0
No files found.
lib/Doctrine/ORM/Event/LifecycleEventArgs.php
View file @
59cf1f74
...
...
@@ -7,7 +7,7 @@ class LifecycleEventArgs extends \Doctrine\Common\EventArgs
private
$_em
;
private
$_entity
;
public
function
__construct
(
$entity
,
\Doctrine\ORM\EntityManager
$em
)
public
function
__construct
(
$entity
)
{
$this
->
_entity
=
$entity
;
}
...
...
@@ -16,9 +16,4 @@ class LifecycleEventArgs extends \Doctrine\Common\EventArgs
{
return
$this
->
_entity
;
}
public
function
getEntityManager
()
{
return
$this
->
_em
;
}
}
\ No newline at end of file
lib/Doctrine/ORM/Events.php
View file @
59cf1f74
...
...
@@ -32,13 +32,76 @@ namespace Doctrine\ORM;
final
class
Events
{
private
function
__construct
()
{}
/**
* The preDelete event occurs for a given entity before the respective
* EntityManager delete operation for that entity is executed.
*
* This is an entity lifecycle event.
*
* @var string
*/
const
preDelete
=
'preDelete'
;
/**
* The postDelete event occurs for an entity after the entity has
* been deleted. It will be invoked after the database delete operations.
*
* This is an entity lifecycle event.
*
* @var string
*/
const
postDelete
=
'postDelete'
;
const
preInsert
=
'preInsert'
;
const
postInsert
=
'postInsert'
;
/**
* The preSave event occurs for a given entity before the respective
* EntityManager save operation for that entity is executed.
*
* This is an entity lifecycle event.
*
* @var string
*/
const
preSave
=
'preSave'
;
/**
* The postSave event occurs for an entity after the entity has
* been made persistent. It will be invoked after the database insert operations.
* Generated primary key values are available in the postSave event.
*
* This is an entity lifecycle event.
*
* @var string
*/
const
postSave
=
'postSave'
;
/**
* The preUpdate event occurs before the database update operations to
* entity data.
*
* This is an entity lifecycle event.
*
* @var string
*/
const
preUpdate
=
'preUpdate'
;
/**
* The postUpdate event occurs after the database update operations to
* entity data.
*
* This is an entity lifecycle event.
*
* @var string
*/
const
postUpdate
=
'postUpdate'
;
/**
* The postLoad event occurs for an entity after the entity has been loaded
* into the current EntityManager from the database or after the refresh operation
* has been applied to it.
*
* This is an entity lifecycle event.
*
* @var string
*/
const
postLoad
=
'postLoad'
;
/**
* The loadClassMetadata event occurs after the mapping metadata for a class
* has been loaded from a mapping source (annotations/xml/yaml).
*
* @var string
*/
const
loadClassMetadata
=
'loadClassMetadata'
;
}
\ No newline at end of file
lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php
View file @
59cf1f74
...
...
@@ -231,9 +231,39 @@ class AnnotationDriver implements Driver
$mapping
[
'mappedBy'
]
=
$manyToManyAnnot
->
mappedBy
;
$mapping
[
'cascade'
]
=
$manyToManyAnnot
->
cascade
;
$metadata
->
mapManyToMany
(
$mapping
);
}
}
// Evaluate LifecycleListener annotation
if
((
$lifecycleListenerAnnot
=
$this
->
_reader
->
getClassAnnotation
(
$class
,
'Doctrine\ORM\Mapping\LifecycleListener'
)))
{
foreach
(
$class
->
getMethods
()
as
$method
)
{
if
(
$method
->
isPublic
())
{
$annotations
=
$this
->
_reader
->
getMethodAnnotations
(
$method
);
if
(
isset
(
$annotations
[
'Doctrine\ORM\Mapping\PreSave'
]))
{
$metadata
->
addLifecycleCallback
(
$method
->
getName
(),
\Doctrine\ORM\Events
::
preSave
);
}
if
(
isset
(
$annotations
[
'Doctrine\ORM\Mapping\PostSave'
]))
{
$metadata
->
addLifecycleCallback
(
$method
->
getName
(),
\Doctrine\ORM\Events
::
postSave
);
}
if
(
isset
(
$annotations
[
'Doctrine\ORM\Mapping\PreUpdate'
]))
{
$metadata
->
addLifecycleCallback
(
$method
->
getName
(),
\Doctrine\ORM\Events
::
preUpdate
);
}
if
(
isset
(
$annotations
[
'Doctrine\ORM\Mapping\PostUpdate'
]))
{
$metadata
->
addLifecycleCallback
(
$method
->
getName
(),
\Doctrine\ORM\Events
::
postUpdate
);
}
if
(
isset
(
$annotations
[
'Doctrine\ORM\Mapping\PreDelete'
]))
{
$metadata
->
addLifecycleCallback
(
$method
->
getName
(),
\Doctrine\ORM\Events
::
preDelete
);
}
if
(
isset
(
$annotations
[
'Doctrine\ORM\Mapping\PostDelete'
]))
{
$metadata
->
addLifecycleCallback
(
$method
->
getName
(),
\Doctrine\ORM\Events
::
postDelete
);
}
if
(
isset
(
$annotations
[
'Doctrine\ORM\Mapping\PostLoad'
]))
{
$metadata
->
addLifecycleCallback
(
$method
->
getName
(),
\Doctrine\ORM\Events
::
postLoad
);
}
}
}
}
}
/**
...
...
lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php
View file @
59cf1f74
...
...
@@ -103,6 +103,7 @@ final class SequenceGenerator extends \Doctrine\Common\Annotations\Annotation {
final
class
ChangeTrackingPolicy
extends
\Doctrine\Common\Annotations\Annotation
{}
/* Annotations for lifecycle callbacks */
final
class
LifecycleListener
extends
\Doctrine\Common\Annotations\Annotation
{}
final
class
PreSave
extends
\Doctrine\Common\Annotations\Annotation
{}
final
class
PostSave
extends
\Doctrine\Common\Annotations\Annotation
{}
final
class
PreUpdate
extends
\Doctrine\Common\Annotations\Annotation
{}
...
...
lib/Doctrine/ORM/UnitOfWork.php
View file @
59cf1f74
...
...
@@ -25,6 +25,7 @@ use Doctrine\Common\Collections\Collection;
use
Doctrine\Common\DoctrineException
;
use
Doctrine\Common\PropertyChangedListener
;
use
Doctrine\ORM\Events
;
use
Doctrine\ORM\Event\LifecycleEventArgs
;
use
Doctrine\ORM\Internal\CommitOrderCalculator
;
use
Doctrine\ORM\Internal\CommitOrderNode
;
use
Doctrine\ORM\PersistentCollection
;
...
...
@@ -634,18 +635,28 @@ class UnitOfWork implements PropertyChangedListener
{
$className
=
$class
->
name
;
$persister
=
$this
->
getEntityPersister
(
$className
);
$hasLifecycleCallbacks
=
isset
(
$class
->
lifecycleCallbacks
[
Events
::
postSave
]);
$hasListeners
=
$this
->
_evm
->
hasListeners
(
Events
::
postSave
);
if
(
$hasLifecycleCallbacks
||
$hasListeners
)
{
$entities
=
array
();
}
foreach
(
$this
->
_entityInsertions
as
$oid
=>
$entity
)
{
if
(
get_class
(
$entity
)
==
$className
)
{
$persister
->
addInsert
(
$entity
);
unset
(
$this
->
_entityInsertions
[
$oid
]);
if
(
$hasLifecycleCallbacks
||
$hasListeners
)
{
$entities
[]
=
$entity
;
}
}
}
$postInsertIds
=
$persister
->
executeInserts
();
if
(
$postInsertIds
)
{
// Persister returned a post-insert IDs
foreach
(
$postInsertIds
as
$id
=>
$entity
)
{
// Persister returned a post-insert ID
$oid
=
spl_object_hash
(
$entity
);
$idField
=
$class
->
identifier
[
0
];
$class
->
reflFields
[
$idField
]
->
setValue
(
$entity
,
$id
);
...
...
@@ -655,6 +666,17 @@ class UnitOfWork implements PropertyChangedListener
$this
->
addToIdentityMap
(
$entity
);
}
}
if
(
$hasLifecycleCallbacks
||
$hasListeners
)
{
foreach
(
$entities
as
$entity
)
{
if
(
$hasLifecycleCallbacks
)
{
$class
->
invokeLifecycleCallbacks
(
Events
::
postSave
,
$entity
);
}
if
(
$hasListeners
)
{
$this
->
_evm
->
dispatchEvent
(
Events
::
postSave
,
new
LifecycleEventArgs
(
$entity
));
}
}
}
}
/**
...
...
@@ -666,14 +688,36 @@ class UnitOfWork implements PropertyChangedListener
{
$className
=
$class
->
name
;
$persister
=
$this
->
getEntityPersister
(
$className
);
$hasPreUpdateLifecycleCallbacks
=
isset
(
$class
->
lifecycleCallbacks
[
Events
::
preUpdate
]);
$hasPreUpdateListeners
=
$this
->
_evm
->
hasListeners
(
Events
::
preUpdate
);
$hasPostUpdateLifecycleCallbacks
=
isset
(
$class
->
lifecycleCallbacks
[
Events
::
postUpdate
]);
$hasPostUpdateListeners
=
$this
->
_evm
->
hasListeners
(
Events
::
postUpdate
);
foreach
(
$this
->
_entityUpdates
as
$oid
=>
$entity
)
{
if
(
get_class
(
$entity
)
==
$className
)
{
//TODO: Fire preUpdate
if
(
$hasPreUpdateLifecycleCallbacks
)
{
$class
->
invokeLifecycleCallbacks
(
Events
::
preUpdate
,
$entity
);
if
(
!
$hasPreUpdateListeners
)
{
// Need to recompute entity changeset to detect changes made in the callback.
$this
->
computeSingleEntityChangeSet
(
$class
,
$entity
);
}
}
if
(
$hasPreUpdateListeners
)
{
$this
->
_evm
->
dispatchEvent
(
Events
::
preUpdate
,
new
LifecycleEventArgs
(
$entity
));
// Need to recompute entity changeset to detect changes made in the listener.
$this
->
computeSingleEntityChangeSet
(
$class
,
$entity
);
}
$persister
->
update
(
$entity
);
unset
(
$this
->
_entityUpdates
[
$oid
]);
//TODO: Fire postUpdate
if
(
$hasPostUpdateLifecycleCallbacks
)
{
$class
->
invokeLifecycleCallbacks
(
Events
::
postUpdate
,
$entity
);
}
if
(
$hasPostUpdateListeners
)
{
$this
->
_evm
->
dispatchEvent
(
Events
::
postUpdate
,
new
LifecycleEventArgs
(
$entity
));
}
}
}
}
...
...
@@ -687,12 +731,21 @@ class UnitOfWork implements PropertyChangedListener
{
$className
=
$class
->
name
;
$persister
=
$this
->
getEntityPersister
(
$className
);
$hasLifecycleCallbacks
=
isset
(
$class
->
lifecycleCallbacks
[
Events
::
postDelete
]);
$hasListeners
=
$this
->
_evm
->
hasListeners
(
Events
::
postDelete
);
foreach
(
$this
->
_entityDeletions
as
$oid
=>
$entity
)
{
if
(
get_class
(
$entity
)
==
$className
)
{
$persister
->
delete
(
$entity
);
unset
(
$this
->
_entityDeletions
[
$oid
]);
//TODO: Fire postDelete
if
(
$hasLifecycleCallbacks
)
{
$class
->
invokeLifecycleCallbacks
(
Events
::
postDelete
,
$entity
);
}
if
(
$hasListeners
)
{
$this
->
_evm
->
dispatchEvent
(
Events
::
postDelete
,
new
LifecycleEventArgs
(
$entity
));
}
}
}
}
...
...
@@ -1109,7 +1162,12 @@ class UnitOfWork implements PropertyChangedListener
}
break
;
case
self
::
STATE_NEW
:
//TODO: Fire preSave lifecycle event
if
(
isset
(
$class
->
lifecycleCallbacks
[
Events
::
preSave
]))
{
$class
->
invokeLifecycleCallbacks
(
Events
::
preSave
,
$entity
);
}
if
(
$this
->
_evm
->
hasListeners
(
Events
::
preSave
))
{
$this
->
_evm
->
dispatchEvent
(
Events
::
preSave
,
new
LifecycleEventArgs
(
$entity
));
}
$idGen
=
$class
->
idGenerator
;
if
(
$idGen
->
isPostInsertGenerator
())
{
...
...
@@ -1172,15 +1230,20 @@ class UnitOfWork implements PropertyChangedListener
}
$visited
[
$oid
]
=
$entity
;
// mark visited
//TODO: Fire preDelete
$class
=
$this
->
_em
->
getClassMetadata
(
get_class
(
$entity
));
switch
(
$this
->
getEntityState
(
$entity
))
{
case
self
::
STATE_NEW
:
case
self
::
STATE_DELETED
:
// nothing to do
break
;
case
self
::
STATE_MANAGED
:
if
(
isset
(
$class
->
lifecycleCallbacks
[
Events
::
preDelete
]))
{
$class
->
invokeLifecycleCallbacks
(
Events
::
preDelete
,
$entity
);
}
if
(
$this
->
_evm
->
hasListeners
(
Events
::
preDelete
))
{
$this
->
_evm
->
dispatchEvent
(
Events
::
preDelete
,
new
LifecycleEventArgs
(
$entity
));
}
$this
->
registerDeleted
(
$entity
);
break
;
case
self
::
STATE_DETACHED
:
...
...
@@ -1227,6 +1290,15 @@ class UnitOfWork implements PropertyChangedListener
}
else
{
$managedCopy
=
$this
->
_em
->
find
(
$class
->
name
,
$id
);
}
if
(
$class
->
isVersioned
)
{
$managedCopyVersion
=
$class
->
reflFields
[
$class
->
versionField
]
->
getValue
(
$managedCopy
);
$entityVersion
=
$class
->
reflFields
[
$class
->
versionField
]
->
getValue
(
$entity
);
// Throw exception if versions dont match.
if
(
$managedCopyVersion
!=
$entity
)
{
throw
OptimisticLockException
::
versionMismatch
();
}
}
// Merge state of $entity into existing (managed) entity
foreach
(
$class
->
reflFields
as
$name
=>
$prop
)
{
...
...
@@ -1463,13 +1535,13 @@ class UnitOfWork implements PropertyChangedListener
}
}
/*
if (isset($class->lifecycleCallbacks[Events::postLoad])) {
if
(
isset
(
$class
->
lifecycleCallbacks
[
Events
::
postLoad
]))
{
$class
->
invokeLifecycleCallbacks
(
Events
::
postLoad
,
$entity
);
}
if
(
$this
->
_evm
->
hasListeners
(
Events
::
postLoad
))
{
$this->_evm->dispatchEvent(Events::postLoad, new LifecycleEventArgs($entity
, $this->_em
));
$this
->
_evm
->
dispatchEvent
(
Events
::
postLoad
,
new
LifecycleEventArgs
(
$entity
));
}
*/
return
$entity
;
}
...
...
tests/Doctrine/Tests/ORM/Functional/AllTests.php
View file @
59cf1f74
...
...
@@ -35,6 +35,7 @@ class AllTests
$suite
->
addTestSuite
(
'Doctrine\Tests\ORM\Functional\OneToManySelfReferentialAssociationTest'
);
$suite
->
addTestSuite
(
'Doctrine\Tests\ORM\Functional\ManyToManySelfReferentialAssociationTest'
);
$suite
->
addTestSuite
(
'Doctrine\Tests\ORM\Functional\ReferenceProxyTest'
);
$suite
->
addTestSuite
(
'Doctrine\Tests\ORM\Functional\LifecycleCallbackTest'
);
$suite
->
addTest
(
Locking\AllTests
::
suite
());
...
...
tests/Doctrine/Tests/ORM/Functional/LifecycleCallbackTest.php
0 → 100644
View file @
59cf1f74
<?php
namespace
Doctrine\Tests\ORM\Functional
;
require_once
__DIR__
.
'/../../TestInit.php'
;
class
LifecycleCallbackTest
extends
\Doctrine\Tests\OrmFunctionalTestCase
{
protected
function
setUp
()
{
parent
::
setUp
();
try
{
$this
->
_schemaTool
->
createSchema
(
array
(
$this
->
_em
->
getClassMetadata
(
'Doctrine\Tests\ORM\Functional\LifecycleCallbackTestEntity'
)
));
}
catch
(
\Exception
$e
)
{
// Swallow all exceptions. We do not test the schema tool here.
}
}
public
function
testPreSavePostSaveCallbacksAreInvoked
()
{
$entity
=
new
LifecycleCallbackTestEntity
;
$entity
->
value
=
'hello'
;
$this
->
_em
->
save
(
$entity
);
$this
->
_em
->
flush
();
$this
->
assertTrue
(
$entity
->
preSaveCallbackInvoked
);
$this
->
assertTrue
(
$entity
->
postSaveCallbackInvoked
);
$this
->
_em
->
clear
();
$query
=
$this
->
_em
->
createQuery
(
"select e from Doctrine\Tests\ORM\Functional\LifecycleCallbackTestEntity e"
);
$result
=
$query
->
getResultList
();
$this
->
assertTrue
(
$result
[
0
]
->
postLoadCallbackInvoked
);
$result
[
0
]
->
value
=
'hello again'
;
$this
->
_em
->
flush
();
$this
->
assertEquals
(
'changed from preUpdate callback!'
,
$result
[
0
]
->
value
);
}
}
/**
* @Entity
* @LifecycleListener
* @Table(name="lifecycle_callback_test_entity")
*/
class
LifecycleCallbackTestEntity
{
/* test stuff */
public
$preSaveCallbackInvoked
=
false
;
public
$postSaveCallbackInvoked
=
false
;
public
$postLoadCallbackInvoked
=
false
;
/**
* @Id @Column(type="integer")
* @GeneratedValue(strategy="AUTO")
*/
private
$id
;
/**
* @Column(type="string", length=255)
*/
public
$value
;
/** @PreSave */
public
function
doStuffOnPreSave
()
{
$this
->
preSaveCallbackInvoked
=
true
;
}
/** @PostSave */
public
function
doStuffOnPostSave
()
{
$this
->
postSaveCallbackInvoked
=
true
;
}
/** @PostLoad */
public
function
doStuffOnPostLoad
()
{
$this
->
postLoadCallbackInvoked
=
true
;
}
/** @PreUpdate */
public
function
doStuffOnPreUpdate
()
{
$this
->
value
=
'changed from preUpdate callback!'
;
}
}
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