zircote.com

development (in)action

Starting a Zend Framework Project [2/2]

Previously I discussed the creation of a ZF project skeleton; having established the test suite, build file, phpdoc and phpcs processing, we can now begin building the database models. I will also expand on relationships within the models and will cover the implementation of model relationships using Zend_Db_Table_Relationship.

The Database

For the purpose of this entry, I will utilize the database model described in the Zend Framework documentation; this database contains four tables:

  • accounts
  • products
  • bugs
  • bugs_products

To create the database follow, the commands outlined below. Be sure to ‘cat’ the contents of the following gist into db/development.sql:

Now that your database is created we may generate the table models.

Table Models

To generate table models, we will employ the zf cli providers; it should be noted that while it is possible to create them by hand this does not maintain the manifest. .zfproject.xml . The commands to create the models are as follows:

It should be noted that additional parameters are available. The list of parameters are as follows:

  • name: the models name, this will be in addition to the namespace portion; ie App_Model_DbTable_
  • actual-table-name: the table name within the database
  • module: the module the model will reside, in this case default in which case we submit nothing
  • force-overwrite: whether to rewrite the model

It should be noted that commands in the ‘zf’ project provider will also accept parameters in the following manner -f force-rewrite -m module -n name -a actual-table-name

Table Relationships

The Zend_Db package also provides the tools to create and maintain relations between models enabling a series of methods that allow for child and parent queries from result row sets. As the db models are extended from Zend_Db_Table there are two properties of interest, Zend_Db_Table::dependentTables and Zend_Db_Table::referenceMap.

We will begin with the ZendDb_Model_DbTable_Accounts and declare our dependant table, ZendDb_Model_DbTable_Bugs as an array member of the ZendDb_Model_DbTable_Accounts::referenceMap property. Following the ZendDb_Model_DbTable_Accounts model, we will next detail the ZendDb_Model_DbTable_Bugs model and associated references, and dependencies. Within the bugs table three columns are dependencies of accounts table, reported_by, assigned_to, and verified_by each of which references accounts. This is represented in the model ZendDb_Model_DbTable_Bugs::referenceMap as follows:

For the cascading actions for Zend_Db_Table::_referenceMap there are three class constants provided for declaration:

  • Zend_Db_Table::CASCADE
  • Zend_Db_Table::RESTRICT
  • Zend_Db_Table::SET_NULL

Additional details maybe found at:

Zend_Db_Table_Definition

As an alternative to defining relationships within each model there is another option, Zend_Db_Table_Definition for this projects database definitions. I would prefer to maintain the definitions within the application.ini and utilize the resource autoloader to place it within a Zend_Registry container (note: it is possible to utilize a separate .ini file for the database definition.) It will also be necessary to change the models to extend from the Zend_Db_Table instead of Zend_Db_Table_Abstract , in order to gain the constructor functionality required to define the definition and key specific to each model. Within the models we may now define our database definition as well as the definition key in the constructor. To begin the changes required to enable the table definitions, we first must create the resource entries within the application.ini. These definitions are laid out in the .ini in the same manner as an array. Note the first keyname (‘resources’) is required so the bootstraper will seek to use it to find the bootstrap method within the Bootstrap class.

Next we create the resource bootrap method within the Bootstrap.php. The goal of this is to load and instantiate the Zend_Db_Table_Definition object and store it within a Zend_Registry container for use by our models.
Next, we must modify our models to reflect the changes, namely the constructor. Within these models constructors we pass the definition key that corresponds to the class in question as the first parameter; with the second parameter, we will pass the definition object which we will acquire from the Zend_Registry container created within the bootstrap. We must do this for all database models.
Having updated the models, application.ini and Bootstrap.php examples of their magic methods, as well as explicit calls, may be found in the Zend Framework reference guide; I have also provided the following snips to demonstrate explicit calls: