Level: Intermediate Duane O'Brien (d@duaneobrien.com), PHP developer, Freelance
16 Oct 2007 This "PHP
frameworks" series takes a look at three widely used PHP frameworks — Zend,
symfony, and CakePHP — examining their similarities and differences while
building and extending a sample application in each of the three frameworks. Part 1
laid out the scope for the series and got the prerequisites out of the way. Here in
Part 2, you will build the sample application in each of the three frameworks.
In Part 1 of this series, we laid out the scope for
the series and got the prerequisites out of the way. Now, you will build
the sample application in each of the three frameworks. In future articles, you will
extend the application, look at exceptions to the rule, play with Ajax, integrate
external tasks, and much more.
This article walks you through creating the sample application, Blahg, in each of the
three frameworks. You'll do it all from scratch, learning the basics of
developing a simple application in the Zend Framework, symfony, and CakePHP.
You should have already gone through Part 1, which covers installation and
prerequisites for each framework. If you haven't, you should do so now.
It is assumed that you already know PHP, application design, and how to work in a
database. It's not necessary to have used a framework before, but you should certainly
be ready to jump in with both feet.
Building Blahg in the Zend Framework
To start, create the directories /column/htdocs/zend and /column/protected/zend. These
will hold Web-accessible files and application files that should not be Web-accessible,
respectively. In /column/htdocs/zend, create an .htaccess file with the following
lines:
RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
|
Each framework has its own particular needs when it comes to directory structures. For
the Zend Framework, you need to create the directories
/column/protected/zend/controllers, /column/protected/zend/models, and
/column/protected/zend/views to hold your controllers, models, and views. Additionally,
you need to create the directory /column/protected/zend/views/scripts; and for each
controller, you need to create a directory to hold some views. For example, you know
Blahg is going to need some views for the post controller, so you need to create the
directory /column/protected/zend/views/scripts/post to hold this view.
You've got your directories in place. Time to build your model.
Building your Zend posts table and model
In Part 1, you created the posts table you will be using. If you skipped that, go back
and do it now. The model for this table will be very simple. It should be called
Posts.php, and you should create it in /column/protected/zend/models/. Posts.php will
extend the Zend_Db_Table class, and you'll be using most the
inherited methods from that class. If you open up the Posts.php file in the code
archive, you will see very little actual code.
Building your Zend Front controller
and PostController
For your Front controller, you will create an index.php file
in /column/htdocs/zend. This file is the only part of your application exposed
to the outside world. The rest of your application is accessed through this file. The
Front controller needs to do several things: load the Zend
Loader (to avoid having to include every library by hand), set up your connection to
the database, and dispatch requests to the appropriate application controllers; in this
case, that's only the PostController.
As you might have guessed, you will be creating the file PostController.php in the
/column/protected/zend/controllers directory. The PostController you need to create is fairly simple.
For starters, you need to include the posts model you created earlier. And you should
probably create an init method, which will be called when
the PostController object is created. In the init method, you can set up the view and model objects you will
use in the subsequent actions. You can probably surmise that you need three
actions: indexAction, readAction, and writeAction (the
xxxxxAction naming convention for actions is part of doing things in the Zend Framework).
The indexAction is simple: get all the posts and assign them
to the view. The readAction isn't much more complicated: get the post ID
from the request, retrieve the post, and assign the post to the view. The writeAction isn't all that complicated, either. If a
request has been posted, strip any tags and save the data to the database. Otherwise,
render the form.
Take a look at the PostController in the code archive for
details on the syntax and structure. Now that your controllers are done, you can move on to your views.
Building your Zend post views
You're almost done. Blahg requires a number of views, and you create them
all in the /column/protected/zend/views/scripts/posts directory. You'll need at least
three views (index.php, read.php, and write.php), though the code in the code archive
makes use of four. The views are simple files: The index and read views simply
output the data assigned to them, applying minimal formatting, while the write view
displays a form to be used when posting to Blahg. Take a look at the views in the code download for details.
If you've created your model, controllers, and views properly (or installed the code properly), you should be able to try out the
Zend Framework version of Blahg by going to http://localhost/zend/post (assuming you installed everything locally).
You are probably itching to play around with Blahg. Don't get carried away yet.
You still have two more frameworks to go.
Building Blahg in symfony
Building Blahg in symfony is somewhat different. For starters, you need to initialize
the project using symfony's command-line utility.
Running the symfony init commands
Switch to a terminal window and create the directory /column/protected/sf_column using
a using a command line. This will be the protected directory to hold all the symfony
code for the column. All of your symfony command-line work must be done from this
directory. Change into the sf_column directory and execute the following command:
php /column/protected/symfony/data/bin/symfony init-project sf_column.
This command will create a slew of directories and files in /column/protected/sf_column
that are required for a symfony project. Next, you'll need to init the Blahg application. In the sf_column directory, execute the following command: php /column/protected/symfony/data/bin/symfony init-app blahg.
This command will create some more directories and files, largely in
/column/protected/sf_column/apps. But before you can use most of this, you need to
rearrange some of the files. Remember, your installation is exposing very few files to
the outside world. The application structure built by the symfony init scripts don't know what your directory structure is.
Fortunately, you can change that by adding the following lines to the end of
/column/protected/sf_column/apps/config/config.php.
Listing 1. Changing the application structure for the
symfony init scripts
$sf_root_dir = sfConfig::get('sf_root_dir');
sfConfig::add(array(
'sf_web_dir_name' => $sf_web_dir_name = 'symfony',
'sf_web_dir' => DIRECTORY_SEPARATOR.'column'.DIRECTORY_SEPARATOR.'htdocs'.
DIRECTORY_SEPARATOR.$sf_web_dir_name,
'sf_upload_dir' => DIRECTORY_SEPARATOR.'column'.DIRECTORY_SEPARATOR.
'htdocs'.DIRECTORY_SEPARATOR.$sf_web_dir_name.DIRECTORY_SEPARATOR.
sfConfig::get('sf_upload_dir_name'), ));
|
In essence, these lines are telling symfony where to find your web directory.
Now that you had added these lines, you should move the contents of
/column/protected/sf_column/web to /column/htdocs/symfony (create this directory if you
haven't already). And last but not least, you need to modify
/column/htdocs/symfony/index.php so it knows what the real root directory is for your
project. Replace the existing define for SF_ROOT_DIR with the following line:
define('SF_ROOT_DIR', '/column/protected/sf_column');.
You're almost done. Now you just need to init the post
module for Blahg. This means running another command at the command line:
php /column/protected/symfony/data/bin/symfony init-app
blahg. This command, like the others, builds up some files and directories, this
time in /column/protected/sf_column/apps/blahg/modules/post.
Now that you have symfony up and running, it's time to cobble together Blahg.
NOTE: symfony provides functionality to auto-generate code to provide the Create, Read, Update, and Delete (CRUD) functionality based on your database. While this can help you
get the basics of an application together quickly, using it in this context wouldn't
give you much of a feel for how a symfony application fits together. For the purpose
of this article, you'll build your application by hand.
Generating the model
Again, the posts table you will use was created in Part 1.
Because symfony uses Propel to provide Object Relational Mapping, you need to generate
the model with the symfony command-line utility. This requires that you describe your
database scheme and provide some database information first.
NOTE: Technically, providing the database information first isn't necessary. symfony
builds the model based on the schema, and the command-line utility can even be used to
generate SQL scripts to create a database based on the schema definition. We'll try
that in a subsequent article.
For the database and schema definition files, symfony uses Yet Another Markup Language
(YAML). YAML isn't too complicated, but if you've never used it before, it can seem
confusing. At this stage, the main thing to know about YAML is that whitespace is
significant. You use two spaces for an indent, and you never use tabs.
Now you will edit your database.yml and schema.yml files. They live in
/column/protected/sf_column/config. And your schema.yml file needs to be edited to describe the posts table. Edit your
schema file to contain the following information.
Listing 2. Editing the schema.yml file
propel:
posts :
_attributes: { phpName: Post }
id:
title: varchar(255)
text: longvarchar
modified: timestamp
|
NOTE: Since you probably copied and pasted that code, go back and make sure that each
indent is two spaces, and that no tabs were used. For example, the modified line
should have four spaces in front of it (two for the indent to posts and two for the
indent to modified).
Your database.yml file should be edited to contain your specific database parameters.
It might look something like Listing 3.
Listing 3. The database.yml file
all:
propel:
class: sfPropelDatabase
param:
phptype: mysql
hostspec: localhost
database: symfony
username: frameworks
password: fwpw
|
That shouldn't have been too hard. Now that your schema and database configurations
are complete, you can generate your model. Return to the command line you were using
earlier, and in /column/protected/sf_column, execute the following commands:
php /column/protected/symfony/data/bin/symfony propel-build-model
php /column/protected/symfony/data/bin/symfony clear-cache
|
Each command will output a large amount of data, but the important end result is
the creation of the Post.php and PostPeer.php files in
/column/protected/sf_column/lib/model — these are your models. If you open them
up, you'll see there's not much there. They just extend the base model classes.
NOTE: Whenever you rebuild your models, it is important to run the
clear-cache command as above. Also note that if you installed symfony using
the PHP Extension and Application Repository (PEAR), you can just run
symfony propel-build-model without calling PHP
first or providing the full path to the binary. Not everyone has the option
of using PEAR their environment, which is why we described the alternate
installation instructions in Part 1, and the corresponding model-generation instructions above.
That's it! Your model for this round is done. A lot more could be said about
models, but it's time to move on to your controller.
Building out the controller
You don't need to write a Front Controller like you did in Zend, as symfony has already
provided this for you.
Your post controller will actually be called actions.class.php and will live in
/column/protected/sf_column/apps/blahg/modules/post/actions. This controller will
handle all the actions for the post module. Like before, you need three actions,
but the names are different: executeIndex, executeRead, and executeWrite (the
executeXxxxxx is the naming convention used by symfony for actions and must be followed).
The executeIndex action is simple: Retrieve the posts and
make them available to the view. The executeRead action is also simple: Take in the post ID,
retrieve the post, and make the post data available to the view. The executeWrite action takes in the title and text from the
request and saves the data to the database, returning the ID of the post that was saved.
Take a look at the post/actions/actions.class.php in the code download for details on
the syntax and structure. Now that your controller is done, you can move on to your views.
Building out the views
Your post views will live in
/column/protected/sf_column/apps/blahg/modules/post/templates. You need three
views: indexSuccess.php, readSuccess.php, and writeSuccess.php (the xxxxSuccess.php
naming convention is part of symfony and must be followed).
These views won't render into a complete HTML document like the Zend views did.
symfony provides a default layout template (in apps/blahg/templates/layout.php) that
provides the basic head andfoot of the HTML page. All you need to provide is the
middle of the view — content specific to the action. For example,
indexSuccess.php just needs to loop through and format the provided array of posts,
readSuccess.php just formats the post content, and writeSuccess.php displays the
form or outputs your success message if a post has been submitted.
If you've created or installed everything properly, you should be able to try out the
symfony version of Blahg by going to http://localhost/symfony/post (assuming you installed everything locally).
So you've seen how Blahg fits together in the Zend Framework and symfony. Two down, one to go.
Building Blahg in CakePHP
Before you can start building Blahg in CakePHP, you need to move some of the files
around. Then you'll set up your database connection and let Bake take over.
Setting up the file structure
Take a look at the /column/protected/cakephp/ directory. You should see four
directories: application (the directory that will hold your application), cake (the
directory containing Cake's core files), docs (readme docs), and vendors (where you put
third-party libraries you may use). There are also two files: index.php and .htaccess.
These two files only come into play when you install CakePHP in the webroot. This is
generally a bad idea, as it makes all of your application files accessible to anyone
using a Web browser.
The preferred method of installation is to make /column/protected/cakephp/app/webroot
the root directory for your Web server. Equally viable (and preferred for this series)
would be to copy the contents of /column/protected/cakephp/app/webroot into a
Web-accessible directory (in this case, /column/htdocs/cakephp). Go ahead and do this
now.
Once you've copied the files over, you need to open up
/column/protected/cakephp/app/webroot/index.php and make a couple edits: The existing
definitions for ROOT and APP_DIR
need to be updated. They should look something like Listing 4.
Listing 4. Definitions of ROOT and APP_DIR
if (!defined('ROOT')) {
define('ROOT', DS . 'column' . DS . 'protected' . DS . 'cakephp');
}
if (!defined('APP_DIR')) {
define('APP_DIR', 'app');
}
|
That's enough to get you going, but you may as well enter in your database information
and update core.php with a unique value for CAKE_SESSION_STRING.
In /column/protected/cakephp/app/config/ make a copy of database.php.default called
database.php and enter the host, login, password, and database name for your system.
Also, in /column/protected/cakephp/app/config/core.php, change the define for
CAKE_SESSION_STRING to include a new value, such as define('CAKE_SESSION_STRING', 'He had a Subbuteo player in his hair. I got distracted.');.
You've got the preliminaries out of the way. Time to jump into the cake.
NOTE: Like symfony, CakePHP provides functionality to auto-generate code to provide
the CRUD functionality based on your database. CakePHP also provides scaffolding, which
provides a similar service without generating any code at all. Both of these features
help you get the basics of an application together quickly, but as mentioned, using
these features in this context wouldn't give you much of a feel for how to build an application in CakePHP.
Create the table and model
If you don't have a posts table, you skipped that part of Part 1, so go back and do it
now. Create a file called post.php in the /column/protected/cakephp/app/models
directory. This will contain the class definition for your model. The definition is a
simple one: The class is Post and extends AppModel, and you should set the class variable $name to post.
That's really all there is. Your model will be using all inherited methods from AppModel. Now you can move on to your controller.
NOTE: You may have noticed that the table is called posts (plural), while the model name
is post (singular). This is an important part of Cake conventions. Models are always
singular, and their corresponding tables are always plural.
Building the Cake posts controller
Your posts controller will be simple, like the other
controllers you have written today. You will pull in a couple helpers, then define
three actions: index, read, and write.
The index action gets a list of posts and makes them available to the view. The read action gets the ID of a post, retrieves the post and makes the
post data available to the view. The write action accepts a
submission (if there was one) and saves the data to the database.
Take a look at the /column/protected/cakephp/app/controllers/posts_controller.php in
the code download for details about the syntax and structure.
Your controller is done. Now you can move on to your final views.
Building the Cake views
You'll need the same three basic views you created for Blahg in the other frameworks.
In this case, you'll create the files index.ctp, read.ctp, and write.ctp in the
/column/protected/cakephp/app/views/posts directory. These are just templates CakePHP
will use, much like the templates you created in symfony. Take a look at these files
in the code archive. The views make extensive use of the forms and HTML helpers to
output links and form elements, but they should look similar to the other views you created for symfony.
Note that the views do not render to complete HTML files. A default layout is provided
by CakePHP. These default layout files are located in
/column/protected/cakephp/cake/libs/views/templates/layouts, but you shouldn't modify
them. If you want to change the default layout, place a copy of the default.ctp layout
file in /column/protected/cakephp/app/views/layouts and modify it according to your needs.
Note: Forms and links in Cake are much easier to maintain when using these helpers, as
Cake will make sure your links point to the right places in the application should it
be installed or moved to a different directory, and Cake will do a lot of heavy lifting
for you if your form element names are formatted properly.
Build the views according to the Blahg's needs, or install the views from the code download. Assuming you've written and installed
everything properly, you should be able to try out the CakePHP version of Blahg at
http://localhost/cakephp/posts (assuming you've installed locally).
Summary
You gotten quite a lot done. You've installed three frameworks, gotten them each up
and running, and created a basic application in each framework.
Spend some time playing
around with Blahg in each framework, then try your hand at extending Blahg in each
framework. Try writing a comments controller that will allow users to post their own
replies to each post. Don't get too wrapped up in linking the comments to the posts
just yet, though. But if you feel up to it, dive in! In Part 3, you are provided with some code that covers this.
Download | Description | Name | Size | Download method |
|---|
| Part 2 sample code | os-php-fwk2.zip | 11KB | HTTP |
|---|
Resources Learn
-
Read the rest of this "PHP
frameworks" series.
-
See the Zend Framework manual.
-
Get the symfony documentation.
-
Check out the CakePHP Manual (Note: The manual is
written to CakePHP V1.1. There may be some variance as you are using CakePHP V1.2).
-
Read the five-part series "Cook
up Web sites fast with CakePHP."
-
Visit Wikipedia for a high-level view of software
frameworks.
-
Get on overview of the MVC architecture from Wikipedia.
-
Refer to the PHP Manual for more information.
-
Visit PHP.net for additional PHP documentation.
-
For tutorials about learning to program with PHP, check out the developerWorks
"Learning PHP" series.
-
PHP.net is the central resource for PHP developers.
-
Check out the "Recommended PHP reading list."
-
Browse all the PHP content on developerWorks.
-
Expand your PHP skills by checking out IBM developerWorks' PHP project resources.
-
To listen to interesting interviews and discussions for software developers, check out developerWorks podcasts.
-
Using a database with PHP? Check out the Zend Core for
IBM, a seamless, out-of-the-box, easy-to-install PHP development and production environment that supports IBM DB2 V9.
-
Stay current with developerWorks' Technical events and webcasts.
-
Check out upcoming conferences, trade shows, webcasts, and other Events around the world that are of interest to IBM open source developers.
-
Visit the developerWorks Open source zone for extensive how-to information, tools, and project updates to help you develop with open source technologies and use them with IBM's products.
-
Watch and learn about IBM and open source technologies and product functions with the no-cost developerWorks On demand demos.
Get products and technologies
Discuss
About the author  | |  | Duane O'Brien has been a technological Swiss Army knife since the Oregon Trail was text only. His favorite color is sushi. He has never been to the moon. |
Rate this page
|