Quick search:

13. M to N Relationship

This example requires phpPeanuts version 1.2 or higher and is not included in 1.0. It is situated in the example13 folder. To run it on your own server you need you need to create its table and data by executing the SQL in the file 'examples.sql/example13.sql'. To try it out on the phpPeanuts website click here.

It extends a copy of example 12 with a new type Keyword that has an n to m relationship with Activity. The relationship is implemented using a new feature of multi value properties (requires 1.2). On the Keyword class in initPropertyDescriptors a multi value property 'Activities' was defined to hold instances of Activity. The line
  $prop->setDerivationPath('activityRelations.activity');
then instructs the property to derive its values by navigating the property 'activityRelations', and from there the property 'activity'. Navigating the property 'activityRelations' returns an Array with instances of KeywordRelation. From each KeywordRealtion navigating the property 'activity' returns an instance of Activity. These are collected in an Array and returned. See also how to add relationship navigation.

The other side of the relationship is defined on class Activity in the same way: A multi value property 'keywords' is defined to derive its values by navigating the path keywordRelations.keyword. Multi value properties do not really navigate this way. In fact they use an optimization, getting their values directly from the database through a JOIN.

On the side of Keyword the user interface in the example shows a normal propertyPage. With the line
  $prop->setVisible(false);
the property 'activityRelations' was set invisible, so you do not get a button for a PropertyPage for this property.

On the side of Activity an MtoNPropertyPage was used. Since version 1.3 the default user interface does automaticly use an MtoNpropertyPage for a multi value property whose name is in the uiFieldPaths. For this Employee defines a getUiFieldPaths method that gets the uiPropertyDescriptors from the classDescriptor and returns their keys with 'keywords' added. 

For Projects a different solution is chosen: the ProjectEditDetailsPage shows an MtoNDialogWidget. If the user clicks in this widget an MtoNDialog pops up, which is similar to an MtoNPropertyPage, but sets the values chosen in the widget. To get this MtoNDialogWidget a class ProjectEditDetailsPage was added twith a method getExcludedMultiValuePropButtonKeys returning an array with 'keywords' as a key. This excludes the property 'keywords' from the multi value property buttons. Because it is still in the uiFieldPaths (inherited by Project) the default user interface adds the MtoNDialogWidget (since 1.4.beta1).

There are a few more things to take a look at: In the first place the example implements maintenance of a dependency between KewordRelation and both classes it relates: If an Activity is removed, it will also remove its keywordRelations. This is implemented in the method deleteDependents that is called by the delete method. On the other hand, before a Keyword is removed, it checks that there are no more activityRelations. This is implemented by getDeleteErrorMessages.

Finally, one method that could have been implemented was not: keywordsMtoNmodIds. This modifier method is only necessary if we do want other then the default n to m relationship behaviour.