Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

update associations documentation #21

Merged
merged 3 commits into from

2 participants

@dbu
Collaborator
dbu commented

I tried to weight understandability against duplication of the ORM doc here.

@dbu dbu commented on the diff
en/reference/association-mapping.rst
((221 lines not shown))
+1. New entities in a collection marked as cascade persist will be
+ directly persisted by Doctrine.
+2. New entities in a collection not marked as cascade persist will
+ produce an Exception and rollback the flush() operation.
+3. Collections without new entities are skipped.
+
+This concept is called Persistence by Reachability: New entities
+that are found on already managed entities are automatically
+persisted as long as the association is defined as cascade
+persist.
+
+
+
+.. _collections:
+
+Collections
@dbu Collaborator
dbu added a note

there was a long arguing about clean domain models. i think linking to the orm doc for that is enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@dbu dbu commented on the diff
en/reference/association-mapping.rst
((197 lines not shown))
- Collection class, like everything else in the Common namespace, is
- not part of the persistence layer. You could even copy that class
- over to your project if you want to remove Doctrine from your
- project and all your domain classes will work the same as before.
+ However, pulling objects graph into memory on cascade can cause considerable performance
+ overhead, especially when cascading collections are large. Makes sure
+ to weigh the benefits and downsides of each cascade operation that you define.
+
+Even though automatic cascading is convenient it should be used
+with care. Do not blindly apply cascade=all to all associations as
+it will unnecessarily degrade the performance of your application.
+For each cascade operation that gets activated Doctrine also
+applies that operation to the association, be it single or
+collection valued.
+
+Persistence by Reachability: Cascade Persist
@dbu Collaborator
dbu added a note

we really follow the same logic in phpcr-odm, right? or is it different?
maybe we should repeat here that children automatically have cascade persist?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
en/reference/association-mapping.rst
((171 lines not shown))
-.. warning::
+For References and Referrers, no operations are cascaded by default, they
+can be configured specifically.
+
+The following cascade options exist:
+
+- persist : Cascades persist operations to the associated entities.
+- remove : Cascades remove operations to the associated entities.
+- merge : Cascades merge operations to the associated entities.
+- detach : Cascades detach operations to the associated entities.
+- refresh : Also refresh the associated entities when refreshing this entity.
+- translation : Cascade the current translation locale to associated entities.
@dbu Collaborator
dbu added a note

is the translation cascade case already documented somewhere? whould it go into a section below like persist, or into the multilanguage chapter and just be linked here?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
en/reference/association-mapping.rst
((215 lines not shown))
+Persistence by Reachability: Cascade Persist
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are additional semantics that apply to the Cascade Persist
+operation. During each flush() operation Doctrine detects if there
+are new entities in any collection and three possible cases can
+happen:
+
+
+1. New entities in a collection marked as cascade persist will be
+ directly persisted by Doctrine.
+2. New entities in a collection not marked as cascade persist will
+ produce an Exception and rollback the flush() operation.
+3. Collections without new entities are skipped.
+
+This concept is called Persistence by Reachability: New entities
@dantleech Collaborator

Should probably be: .... This concept is called persistance by reachability; new entities ....

i.e. emphasis instead of capitilization and a semi-colon. not 100% sure on that, but the capitalized words (mid sentance) look wierd to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
en/reference/association-mapping.rst
((69 lines not shown))
+ this content. However, it is not allowed to modify both the reference collection
+ and the referrer collection of interlinked content, as this would be ambiguous.
+
+.. tip::
+
+ There is also the ``DocumentManager::getReferrers`` that allows you to control
+ what referencing documents to get more fine grained, if Referrers is to limited
+ and MixedReferrers too broad.
+
+
+MixedReferrers
+~~~~~~~~~~~~~~
+
+The mixed referrers is a much simpler but read only mapping to get a collection
+of *all* documents that have a reference to this document. The only possible option
+to this mapping is the `referenceType` to only get hard resp. weak references. If
@dantleech Collaborator

don't understand this sentance: "... to only get hard resp. weak references."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
en/reference/association-mapping.rst
((155 lines not shown))
-and ArrayObject but until instances of these types can be used in
-all places where a plain array can be used (something that may
-happen in PHP6) their usability is fairly limited. You "can"
-type-hint on ``ArrayAccess`` instead of ``Collection``, since the
-Collection interface extends ``ArrayAccess``, but this will
-severely limit you in the way you can work with the collection,
-because the ``ArrayAccess`` API is (intentionally) very primitive
-and more importantly because you can not pass this collection to
-all the useful PHP array functions, which makes it very hard to
-work with.
+Each association to another entity or a collection of entities can be
+configured to automatically cascade certain operations. For Children,
+cascading persist and remove are implicit and can not be disabled. (A
+PHPCR node always must have a parent, removing the parent removes its children.)
+The child removal happens on PHPCR level and does not trigger additional
+lifecycle events.
@dantleech Collaborator

.. For Children: Children should be lowercase I think.

.. and can not be disabled. (A ... : paranthesis should be before the full stop, "can not" should be "cannot" and the full stop should be after the paranthesis, again I think :)

and cannot be disabled (a PHPCR node must always have a parent, removing the parent removes its children).
@dbu Collaborator
dbu added a note

learning something new every day: http://www.dailywritingtips.com/cannot-or-can-not/ - i thought cannot is kind of sloppy and "can not" the correct thing to do :-) will fix it then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
en/reference/association-mapping.rst
((171 lines not shown))
-.. warning::
+For References and Referrers, no operations are cascaded by default, they
+can be configured specifically.
+
+The following cascade options exist:
+
+- persist : Cascades persist operations to the associated entities.
@dantleech Collaborator
  1. Entities => Documents

  2. In the annotations reference I delimted options with emphasis like

  • persist - Cascade persist operations to the associated entities.

Which I think I copied from the sf docs for stuff like that, e.g. http://symfony.com/doc/current/book/templating.html#template-suffix

I think I have also seen two backquotes being used to delimt the "option" in definition lists like this, but maybe that applies more to class names etc. Is there are style guide that covers stuff like this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
en/reference/association-mapping.rst
((189 lines not shown))
- The Collection interface and ArrayCollection class,
- like everything else in the Doctrine namespace, are neither part of
- the ORM, nor the DBAL, it is a plain PHP class that has no outside
- dependencies apart from dependencies on PHP itself (and the SPL).
- Therefore using this class in your domain classes and elsewhere
- does not introduce a coupling to the persistence layer. The
- Collection class, like everything else in the Common namespace, is
- not part of the persistence layer. You could even copy that class
- over to your project if you want to remove Doctrine from your
- project and all your domain classes will work the same as before.
+ Cascade operations are performed in memory. That means collections and related entities
+ are fetched into memory, even if they are still marked as lazy when
+ the cascade operation is about to be performed. This approach allows
+ entity lifecycle events to be performed for each of these operations.
+
+ However, pulling objects graph into memory on cascade can cause considerable performance
@dantleech Collaborator

Should be ...

However, pulling the object graph into memory can cause considerable performance overhead - especially .

i.e. pulling the object graph into memory and - instead of comma after overhead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
en/reference/association-mapping.rst
((198 lines not shown))
- project and all your domain classes will work the same as before.
+ Cascade operations are performed in memory. That means collections and related entities
+ are fetched into memory, even if they are still marked as lazy when
+ the cascade operation is about to be performed. This approach allows
+ entity lifecycle events to be performed for each of these operations.
+
+ However, pulling objects graph into memory on cascade can cause considerable performance
+ overhead, especially when cascading collections are large. Makes sure
+ to weigh the benefits and downsides of each cascade operation that you define.
+
+Even though automatic cascading is convenient it should be used
+with care. Do not blindly apply cascade=all to all associations as
+it will unnecessarily degrade the performance of your application.
+For each cascade operation that gets activated Doctrine also
+applies that operation to the association, be it single or
+collection valued.
@dantleech Collaborator

double back-ticks around "cascade-all", e.g. cascade=all ?
should the last sentance be "be it single or multi valued" ?

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

thanks a lot for the input dantleech. (good thing you don't ride your bicycle at night :-)

quite a bit of this was copied and (insufficiently) adapted from the orm doc. i made sure to have document and not entity everywhere now, and clarified the places where you noted inconsistencies.

@dbu dbu merged commit a19e99e into from
@dbu dbu deleted the branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 6, 2013
  1. @dbu

    update associations documentation

    dbu authored
Commits on Mar 7, 2013
  1. @dbu

    cleaning up docs

    dbu authored
Commits on Mar 12, 2013
  1. @dbu

    cleanup link and list

    dbu authored
This page is out of date. Refresh to see the latest.
Showing with 177 additions and 77 deletions.
  1. +169 −69 en/reference/association-mapping.rst
  2. +8 −8 en/reference/events.rst
View
238 en/reference/association-mapping.rst
@@ -235,112 +235,212 @@ In ReferenceMany collections, you can even have documents of mixed types.
exists.
-Referrers back to the referencing documents
+Referrers to inverse the reference relation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-PHPCR-ODM is able to tell which documents reference a specific document, if the `hard` or
-`weak` strategy is used. The Referrers mapping provides a read only field with a collection
-of all documents referencing this document.
+PHPCR-ODM is able to tell which documents reference a specific document, if the ``hard`` or
+``weak`` strategy is used. The ``Referrers`` mapping is a collection of documents that have
+a reference to this document.
-In ORM terms, the Reference is the owning side of the association, while the Referrer is the inverse side.
+In ORM terms, the Reference is the owning side of the association, while the
+Referrer is the inverse side. Contrary to the ORM, the PHPCR references really
+are directional, they are always stored in the property of the document with
+the ReferenceOne or ReferenceMany field. Referrer is a purely virtual information
+that is not explicitly stored in the PHPCR database but determined at runtime.
-You can use the ``filter`` attribute to limit the collection to a specific property name
-on the referring side. The filter follows the ``name`` parameter of
-`PHPCR\NodeInterface::getReferences() <http://phpcr.github.com/doc/html/phpcr/nodeinterface.html#getReferences%28%29>`_
+You need to specify the ``referrerDocument`` to specify the (base) class of the
+document that has the reference, and ``referencedBy`` to tell which field of the
+referencing document contains the reference. After flushing, the reference property
+will contain the referenced document.
+
+.. configuration-block::
+
+ .. code-block:: php
+
+ /** @Referrers(referrerDocument="FQN\Class\Name", referencedBy="otherFieldName") */
+ private $specificReferrers;
+ /** @Referrers(referrerDocument="Other\Class\Name", referencedBy="someFieldName", cascade="persist, remove") */
+ private $cascadedReferrers;
+
+ .. code-block:: xml
+
+ <doctrine-mapping>
+ <document class="MyPersistentClass">
+ <referrers fieldName="specificReferrers" referrerDocument="FQN\Class\Name" referencedBy="otherFieldName" />
+ <referrers fieldName="cascadedReferrers" referrerDocument="Other\Class\Name" referencedBy="someFieldName" cascade="persist, remove" />
+ </document>
+ </doctrine-mapping>
+
+ .. code-block:: yaml
+
+ MyPersistentClass:
+ referrers:
+ specificReferrers:
+ referrerDocument: FQN\Class\Name
+ referencedBy: otherFieldName
+ cascadedReferrers:
+ referrerDocument: Other\Class\Name
+ referencedBy: someFieldName
+ cascade: persist, remove
+
+
+
+Referrers can cascade like the other association mappings to persist or delete their
+referrers if desired.
+
+.. note::
+
+ The main use case to persist cascade or deletion of the referrer mapping
+ is to build a form where it is possible to add documents that should reference
+ this content. However, it is not allowed to modify both the reference collection
+ and the referrer collection of interlinked content, as this would be ambiguous.
+
+.. tip::
+
+ There is also the ``DocumentManager::getReferrers`` that allows you to control
+ what referencing documents to get more fine grained, if Referrers is to limited
+ and MixedReferrers too broad.
+
+
+MixedReferrers
+~~~~~~~~~~~~~~
+
+The mixed referrers is a much simpler but read only mapping to get a collection
+of *all* documents that have a reference to this document. The only possible option
+of mixed referrers is `referenceType` to limit the referrers to only hard resp. weak
+references. If left out, you get both types of references.
+
+Mixed referrers can even be mapped on a document that is not referenceable, as you
+might do it on a base document of which some extending documents are referenceable.
+An example for this is the `Generic` document provided by phpcr-odm itself.
-Additionally you can filter for only weak or only hard references with ``referenceType`` -
-if you don't you get both types of references.
.. configuration-block::
.. code-block:: php
- /** @Referrers */
+ /** @MixedReferrers */
private $allReferrers;
- /** @Referrers(filter="weakTarget") */
- private $specificReferrers;
- /** @Referrers(referenceType="hard") */
+ /** @MixedReferrers(referenceType="hard") */
private $hardReferrers;
.. code-block:: xml
<doctrine-mapping>
<document class="MyPersistentClass">
- <referrers fieldName="allReferrers" />
- <referrers fieldName="specificReferrers" filter="weakTarget" />
- <referrers fieldName="hardReferrers" reference-type="hard" />
+ <mixed-referrers fieldName="allReferrers" />
+ <mixed-referrers fieldName="hardReferrers" reference-type="hard" />
</document>
</doctrine-mapping>
.. code-block:: yaml
MyPersistentClass:
- referrers:
+ mixedReferrers:
allReferrers: ~
- specificReferrers:
- filter: weakTarget
hardReferrers:
referenceType: hard
-.. _collections:
+Transitive persistence / Cascade Operations
+-------------------------------------------
-Collections
------------
+Persisting, removing, detaching and merging individual documents can
+become pretty cumbersome, especially when a highly interweaved object graph
+is involved. PHPCR-ODM provides cascading with the same concepts as
+Doctrine2 ORM does.
-TODO: review
-
-In all the examples of many-valued associations in this manual we
-will make use of a ``Collection`` interface and a corresponding
-default implementation ``ArrayCollection`` that are defined in the
-``Doctrine\Common\Collections`` namespace. Why do we need that?
-Doesn't that couple my domain model to Doctrine? Unfortunately, PHP
-arrays, while being great for many things, do not make up for good
-collections of business objects, especially not in the context of
-an ORM. The reason is that plain PHP arrays can not be
-transparently extended / instrumented in PHP code, which is
-necessary for a lot of advanced ORM features. The classes /
-interfaces that come closest to an OO collection are ArrayAccess
-and ArrayObject but until instances of these types can be used in
-all places where a plain array can be used (something that may
-happen in PHP6) their usability is fairly limited. You "can"
-type-hint on ``ArrayAccess`` instead of ``Collection``, since the
-Collection interface extends ``ArrayAccess``, but this will
-severely limit you in the way you can work with the collection,
-because the ``ArrayAccess`` API is (intentionally) very primitive
-and more importantly because you can not pass this collection to
-all the useful PHP array functions, which makes it very hard to
-work with.
+Each association to another document or a collection of documents can be
+configured to automatically cascade certain operations. For the ``Children`` mapping,
+cascading persist and remove are implicit and cannot be disabled. A PHPCR node
+always must have a parent, removing the parent removes its children.
+The child removal happens on PHPCR level and does not trigger additional
+lifecycle events.
-.. warning::
+For References and Referrers, no operations are cascaded by default, they
+can be configured specifically.
+
+The following cascade options exist:
+
+- **persist**: Cascades persist operations to the associated documents.
+- **remove**: Cascades remove operations to the associated documents.
+- **merge**: Cascades merge operations to the associated documents.
+- **detach**: Cascades detach operations to the associated documents.
+- **refresh**: Also refresh the associated documents when refreshing this document.
+- **translation**: Cascade the current translation locale to associated documents.
+- **all**: Cascades persist, remove, merge, detach, refresh and translation
+ operations to associated documents.
+
+.. note::
- The Collection interface and ArrayCollection class,
- like everything else in the Doctrine namespace, are neither part of
- the ORM, nor the DBAL, it is a plain PHP class that has no outside
- dependencies apart from dependencies on PHP itself (and the SPL).
- Therefore using this class in your domain classes and elsewhere
- does not introduce a coupling to the persistence layer. The
- Collection class, like everything else in the Common namespace, is
- not part of the persistence layer. You could even copy that class
- over to your project if you want to remove Doctrine from your
- project and all your domain classes will work the same as before.
+ Cascade operations are performed in memory. That means collections and related documents
+ are fetched into memory, even if they are still marked as lazy when
+ the cascade operation is about to be performed. This approach allows
+ document lifecycle events to be performed for each of these operations.
+
+ However, pulling a large object graph into memory on cascade can cause considerable performance
+ overhead, especially when cascading collections are large. Makes sure
+ to weigh the benefits and downsides of each cascade operation that you define.
+
+Even though automatic cascading is convenient it should be used
+with care. Do not blindly apply ``cascade=all`` to all associations as
+it will unnecessarily degrade the performance of your application.
+For each cascade operation that gets activated Doctrine also
+applies that operation to the association, be it single or
+collection valued.
+
+Persistence by Reachability: Cascade Persist
@dbu Collaborator
dbu added a note

we really follow the same logic in phpcr-odm, right? or is it different?
maybe we should repeat here that children automatically have cascade persist?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are additional semantics that apply to the Cascade Persist
+operation. During each flush() operation Doctrine detects if there
+are new documents in any collection and three possible cases can
+happen:
+
+
+1. New documents in a collection marked as cascade persist will be
+ directly persisted by Doctrine.
+2. New documents in a collection not marked as cascade persist will
+ produce an Exception and rollback the flush() operation.
+3. Collections without new documents are skipped.
+
+This concept is called "Persistence by Reachability". New documents
+that are found on already managed documents are automatically
+persisted as long as the association is defined as cascade
+persist.
+
+
+
+.. _collections:
+
+Collections
@dbu Collaborator
dbu added a note

there was a long arguing about clean domain models. i think linking to the orm doc for that is enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+-----------
+All many-valued associations of PHPCR-ODM use implementations of the ``Collection``
+interface. They are more powerful than plain arrays. Read sections 8.2 to 8.5 in
+the ORM documentation `Working with associations <http://docs.doctrine-project.org/en/latest/reference/working-with-associations.html>`_
+if you are not familiar with associations.
+Your domain models need to use those classes, but they are defined in a
+specific doctrine collections repository and thus not specific to any
+persistence implementation.
+For a discussion of this topic, see the `Collections section <http://docs.doctrine-project.org/en/latest/reference/association-mapping.html#collections>`_
+in the ORM documentation.
Initializing Collections
-------------------------
+~~~~~~~~~~~~~~~~~~~~~~~~
-You have to be careful when using entity fields that contain a
-collection of related entities. Say we have a User entity that
+You have to be careful when using document fields that contain a
+collection of related documents. Say we have a User document that
contains a collection of groups:
.. code-block:: php
<?php
- /** @Entity **/
+ /** @Document **/
class User
{
- /** @ManyToMany(targetEntity="Group") **/
+ /** @ReferenceMany **/
private $groups;
public function getGroups()
@@ -352,21 +452,21 @@ contains a collection of groups:
With this code alone the ``$groups`` field only contains an
instance of ``Doctrine\Common\Collections\Collection`` if the user
is retrieved from Doctrine, however not after you instantiated a
-fresh instance of the User. When your user entity is still new
+fresh instance of the User. When your user document is still new
``$groups`` will obviously be null.
This is why we recommend to initialize all collection fields to an
-empty ``ArrayCollection`` in your entities constructor:
+empty ``ArrayCollection`` in your documents constructor:
.. code-block:: php
<?php
use Doctrine\Common\Collections\ArrayCollection;
- /** @Entity **/
+ /** @Document **/
class User
{
- /** @ManyToMany(targetEntity="Group") **/
+ /** @ReferenceMany **/
private $groups;
public function __construct()
@@ -380,12 +480,12 @@ empty ``ArrayCollection`` in your entities constructor:
}
}
-Now the following code will be working even if the Entity hasn't
-been associated with an EntityManager yet:
+Now the following code will be working even if the Document hasn't
+been associated with a DocumentManager yet:
.. code-block:: php
<?php
- $group = $entityManager->find('Group', $groupId);
+ $group = $documentManager->find(null, $groupId);
$user = new User();
$user->getGroups()->add($group);
View
16 en/reference/events.rst
@@ -61,13 +61,13 @@ Event order when moving
During the flush() operation of a modified document, the events get triggered in the following order:
-1. preFlush
-2. onFlush
-3. preUpdate
-4. postUpdate
-5. preMove
-6. postMove
-7. postFlush
+* 1. preFlush
+* 2. onFlush
+* 3. preUpdate
+* 4. postUpdate
+* 5. preMove
+* 6. postMove
+* 7. postFlush
As the move event is triggered after the changeset has been calculated,
@@ -165,4 +165,4 @@ listed in the previous Lifecycle Events section.
Listening to Lifecycle Events
-----------------------------
-This works exactly the same as with the `ORM events <http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html>`_.
+This works exactly the same as with the `ORM events <http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#listening-to-lifecycle-events>`_.
Something went wrong with that request. Please try again.