Share » Learn » eZ Publish » The PersistentObject eZ Component:...

The PersistentObject eZ Component: Putting Relations Where Relations Belong

Tuesday 27 February 2007 12:12:00 am

  • Currently 3 out of 5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

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

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. The usage of the UserInput component, which is used to retrieve the POST variables in the action, is skipped as well. Here is the relevant section of the source code:

<?php
//...
 
$session = ezcPersistentSessionInstance::get();
 
$this->person = new ezcappContactPerson();
$this->person->firstname = $form->firstname;
$this->person->lastname  = $form->lastname;
 
$session->save( $this->person );
 
//...
?>

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. 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 the relations property of the ezcPersistentObjectDefinition instance. The following code must be added to the definition of the person object, in order to relate it to the detail object:

<?php
// ...
 
// 1:1 relation to detail table
$def->relations['ezcappContactDetail'] = new ezcPersistentOneToOneRelation(
    "person",
    "detail"
);
$def->relations['ezcappContactDetail']->columnMap = array(
    new ezcPersistentSingleTableMap(
        "id",
        "person"
    ),
);
$def->relations['ezcappContactDetail']->cascade = true;
 
// ...
?>

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 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 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 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.

Now that we have the first relation defined, it can be used in our example from before:

<?php
// ...
 
$session = ezcPersistentSessionInstance::get();
 
$this->person = new ezcappContactPerson();
$this->person->firstname = $form->firstname;
$this->person->lastname  = $form->lastname;
 
$session->save( $this->person );
 
$this->detail = new ezcappContactDetail();
$this->detail->birthday = trim( $form->birthday ) !== "" ? strtotime( $form->birthday ) : null;
$this->detail->comment  = $form->comment;
 
$session->addRelatedObject( $this->person, $this->detail );
$session->save( $this->detail );
 
// ...
?>

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 $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 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 ezcPersistentSequenceGenerator, as we did for the person object, we would run into problems: the sequence generator would try to generate a new ID, but we want it to use the same one as the person object. Therefore, we need to use another generator here:

<?php
// ...
 
$def->idProperty               = new ezcPersistentObjectIdProperty();
$def->idProperty->columnName   = 'person';
$def->idProperty->propertyName = 'person';
$def->idProperty->generator    = new ezcPersistentGeneratorDefinition( 'ezcPersistentManualGenerator' );
 
// ...
?>

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, sets the ID property because the id and person columns were mapped to each other.

36 542 Users on board!

Tutorial menu

Printable

Printer Friendly version of the full article on one page with plain styles

Author(s)