Solar Models vs. Zend Framework Models
Today, Michelangelo van Dam posted this narrative relating his experience with Zend Framework models:
http://www.dragonbe.com/2010/01/zend-framework-data-models.html
I read the article, and wondered how hard it would be to replicate his narrative using the Solar Framework model system. Turns out it's pretty easy: there's a lot of work that Solar does for you.
-
Download a Solar system, move it to your localhost directory and make sure that the
tmp
andsqlite
directories are accessible to the web server.$ wget http://svn.solarphp.com/system/download/solar-system-1.0.0beta2.tgz $ tar -zxf solar-system-1.0.0beta2.tgz $ cp -r solar/* /var/www/htdocs # or your localhost directory $ cd /var/www/htdocs # or your localhost directory $ chmod -R 777 tmp sqlite
-
Create tables and data in
sqlite/example.sq3
. There are two changes from Michelangelo's code: the table names are plural, and rename the columntype_id
toaddress_type_id
. (These are easy enough to change in the model class definitions, but I'd like to minimize the amount of customization for this example.)CREATE TABLE "users" ( "id" integer primary key autoincrement, "username" varchar(255) not null, "password" varchar(255) not null ); CREATE TABLE "contacts" ( "id" integer primary key autoincrement, "user_id" integer not null, "email" varchar(255) not null, "phone" varchar(255) null, "fax" varchar(255) null ); CREATE TABLE "addresses" ( "id" integer primary key autoincrement, "address_type_id" integer not null default 1, "user_id" integer not null, "address1" varchar(255) not null, "address2" varchar(255) null, "city" varchar(255) not null, "state" varchar(255) null, "zip" varchar(255) not null, "country" varchar(255) not null ); CREATE TABLE "address_types" ( "id" integer primary key autoincrement, "type" varchar(255) not null ); -- Data for users table -- INSERT INTO "users" VALUES (1, 'testuser1', 'test123'); INSERT INTO "users" VALUES (2, 'testuser2', 'test234'); -- Data for contacts table -- INSERT INTO "contacts" VALUES (1, 1, 'test1@example.com', '1-800-555-1234', '1-800-555-1230'); INSERT INTO "contacts" VALUES (2, 2, 'test2@example.com', '1-800-555-2234', '1-800-555-2230'); -- Data for addresses table -- INSERT INTO "addresses" VALUES (1, 1, 1, '1 Test Home', '', 'Testtown', 'ZF', '1234', 'PHP'); INSERT INTO "addresses" VALUES (2, 1, 2, '2 Test Home', '', 'Testtown', 'ZF', '1234', 'PHP'); INSERT INTO "addresses" VALUES (3, 2, 2, 'Test Corp, LTD', '4 Test Ave', 'Testtown', 'ZF', '1234', 'PHP'); -- Data for address_types table -- INSERT INTO "address_types" VALUES (1, 'Home address'); INSERT INTO "address_types" VALUES (2, 'Billing address');
-
Make sure the SQLite database is accessible to the web server.
$ chmod 777 sqlite/example.sq3
-
Make a vendor space for the controllers, models, suppory libraries, etc. For this example the vendor will be named
Example
.$ ./script/solar make-vendor Example
-
Edit the system configuration in
config.php
. Change the front-controller class prefixes and model catalog class prefixes, and tell the SQLite adapter which file name to use.// front controller $config['Solar_Controller_Front'] = array( 'classes' = array('Example_App'), // ... the rest of the front-controller array ... ); // model catalog $config['Solar_Sql_Model_Catalog']['classes'] = 'Example_Model'; // add sqlite config $config['Solar_Sql_Adapter_Sqlite'] = array( 'name' => "$system/sqlite/example.sq3", );
-
Make the model classes. Note that this avoids a ton of effort that Zend Framework requires: Michelangelo had to hand-create table, model, and mapper classes for each of the following single-line commands.
$ ./script/solar make-model Example_Model_Users $ ./script/solar make-model Example_Model_Contacts $ ./script/solar make-model Example_Model_Addresses $ ./script/solar make-model Example_Model_AddressTypes
-
Edit the model classes to express what the related models are:
/** source/example/Example/Model/Users.php */ protected function _setup() { // chain to parent parent::_setup(); // relateds $this->_hasOne('contact'); $this->_hasMany('addresses'); } /** source/example/Example/Model/Contacts.php */ protected function _setup() { // chain to parent parent::_setup(); // relateds $this->_belongsTo('user'); } /** source/example/Example/Model/AddressTypes.php */ protected function _setup() { // chain to parent parent::_setup(); // relateds $this->_hasMany('addresses'); } /** source/example/Example/Model/Addresses.php */ protected function _setup() { // chain to parent parent::_setup(); // relateds $this->_belongsTo('address_type'); $this->_belongsTo('user'); }
-
Make a skeleton app (i.e., a controller with its associated actions and views):
$ ./script/solar make-app Example_App_Accounts
-
Edit the controller action to fetch user account data:
/** source/example/Example/App/Accounts.php */ public $list; public function actionIndex() { // get a model catalog $model = Solar_Registry::get('model_catalog'); // populate $this->list with all users. // eager-fetch the contact record and addresses collection. $this->list = $model->users->fetchAll(array( 'eager' => array( 'contact', 'addresses', ), )); }
-
Edit the view for the index action. This could be a view and a partial, but let's keep it straightforward for now.
/** source/example/Example/App/Accounts/View/index.php */ <table> <tr> <th>Username</th> <th>E-Mail</th> <th>Phone</th> <th>Fax</th> <th># addresses</th> </tr> <?php foreach ($this->list as $user): ?> <tr> <td><?php echo $this->escape($user->username); ?></td> <td><?php echo $this->escape($user->contact->email); ?></td> <td><?php echo $this->escape($user->contact->phone); ?></td> <td><?php echo $this->escape($user->contact->fax); ?></td> <td><?php echo count($user->addresses); ?></td> </tr> <?php endforeach; ?> </table>
You're done. Browse to http://localhost/index.php/accounts/index
to see the results of your handiwork.
Total elapsed time from when I read Michelangelo's article to come up with the Solar conversion and write this article: under two hours.
Solar makes model creation and interaction very easy and very powerful. Maybe your next project should use Solar instead of Zend Framework?