menu_banner (2K)

Appendix I: Passing context between objects

In this documentation the term "context" is used to mean the identity of an entity within the application database, and usually consists of the primary key from the associated database table.

An application developed using this framework may have many tasks dealing with many entities, and a common structure is to start with a LIST screen which shows summary information from several occurrences from a particular database table. From here the user can select one or more occurrences and navigate to other tasks, such as an ENQUIRY screen, to show more details concerning the selected occurrences. The processing of selecting occurrences in a parent task then navigating to a child task to show more levels of detail is known as the drill down technique. The selecting of occurrences in the parent task determines the context which is passed to the child task so that when the child task is activated it knows which occurrence(s) to deal with without having to ask the user. The user does not have to type in the identities of the selected occurrences, simply mark them as "selected" and press a button on the navigation bar.

For example, a user may start at a "List Customer" screen which shows several rows of summary information, one row per customer. The user can select one or more rows in this screen and press the "Show Details" button to activate a different screen which shows more details concerning those customers, one customer at a time. The user can then press the "Show Invoices" button to show a list of invoices which were sent to the current customer. Within this screen there may be another button to "Show Invoice Lines", and so on. There is no limit to the hierarchy of levels which may be navigated in this way, and context is automatically passed from the parent screen to the child screen.

Passing context to a child task/object

This is a two-part operation which involves the following:

Extracting the selection from the current task/object

The child tasks which are available to any parent task will be indicated on its navigation bar. A parent can have any number of children, and a child can have an number of parents. It is also possible for a child task to have children of its own, and each of those children to have grandchildren, and so on.

If a parent task shows multiple rows the user marks individual rows for selection by clicking on the checkbox in the "select" column at the start of each row. A row is selected if its select box is "On" and not selected if its select box is "Off".

If the parent task does not contain multiple selectable rows - in other words it only shows information concerning a single database row - then the identity of the current row will automatically become the selection which is passed to the child task.

The mechanism for extracting the identities of the selected rows is as follows:

  1. When the parent task retrieves data from the database it will display each database row (occurrence) on a separate row (line) in the screen with its own select box.
  2. Although the primary key for each row may not be displayed on the screen it should still be included in the task's select list.
  3. All the retrieved data will be stored in the $_SESSION array which has a separate area for each object within each task.
  4. The user selects one or more rows and presses a button on the navigation bar which generates an HTTP request using the POST method for the current task, not the child task.
  5. The information in the POST array does not identify the primary keys of the selected records, it simply identifies the row numbers within the current object.
  6. The current object will obtain the names of the fields which constitute the primary key of the current database table. This is done in two parts:
  7. The current task will then iterate through the array of saved database data to extract the values for each primary key field from each database row which has been selected. The result will be a $selection string similar to the following:
    (fieldname='fieldvalue')
    (fieldname1='fieldvalue' AND fieldname2='fieldvalue')
    (fieldname1='fieldvalue') OR (fieldname1='fieldvalue')
    
    This $selection string has the following format:
  8. The $where string for the current task will be extracted, using _cm_getWhere() to allow any temporary modifications.
  9. The current task will then write the $selection and $where strings into the child task's area in the $_SESSION array.
  10. It will then call the scriptNext() function to activate the selected child task.

Receiving the selection in the child task/object

Whenever a child task/object is activated it will look for any selections which were passed down to it from its parent task/object before it retrieves any data from the database. The procedure is as follows:

  1. The $where string and the $selection string will be extracted from the task's area in the $_SESSION array, not from arguments in the URL. This means that they will not be visible to the user.
  2. All patterns will receive both the $where and $selection strings, but their priority is as follows:

    In the case of ADD2 tasks both the $where and $selection strings will be made available to the _cm_initialise() method.

  3. During the processing of the initialise() method the contents of the $where string will be filtered to remove any references to fields which do not exist in the current database table (see Different Names). This will prevent the subsequent database retrieval from failing. This list of fields is obtained in the following manner:
  4. If the child task can display multiple occurrences then the pagination area will contain hyperlinks if more occurrences were retrieved than can fit on a single page.
  5. If the child task can display details from a single occurrence then the scrolling area will contain hyperlinks if more than one occurrence was retrieved.

Passing context to a child object within the same task

Some tasks, such as those which are based on the LIST2, LIST3, MULTI2 and MULTI3 patterns, contain more than one database object either in an outer-inner or outer-middle-inner configuration. The processing flow starts with the outermost object and moves in sequence down to the innermost as follows:

  1. The outermost object receives any selection passed down from a parent task as documented above.
  2. The outermost object can only display one database occurrence at a time, so its scrolling area will contain hyperlinks if more than one occurrence was retrieved.
  3. Before the processing flow passes to the next object (middle or inner) the primary key of the current occurrence in the outer object will be extracted using the following procedure:
  4. This $where string is passed to the next object so that it can retrieve its own records from the database (see Different Names).
  5. If the second object is not the innermost object then it can only display one database occurrence at a time, so its scrolling area will contain hyperlinks if more than one occurrence was retrieved. The primary key of the current occurrence is extracted into a new $where string which is then passed to the third object.
  6. If the second object is the innermost object then then the pagination area will contain hyperlinks if more occurrences were retrieved than can fit on a single page.
  7. If a navigation button is used in this task then a $selection string will be extracted from the innermost object using the procedure described above so that it can be passed to the next task.

Context which is not selected by the user

If a task is activated from a button in the menu bar there is no user-definable context which can be passed to it. It is possible, however, to provide preset selection criteria in various ways as documented in FAQ 71.

Different names for the same field

Note that if the $where string, as passed down from a parent object, contains a reference to a field which exists in the current table but with a different name in the parent object, then that name must be converted manually into the one used by the current table otherwise the subsequent call to getData() may not retrieve the correct records. This is typically the case where the primary key of the parent table has a different name from the foreign key in the child table. This conversion of field names can usually be performed in the _cm_pre_getData() method using code similar to the following:

    $where = str_replace('node_id=', 'node_id_snr=', $where);

Note that although the $parent_relations array contains information regarding which fields are used in the relationship between two tables, or even where a table is related to itself, this is only used in the ON clause of a JOIN when that table object is asked to construct an sql SELECT statement prior to retrieving its own data. This information cannot be used to automatically translate field names in a WHERE string which is passed down from an external source as there is no information which identifies which of the many possible relationships is involved.

This is described in more detail in FAQ129.


http://www.tonymarston.net
http://www.radicore.org

counter