Author: Peter Keung
Date: 2007-02-02 03:00:17 +0100 (Fri, 02 Feb 2007)
New Revision: 4617

Log:
First edit of PersistentObject article
Modified:
   docs/articles/PersistentObject/relations/article.txt

Modified: docs/articles/PersistentObject/relations/article.txt
===================================================================
--- docs/articles/PersistentObject/relations/article.txt        2007-02-01 
19:37:48 UTC (rev 4616)
+++ docs/articles/PersistentObject/relations/article.txt        2007-02-02 
02:00:17 UTC (rev 4617)
@@ -1,5 +1,5 @@
-Relations where relations belong
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+The PersistentObject eZ Component: Putting Relations Where Relations Belong
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 :Author: Tobias Schlitt
 :Revision: $Rev$
@@ -11,174 +11,158 @@
 Introduction
 ============
 
-One of the cool new features of the eZ Components 2006.2 release (short before
-Christmas last year) was the support for relation mappings in the
-PersistentObject component. Before that, PersistentObject already allowed you
-to store any of your applications objects into a database and retrieve them
-back from there, but you needed to care for the relations between these data
-objects yourself all over your application. With the latest release 1.2 of
-PersistentObject, these times are gone and you can configure the relations of
-your objects in a central place and rely on PersistentObject all over your
-application.
+One of the cool new features of the eZ Components 2006.2 release is the support
+for relation mappings in the PersistentObject component. PersistentObject
+already allowed you to store objects in a database (and retrieve them from
+there). With the latest 1.2 release of PersistentObject, you can configure the
+object relations in a central place and benefit from using PersistentObject
+throughout your application.
 
-This article will give you an introduction into PersistentObject in general and
-how the new facilities of handling relations work. As usual in my articles, I
-will show you code from a simple example application. The application that will
-be shown makes also heavy use of other components, like UserInput and Template,
-but we will keep those out of the article and concentrate completely on
-PersistentObject.
+This article will give you an introduction to the PersistentObject component in
+general, and explain the new feature of handling relations. To aid in the
+explanations, we will look at code from a simple example application, as is
+usually the case with my articles. The example application makes heavy use of
+other components, such as UserInput and Template, but this article will
+concentrate completely on the use of PersistentObject.
 
 The example application
 =======================
 
-This time, it will be a simple address book, that allows you to take care of
-your friends their addresses and email addresses. The application will have a
-web interface to test the functionality, which covers creation of new data and
-deletion of objects. For simplicity, the manipulation of existing data has been
-left out.
+We will create a simple address book that allows you manage information about
+your friends, and their addresses and email addresses. The application will 
have a
+web interface that facilitates the creation and deletion of objects. For
+simplicity, the manipulation of existing objects will be left out.
 
 The database layout
 -------------------
 
-The application relies on 5 database tables: The table "person" will store
-first- and lastname of each contact. A second table, called "detail", will
-contain additional details about person. -- Yes, this is not in the sense of
-normalization, but it can make a lot of sense in praxis, if you reach
-multi-millions of records, or if your detail table reaches hundreds of columns.
-So, whatever you read and see here: Remember that this is only an example
-application! -- The table "email" will be used to store the email addresses a
-person and finally the table "address" will store physical addresses. Because
-every person can be assigned to several addresses and several persons can live
-at one address, we need a relation table: "person_address".
+The application relies on five database tables: The "person" table stores the
+first and last name of each person. A second table, called "detail", contains
+additional details about people. The table "email" is used to store email
+addresses, and the table "address" stores physical addresses. Because a person
+can be assigned to several addresses and several people can live at one
+address, we have a relation table: "person_address".
 
 .. include:: trunk/docs/ezccontact.sql
    :literal:
 
-This database design contains several relations between the objects we want to
-handle: The "person" table (represented by a Person object) is the central
-instance in the application and represents the starting point for all of our
-relations. The "detail" table contains information describing exactly 1 person
-and every person may only have 1 detail record. This means, we have the
-simplest kind of relation: A 1:1 (one-to-one) relation. A Person can have
-multiple email addresses (so, how many do you have?), but 1 email address can
-only belong to 1 person (at least in our example). Here we have the most common
-relation type: 1:n (one-to-many). Finally a person can have multiple addresses
-(a home address, an office address, ...) and multiple persons may be assigned
-to the same address. This reflects the most complex relation type: A m:n
-(many-to-many) relation.
+This database design contains several relations between objects. The "person"
+table (represented by a person object) is the central instance in the
+application and represents the starting point for all of our relations.
+  
+- The "detail" table contains information describing exactly one person and
+  every person may only have one detail record. Here, we have the simplest kind
+  of relation: a 1:1 (one-to-one) relation.
 
-The application layout
-----------------------
+- A person can have multiple email addresses (so, how many do you have?), but
+  one email address can only belong to one person (at least in our example).
+  Here, we have the most common relation type: 1:n (one-to-many).
+  
+- A person can have multiple addresses (for example, a home address and an
+  office address) and multiple persons can be assigned to the same address.
+  This reflects the most complex relation type: a n:m (many-to-many) relation.
 
-The example application will follow a very simple MVC (Model-View-Controller)
-pattern: The main file is  index.php, which defines and runs the main
-controller object.  This one knows several "actions", for which it will
-dispatch to an action class, which will then handle the request. Beside that,
+The application structure
+-------------------------
+
+The example application follows a very simple MVC (Model-View-Controller)
+pattern: The main file is index.php, which defines and runs the main
+controller. This controller responds to several "actions", and dispatches them
+to an action class, which will then handle the request. In addition,
 the controller handles the initialization and processing of a template (which
-gets defined by the action object).
+is defined by the action object).
 
-We will not take care for the controller and the template mechanism in this
-article, but concentrate on the actions and the configuration of the
-PersistentObject component. If you downloaded the `application source`_, you
-can find the action classes in the sub directory actions/. Furthermore we will
-deal with the model classes used in the application (sub directory models/) and
-the definition files, used by the PersistentObject component (persistent/).
+We will not discuss the controller and template mechanism in this
+article, but will concentrate on the configuration and usage of the
+PersistentObject component. If you download the `application source`_, you
+can find the action classes in the directory actions/. We will
+also deal with the model classes used in the application (in the directory
+models/) and the definition files used by the PersistentObject component (in
+the directory persistent/).
 
 .. _`application source`: 
 
-The further directories are uninteresting for us, but I want to give you
-some short hints, what they contain:
+The other directories are not discussed in this tutorial. Here is a brief
+summary of what they contain:
 
 autoload/
-  This directory contains the autoload files for our applications, which are
+  This directory contains the autoload files for our application, which are
   used in combination with the eZ Components autoload mechanism.
 docs/
-  You can find setup information for this application here. Especially the
-  database structure as a MySQL dump and some example data in the same format.
+  You can find setup information for the application here. For example, there
+  is the database structure and some example data as MySQL dumps.
 templates/
   The example application relies on the Template component, for which the HTML
   template files can be found here.
 templatesc/
-  Because the  Template component compiles template code into PHP source code,
-  it needs this directory to cache the generated code.
+  Because the Template component compiles template code into PHP source code,
+  this directory is needed to cache the generated code.
 
 Getting things started
 ======================
 
-Now we will start digging into the application. You will see step by step, how
-I defined the "persistent objects to reflect our database design and how to 
make
-use of them in the action classes.
+We will see how to define, step by step, the persistent objects to reflect our
+database design and how to make use of them in the action classes.
 
 As already mentioned, the person object is the central model of our
-application. The person object has a relation defined for each of the other
-objects. Therefore, we will create this model in the first step, to see how the
-basics of PersistentObject work. There are 3 steps to take before you can make
+application. There are three steps to take before you can make
 use of PersistentObject:
 
 1. Create the model class, which will be used in the application itself.
-2. Create a definition for the PersistentObject component, to indicate, in
+2. Create a definition for the PersistentObject component to indicate in
    which way this model class reflects the database structure.
 3. Create an instance of ezcPersistentSession and configure it to make use of
-   the 2 previous points.
+   the two previous points.
 
-Creating the first model
-------------------------
+Creating the first model (step 1)
+---------------------------------
 
-So, let's start with step 1. The PersistentObject component does neither
-require you to inherit from a specific base class in order to make an object
-persistent, nor to stick to a given naming scheme. The only thing required is,
-to implement 2 methods in the object class:
+The PersistentObject component does not require you to inherit from a specific
+base class, nor to stick to a given naming scheme. The only requirement is to
+implement two methods in the object class:
 
 getState()
-  Which returns an array representing the current state of the object. The
-  state is represented by the properties of the object, each property name is
-  a key in the array, having the properties value assigned.
+  This returns an array representing the current state of the object. The
+  state is represented by the properties of the object; each property name is
+  a key in the array, assigned to its corresponding value.
 setState()
-  Is the corresponding method which is used to set the state of an object. This
-  method must accept the same format, that getState() returns and must set the
+  This the corresponding method to set the state of an object. This
+  method must accept the same format that getState() returns and must set the
   object properties accordingly.
 
-Let's take a look at the model for the person object. I called the class
-ezcappContactPerson and it looks like this:
+Let's take a look at the model for the person object, which is called
+ezcappContactPerson:
 
 .. include:: trunk/models/person.php
    :literal:
 
-The class contains 3 public properties (I'm quite sure, you would not want to
-have all of them public in a real application, but remember, that this is just
-an example): $id, $firstname and $lastname, which reflect the fields of the
-person table in the database. Beside that, you see the 2 mentioned methods
-getState() and setState(), which perform the desired actions: getState() simply
-returns an array of all properties and setState() sets the properties from a
-given array. You should note, that the implementation of setState() is a bit
-sloppy (for simplicity reasons), because it would also set non-existent
-properties.
+The class contains three public properties: $id, $firstname and $lastname,
+which reflect the fields of the "person" table in the database. (I'm quite sure
+that you would not want to have all of the fields to be public in a real
+application, but remember that this is just an example.) 
 
-Telling PersistentObject about it
----------------------------------
+The getState() and setState() methods perform the desired actions: getState() 
simply
+returns an array of all object properties and setState() sets the properties 
from a
+given array. You should note that the implementation of setState() is a bit
+sloppy (for simplicity reasons) as it would also set non-existent properties.
 
-So far, so good. Now we need to tell PersistentObject, that our new class
+Telling PersistentObject about it (step 2)
+------------------------------------------
+
+So far, so good. Now we need to tell PersistentObject that our new class
 "ezcappContactPerson" should reflect the database table "person".
-PersistentObject is designed to understand different formats for storing these
-information, but there is only 1 format manager available so far.
-The "ezcPersistentCodeManagaer" can load a PHP data structure, so that other
-formats can always rely on this one as the target format. In future versions of
-PersistentObject it might happen, that other code managers are added, which
-could e.g. deal with some XML format. Beside that, you could write your own
-code manager, which possibly creates definitions on the fly, to save you from 
the
-work of creating definitions for all of your model classes, if you use a unique
-naming scheme.
+PersistentObject is designed to understand different formats for storing
+information, but there is only one format manager available so far.
+ezcPersistentCodeManager can load a PHP data structure. Future versions of
+PersistentObject might include additional format managers that could, for
+example, load an XML structure. You could also write your own format managers.
 
-Anyway, we are using the standard definition manager. This one requires us to
-provide a directory with PHP files, the manager can load when we request an
-action on a certain persistent object. For this reason, the PHP files must be
-named after the class names, but all in lowercase. The following definition is
-stored in a file called persistent/ezcappcontactperson.php.
+ezcPersistentCodeManager requires us to provide a directory with PHP files that
+can be loaded when an action is requested on a certain persistent object. For
+this reason, the PHP files must be named after the class names, but in
+lowercase. The following definition is stored in a file called
+persistent/ezcappcontactperson.php.::
 
-Let us take a look at how to create the basic PersistentObject definition
-file. I won't show you how to define relations in this first step, so that we
-have the basics here and concentrate on the really important stuff later. ::
-
     <?php
 
     $def = new ezcPersistentObjectDefinition();
@@ -205,29 +189,31 @@
     return $def;
     ?>
 
-You should try to get not too confused by the explanation that follows now,
-because the term "property" will occur quite often in different meanings. A
-definition of a persistent object is created using an instance of
-ezcPersistentObject definition. This container needs to know 2 essential
-things: The database table and the class name it should interconnect. Next we
-need to define the properties of our persistent object, which is done by
-defining an array called "properties" in the definition object. This one has a
-key for every property of the persistent object. For example: The property
-ezcappContactPerson->firstname is define in "$def->properties['firstname']". We
-need to tell PersistentObject, which column from the database is stored in this
-property, as well as the data type the property has in and the name
-of the property.
+For now, we will leave out the discussion on defining relations until later in
+this article.
 
-A special case for a property is the "ID property", which is commonly called
-"primary key" in terms of a relational database. The ID property is used to
-identify a persistent object uniquely, e.g. to load and store it. The ID
-property needs a definition object, because it needs a "generator" beside the
-usual information for a property. The generator takes care of creating a unique
-ID, when a new persistent object is stored into the database for the first
-time. In our example we are using the "ezcPersistentSequenceGenerator", which
-relies on the database to care for a new ID. In case of MySQL, this is
-"auto_increment" and for Oracle (for example) it would be a sequence.
+First, a definition of a persistent object is created using an instance of
+ezcPersistentObject definition. You need to specify two essential things to the
+definition: the database table and the equivalent class name.
 
+Next, we define the properties of our persistent object, which is done by
+defining an array called "properties" in the definition object. (Beware that 
the
+term "property" will be used quite often in different contexts.) This array 
has a
+key for every property of the persistent object. For example, the property
+ezcappContactPerson->firstname is defined in "$def->properties['firstname']". 
We
+need to specify the corresponding column from the database, its datatype and
+the name of the property.
+
+The ID property, which is commonly called the "primary key" relational database
+terminology, is a special case. The ID property is used to uniquely
+identify a persistent object, in order to manipulate it. The ID
+property needs a definition object, because it needs a "generator" in addition
+to the usual information for a property. The generator takes care of creating 
a unique
+ID when a new persistent object is stored into the database for the first
+time. In our example, we are using the "ezcPersistentSequenceGenerator", which
+relies on the database to provide a new ID. For MySQL, this is
+"auto_increment" and for Oracle this is a sequence.
+
 Finally, the definition we just created is returned from the file. I believe
 I'd see some baffled faces now that you read this , because I must have looked
 the same, when I saw this first. If you want to know more about this, take a
@@ -235,16 +221,11 @@
 
 .. _`PHP manual about include`: 
http://www.php.net/manual/en/function.include.php#AEN5250
 
-Using what we got
------------------
+Using what we have (step 3)
+---------------------------
 
-Finally in this introductional part, we will see, what we need in our
-application beside the configuration setup and how to perform
-the first steps with the real usage of PersistentObject.
-
 To perform any kind of action on a persistent object, we need an instance of
-ezcPersistentSession, which itself needs a database connection to work
-properly: ::
+ezcPersistentSession, which in turn needs a database connection: ::
 
     <?php
 
@@ -260,36 +241,33 @@
     ?>
 
 The first two lines perform the database initialization and store the newly
-created database connection in a singleton like mechanism (for more
-information, take a look at the `Database component`_). After that, we create
-the persistent session itself. Beside the database connection, it needs the
-definition manager, I already talked about earlier. This one needs to know,
-where our definition files reside. Finally, we store the persistent session
-instance in a singleton container, too, so that we can access it from
-everywhere in our application.
+created database connection in a singleton-like mechanism (for more
+information, see the `Database component`_). After that, we create
+the persistent session itself. It also needs to load the format
+manager, as discussed in step 2. Finally, we store the persistent session
+instance in a singleton container so that it can be accessed throughout our
+application.
 
 .. _`Database component`: 
http://ez.no/doc/components/view/2006.2/(file)/classtrees_Database.html
 
 Using persistent objects
 ========================
 
-In the introductional part you learned the basics of how to configure
-PersistentObject. We created a simple model class, the database mapping for
-it and the persistent session. In the following part you will learn how to
-configure relations between persistent objects and how to work with them in
-your application. We will make use of the other models in the following
-examples, assuming, that you know how they are structured and how their basic
-PersistentObject definition looks like. It's all the same as with the "person"
-model.
+In the introduction section we discussed the basics of how to configure
+PersistentObject. We created a simple model class, specified the database
+mapping for it and instantiated the persistent session. We will now demonstrate
+how to configure relations between persistent objects and how to work with 
them in
+an application. Other models are used, which are all similar to
+the "person" model that was just created.
 
 The first steps
 ---------------
 
-First of all I want to show, how a new persistent object can be stored. We
+Let's examine how a new persistent object can be stored. We
 therefore take a look at the "create" action, but still leave out the relations
-it uses. I also skip the part of the `UserInput component`_, which is
-used to retrieve the POST variables in the action. Here is the very shortened
-source code: ::
+it uses. The usage of the `UserInput component`_, which is
+used to retrieve the POST variables in the action, is skipped as well. Here is
+the shortened source code: ::
 
     <?php
     //...
@@ -305,19 +283,19 @@
     //...
     ?>
 
-We retrieve the instance of ezcPersistentSession in the first line of the
-example. After that, we simply create a new ezcappContactPerson object, assign
-its properties from the form data we received and tell the session to save it.
-These few lines of code last, to make PersistentObject put our newly created
-person into the database and assign the ID it retrieved to the defined ID
-property. Note, that the form object already took actions to secure our data
-and that PersistentObject uses bind values internally to secure the SQL 
queries.
+In the first line, the ezcPersistentSession instance is retrieved. Then, we
+create a new ezcappContactPerson object, assign
+its properties from some input form data and save the object.
+PersistentObject puts our newly created person object into the database and
+assigns the generated unique ID to the defined ID property. Note, that the form
+object already ensured that our data is secure
+and that PersistentObject uses bind values to internally secure the SQL 
queries.
 
-So, that was easy. But in the create action, we also retrieve the details for a
-new person, which are stored in the table "detail" and therefore in another
-persistent object. Basically we need to define our first relation: A one-to-one
-relation. As mentioned earlier, I won't show you the class ezcappContactDetail
-here, because it looks too similar to the ezcappContactPerson class. The same
+So, that was easy. During the create action, however, we also retrieve the
+details for a new person, which are stored in the table "detail" and therefore
+in another persistent object. Basically, we need to define our first relation:
+A one-to-one relation. As mentioned earlier, the class ezcappContactDetail
+looks very similar to the ezcappContactPerson class. The same
 applies to its definition file.
 
 Relations are defined in the persistent object definitions themselves, using
@@ -346,25 +324,25 @@
 
 We create a new key for the desired class in the relations array. The
 configuration class for a one-to-one relation is called
-ezcPersistentOneToOneRelation. Its constructor receives the names of 2 database
-tables: The 1st is the name of the source table (which is actually the current
-on, "person"), the second one is the name of the destination table for the
+ezcPersistentOneToOneRelation. Its constructor receives the names of two 
database
+tables: The first is the name of the source table (which is actually the 
current
+one, "person"); the second is the name of the destination table for the
 relation ("detail" in this case).
 
 Furthermore, the relation needs a mapping of columns, which defines how the
-objects are related to each other. In case of a one-to-one relation, this works
-through a so-called ezcPersistentSingleTableMap, because we only do 1 mapping
-between 1 tables in each map (in contrast to an ezcDoubleTableMap, which you
-will get to know later). In our case we map the "id" column of the table
-"person" to the column "person" of the table "detail". As you might have
-noticed, the column map is an array, which means that you can also specify
-multiple column mappings, using 1 instance of ezcPersistentSingleTableMap each.
+objects are related to each other. In the case of a one-to-one relation, this
+works through ezcPersistentSingleTableMap, because we only map one table on
+each end (in contrast to ezcDoubleTableMap, which will be discussed later). In
+our case, we map the "id" column of the table "person" to the "person" column
+of the table "detail". As you might have noticed, the column map is an array,
+which means that you can also specify multiple column mappings, using one
+instance of ezcPersistentSingleTableMap for each mapping.
 
-Finally, we define that this relation should cascade delete actions. This
-means, that whenever we delete a person object from the database, the
-corresponding detail object gets deleted, too.
+Finally, we specify that this relation should cascade delete actions. This
+means that whenever we delete a person object from the database, the
+corresponding detail object is deleted as well.
 
-Nice, so, we have the first relation defined and can make use of it in our
+Now that we have the first relation defined, it can be used in our
 example from before: ::
 
     <?php
@@ -388,21 +366,20 @@
     // ...
     ?>
 
-The first part, for storing the person object stays the same. After that, we
+The first part, for storing the person object, stays the same. After that, we
 create the detail object and assign the necessary properties from the form
-data. The following call to $session->addRelatedObject() performs the
-assignment of the relation. After that, the detail belongs to the person.
-Finally, we only need to save the detail to the database, too. Note, that the
-addRelatedObject() method does only set the necessary properties (and for some
-relations it does some more, but more about that later) and does not store the
-object it manipulated automatically.
+data. The $session->addRelatedObject() method assigns the relation.
+Finally, the detail object is saved to the database. Note that the
+addRelatedObject() method only sets the necessary properties (as you will see
+later, it does a bit more for other relations) but does not actually store the
+object.
 
-Easy, wasn't that? But I have to admit, that I embezzled a small speciality for
-the detail model so far. As you can see from the database structure, the detail
+Easy, wasn't it? But I have to admit, I purposely left out a small point about
+the detail model. As you can see from the database structure, the detail
 table uses the same ID as the person table. If we would define the ID property
-of the detail object using an ezcPersistentSequenceGenerator, as we did for the
-person object, we would run into problems: The sequence generator would try to
-generate a new ID, while we want it to re-use the one from the person.
+of the detail object using ezcPersistentSequenceGenerator, as we did for the
+person object, we would run into problems: the sequence generator would try to
+generate a new ID, while we want it to use the same one as the person object.
 Therefore, we need to use another generator here: ::
 
     <?php
@@ -416,31 +393,31 @@
     // ...
     ?>
 
-Instead of the sequence generator, we are using the manual generator here,
-which allows us to set the ID property on our own and make PersistentObject
-don't care about it. At least not in the moment where we are calling
-$session->save(). Actually, PersistentObject does take care for the ID property
-in our special case, but in a different way: The call to addRelatedObject() in
-the previous code piece does it, because we defined the ID property for the
-relation mapping.
+Instead of the sequence generator, we use the manual generator,
+which allows us to manually set the ID property for the detail object.
+Actually, PersistentObject takes care of this: the call to addRelatedObject(), 
in
+the previous piece of code, set the ID property, because the "id" and "person"
+columns were mapped to each other.
 
+.. _`UserInput component`: 
http://ez.no/doc/components/view/2006.2/(file)/classtrees_UserInput.html
+
 Advanced relations
 ------------------
 
-We just defined our first relation, the one-to-one relation between the person
-and the detail object. Additionally, we saw where a problem for one-to-one
-relations occurs: In the most cases we will use the same keys for related
-objects, so that one of them needs to use the manual generator. And finally we
-saw how to save newly created persistent objects and how to make 2 persistent
-objects related to each other.
+We just defined our first relation: the one-to-one relation between the person
+and detail objects. Additionally, we saw that in most one-to-one cases the same
+keys are used for related objects; as a result, one of them needs to use the
+manual generator. We also saw how to save newly created persistent objects and
+how to relate two persistent objects to each other.
 
-The next step is, to define some more relation types and to see, how we can
-fetch objects, which are related to each other. For that, let's take a look at
-the "show" action, which is responsible for displaying a person, its details, 
its
-email addresses and the addresses it is assigned to. Beside that, the actions
-template shows a list of all addresses, so that the user can assign new ones to
-the actual person. Therefore we need to fetch all address objects, too. ::
+Next, we will define some more relation types and see how to
+fetch objects that are related to each other.
 
+In our example, the "show" action, is responsible for displaying a person
+object, its details, its email addresses and its physical addresses. The 
actions
+template also shows a list of all addresses so that the user can assign new 
ones to
+a person. Therefore, we need to fetch all address objects as well. ::
+
     <?php
     // ...
     
@@ -457,20 +434,19 @@
     // ...
     ?>
 
-As usual we need the instance of ezcPersistentSession, for any kind of action
-on a persistent object. Next we fetch the desired person from the
-database, using $session->load(). If you are using this method, you should be
-aware, that it will throw an exception, if the desired object does not exist.
-If you cannot be sure it exists or if it does not matter to you, you should use
-the method loadIfExists().
+As usual, we need an instance of ezcPersistentSession for any kind of action
+on a persistent object. Next, we fetch the desired person from the
+database using $session->load(). If you are using this method, you should be
+aware that it will throw an exception if the desired object does not exist.
+To fetch an object only if it exists, use the method loadIfExists().
 
-Next we need to fetch the 3 related objects: The detail object, the email
-objects and the address objects. You should note especially, that I am using 2
-different methods for this: getRelatedObject() (used for fetching the detail
-object) will fetch exactly 1 object and will throw an exception, if no object
-was found. In contrast, fetchRelatedObjects() will fetch all related objects of
-a type from the database (0 or more) and always return an array of objects, no
-matter how many were found.
+Then, we need to fetch the three related objects: the detail object, the email
+objects and the address objects. Note that two different methods are used in
+for this: getRelatedObject() (used for fetching the detail
+object) will fetch exactly one object and will throw an exception if no object
+is found; in contrast, getRelatedObjects() will fetch all related objects from
+the database (0 or more) and will always return an array of objects (even if it
+is empty), no matter how many were found.
 
 Finally, we need the list of all address objects. This has actually nothing to
 do with the topic of relations. The ezcPersistentSession instance can create a
@@ -480,14 +456,13 @@
 component`_. Using this object as the basis, we can restrict the performed
 search and add SQL parts to it. As you can see, the query class uses a
 so-called "fluent interface", where each method call returns the object itself,
-so that one can call methods in a chain. We are adding 3 "ORDER BY" clauses to
+so that one can call methods in a chain. We are adding three "ORDER BY" 
clauses to
 our query here. Finally, we instruct the persistent session to find all
-objects, of the class ezcappContactAddress, which match the given query and
-retrieve an array of them.
+objects of the class ezcappContactAddress that match the given query and
+return an array of them.
 
-So, after this little excursus away from relations, let us take a look at the
-definitions for the relations we just used. Again we are enhancing the
-definition file of the person object: ::
+Let us now take a look at the definitions for the relations we just used.
+Again, we are enhancing the definition file of the person object: ::
 
     <?php
     // ...
@@ -525,37 +500,37 @@
     ?>
 
 The relation between the person and email objects is the most common relation
-type, the one-to-many relation. It is defined completely analogues to the
-one-to-one relation, using the specific relation class and the 2 tables we want
-to connect to each other. Since we are only using 2 tables again, we need a
-single table map here, too. Same as for the ezcPersistentOneToOneRelation. The
-cascade option again has the same effect: If a person gets deleted, all of its
-associated email addresses get deleted, too.
+type, the one-to-many relation. It is defined completely analagous to the
+one-to-one relation, using the specific relation class and the two tables we 
want
+to connect to each other. Since we are only using two tables, we need a
+single table map, just as for ezcPersistentOneToOneRelation. The
+cascade option again has the same effect: if a person is deleted, all of its
+associated email addresses are deleted too.
 
-The second relation we define here, is the most complex type: The many-to-many
-relation. It is more complex then the other 2 types we already know, because we
+The second relation we define here is the most complex type: the many-to-many
+relation. It is more complex than the other two types, because we
 need a relation table to realize it. Therefore, the constructor of
-ezcPersistentManyToManyRelation requires 3 table names instead of 2: The source
-table, the destination table and the relation table. We are connecting the
-person table to the address table, using the person_address table. Therefore 
the
-column map of a n:m relation is an array of ezcPersistentDoubleTableMap, which
-connect the 3 named table and therefore realizes 2 table connections.  The
-order of the columns given to the double table map is the following: 1st the
-field from the source table, which maps to (2nd) the first field of the
-relation table. The 3rd item is the second field of the relation table, which
-maps to a field of the destination table (4th). In other words, we are mapping
-the field "id" of the table "person" to the field "person" of the table
-"person_addresss" and the column "address" of the table "person_address" to the
-field "id" of the table "address".
+ezcPersistentManyToManyRelation requires three table names instead of two: the 
source
+table, the destination table and the relation table.
 
-Specialities
-------------
+We are connecting the person table to the address table using the
+person_address table. Therefore, the column map of a n:m relation is an array
+of ezcPersistentDoubleTableMap, which connects the three named tables to
+realizes two table connections. First, the field from the source table maps to
+the first field of the relation table. The third item is the second field of
+the relation table, which maps to the field from the destination table. In
+other words, we are mapping the column "id" of the table "person" to the column
+"person" of the table "person_addresss" and the column "address" of the table
+"person_address" to the column "id" of the table "address".
 
-As already mentioned, many-to-many relations are the most complex relation
-type. To analyze them a bit deeper, we will now take a look at another action.
-Earlier, we loaded all addresses so that the user can assign them to a person.
-We will examine this action now ("address"). ::
+More about relations
+--------------------
 
+As already mentioned, the many-to-many relation is the most complex relation
+type. Earlier, we loaded all addresses so that the user can assign them to a
+person. To analyze this a bit deeper, we will take a look at the "address"
+action: ::
+
     <?php
     // ...
 
@@ -569,16 +544,16 @@
     ?>
 
 We load both desired objects from the database, using the well-known load()
-method. Again we are using the addRelatedObject() method, but this time,
-without saving any of the objects afterwards. Why don't we do so? Because it is
+method. Again, we are using the addRelatedObject() method, but this time,
+without saving any of the objects afterwards. That is
 actually not necessary here. For all other relation types, the
-addRelatedObject() method just sets the desired object properties to the
-correct values. This manipulates the objects themselves, so we need to store
-them afterwards. In the case of a many-to-many relation, the original objects
-are not modified in any way.  Instead, a new record is inserted into the
-relation table, which happens without any manual saving.
+addRelatedObject() method simply sets the desired object properties to the
+correct values; this manipulates the objects themselves, so we need to store
+them. In the case of a many-to-many relation, the original objects
+are not modified in any way. Instead, a new record is inserted into the
+relation table, which occurs without any manual saving.
 
-So, let us also examine the opposite part in the "removeaddress" action. ::
+So, let us also examine the counterpart: "removeaddress" action. ::
 
     <?php
     // ...
@@ -592,29 +567,26 @@
     // ...
     ?>
 
-The same procedure here: Loading both objects and afterwards a call to
-removeRelatedObject() to remove the relation record again. As you might guess,
+The same procedure occurs here: both objects are loaded, then a call to
+removeRelatedObject() removes the relation. As you might guess,
 you can also use this method with all other types of relations, where it will
-simply unset the relation properties, to remove the relation. Again, you will
-have to manually store the object afterwards in that case.
+simply unset the relation properties to remove the relation. Again, you would
+have to manually store the object afterwards.
 
-As a final word about many-to-many relations you should notice, that the
-cascade option does not exist for them. If you think a second about this, it
-makes perfect sense, because PersistentObject cannot know (or only with more
-SQL query overhead), if related objects may be deleted, and are not referenced
-by other objects.
+As a final word about many-to-many relations, notice that the
+cascade option does not exist for them. PersistentObject does not know (or only
+with more SQL query overhead) if related objects can be deleted, as it needs to
+find out whether they are referenced by other objects.
 
-So, what is still missing is the last relation type, about which we did not
-hear anything, yet: Many-to-one relations. Right now, you will wonder, where
-this relation type could make sense. But it actually makes sense: With all of
-the relations we configured so far, we can fetch objects from the database,
-which are related to a person object. What happens if we want to fetch the
-other way around?  Correct: We need to configure the corresponding relation.
-And for a one-to-many relation, this is consequently a many-to-one relation.
+The final relation type, is the many-to-one relation. With all of
+the relations we configured so far, we can fetch objects from the database that
+are related to a person object. What happens if we want to fetch a person
+object related to one of those other objects? We need to configure the
+corresponding relation.
 
 If you want to learn more about this relation type (or so-called "reverse"
 relations), you should take a look at the definition files for the "email" and
-"address" objects. Furthermore, the `PersistentObject tutorial`_ contains some
+"address" objects. The `PersistentObject tutorial`_ also contains some
 information about it.
 
 .. _`PersistentObject tutorial`: 
http://ez.no/doc/components/view/2006.2/(file)/introduction_PersistentObject.html
@@ -622,21 +594,18 @@
 Final thoughts
 ==============
 
-Some of the features of PersistentObject are not mentioned in this, but it
-already became a lot longer than it was planned... Anyway, the example
-application shipped with this article can give you a nice overview on the usage
-of PersistentObject and if you dig into the whole code, you can also learn a
-lot about other components.
+The example application in this article gives a nice overview on the usage
+of PersistentObject and if you dig a bit deeper into the code, you can also
+learn a lot about some other components.
 
-As a hint, you should also take a look at the
-`PersistentObjectDatabaseSchemaTiein component`_, which gives you some comfort
-for generating PersistentObject definitions
+You should also take a look at the `PersistentObjectDatabaseSchemaTiein
+component`_, which can help with generating PersistentObject definitions
 
 .. _`PersistentObjectDatabaseSchemaTiein component`: 
http://ez.no/doc/components/view/2006.2/(file)/classtrees_EventLogDatabaseTiein.html
 
-For the next releases I expect that PersistentObject will become more and more
+For future releases, I expect that PersistentObject will become more and more
 powerful. We will definitely enhance the usability with some API candy and a
-primary goal is, to reduce the SQL overhead generated as much as possible.
+primary goal is to reduce the generated SQL overhead as much as possible.
 
 I hope you enjoyed reading this article and that you try out the
 PersistentObject component. I would be very happy to receive some feedback!

-- 
svn-components mailing list
svn-components@lists.ez.no
http://lists.ez.no/mailman/listinfo/svn-components

Reply via email to