Added by Wil Sinclair, last edited by Wil Sinclair on Aug 11, 2008 ( )
Labels
Zend Framework QuickStart
Co-authored by Aldemar Bernal, Bradley Holt, & Wil Sinclair
Zend Framework is an open source, object oriented web application framework for PHP 5. ZF is often called a 'component library' because it has many loosely coupled components that you can use more or less independently, but it also provides an advanced model-view-controller (MVC) implementation that can provide the basic structure for ZF applications. A full list of Zend Framework components along with short descriptions may be found here . This QuickStart will introduce you to some of ZF's most commonly used components: Zend_Controller, Zend_View, Zend_Layout, Zend_Form, and Zend_Db.
Using these components, we will build a simple database-driven blog application within minutes. The complete source code for this application is available in the following archives:
MVC
So what exactly is this MVC pattern everyone keeps talking about, and why should you care? MVC is much more than just a three-letter acronym (TLA) that you can whip out anytime you want to sound smart; it has become something of a standard in the design of modern web applications. And for good reason. Most web application code falls under one of the following three categories: presentation, business logic, and data access. The MVC pattern models this separation of concerns well. The end result is that your presentation code can be consolidated in one part of the application with your business logic in another and your data access code in yet another. Many developers have found this well-defined separation indispensable for keeping their code organized- especially when more than one developer is working on the same application. More Info. . .
![]() | Use-at-Will MVC Zend Framework provides a very simple, yet powerful, MVC implementation around which most ZF developers organize their applications. But- as is the case for all ZF components- our MVC components can be used at will. This means you can still take advantage of ZF's database, forms, web services- even view- components without necessarily consuming all of its MVC components. |
Building an Application
Project Structure
Let's first create a basic MVC project structure for our application under the directory QuickStart:
Since the public directory will contain all files that should be directly accessible via our web server, you must set your web server's document root to this directory. Please check your web server's documentation on how to do this.
![]() | We will assume that your web server is running on your local machine and that your public directory is accessible at http://localhost/.
|
![]() | You can use the project structure that best suits your needs! You will soon discover that Zend Framework is very flexible, and the project structure for ZF applications is no exception. There is nothing special about the project structure above, except some of the MVC components we'll be using work without overriding defaults in this structure. See the Zend Framework Reference Guide for more information. |
Download and Install Zend Framework
Download the latest version of Zend Framework and extract the contents of the library folder to your project's library directory. You should now find the top-level Zend directory which contains all Zend Framework components under your library directory.
That's it! Zend Framework is now installed and ready to use.
Create a Rewrite Rule
Zend Framework's MVC implementation makes use of the Front Controller pattern. You must therefore rewrite all incoming requests (except those for static resources, which your application need not handle) to a single script that will initialize the FrontController and route the request.
If you're using mod_rewrite for the Apache web server, create the file QuickStart/public/.htaccess with the following contents:
This rewrite rule will cause all requests for URLs that do not end in .js, .ico, .gif, .jpg, .png, or .css to be dispatched to index.php. This is because files with these extensions are static resources; our application must return dynamic content on requests for all URL's that don't end with these extensions, so these requests must be handled by our PHP scripts. Since all requests for dynamic content will be rewritten to it, theindex.php file serves as the entry point to our application.
![]() | Some web servers may ignore .htaccess files unless otherwise configured. Make sure that your web server is configured to read the .htaccess file in your public directory.
|
![]() | Checkpoint Let's make sure everything is working so far. Create the file index.php and add the following contents:
Now open your favorite browser and enter the URL http://localhost/ to see a simple page that says "Hello, Zend Framework!" If this does not work, check your web server logs and make sure you have rewrite enabled with the correct rewrite rules for your web server. |
![]() | Best Practices and Closing Tags We didn't forget the closing (?>) PHP tag! We intentionally omit it to avoid unintentional output of whitespace in the response in certain cases. In fact, this is one of the best practices recommended in the Zend Framework coding standards. |
Create a Bootstrap File
Let's take a quick look at that index.php file now. Replace the contents of QuickStart/public/index.php with the following:
<?php |
require '../application/bootstrap.php'; |
view plain | print | ? |
This index.php script doesn't do much, but it is interesting in that it illustrates another best practice for Zend Framework applications. For security reasons, it is advisable to keep your application's scripts in a directory that your web server does not make publicly accessible. In this case, index.php immediately hands over control to the bootstrap.php file, which resides in the more secure application directory.
Now we need to create our bootstrap.php file, so called because it 'bootstraps' the application on each user request. Create theQuickStart/application/bootstrap.php file with the following contents:
<?php |
// Step 1: Enable all errors so we'll know when something goes wrong. |
error_reporting(E_ALL | E_STRICT); |
ini_set('display_startup_errors', 1); |
ini_set('display_errors', 1); |
// Step 2: Add our {{library}} directory to the include path so that PHP can find the Zend Framework classes. |
set_include_path('../library' . PATH_SEPARATOR . get_include_path()); |
// Step 3: Set up autoload. |
// This is a nifty trick that allows ZF to load classes automatically so that you don't have to litter your |
// code with 'include' or 'require' statements. |
require_once "Zend/Loader.php"; |
Zend_Loader::registerAutoload(); |
// Step 4: Get the front controller. |
// The Zend_Front_Controller class implements the Singleton pattern, which is a design pattern used to ensure |
// there is only one instance of Zend_Front_Controller created on each request. |
$frontController = Zend_Controller_Front::getInstance(); |
// Step 5: Disable error handler. We'd like to see all the errors we enabled in Step 1. :) |
$frontController->throwExceptions(true); |
// Step 6: Point the front controller to your action controller directory. |
$frontController->setControllerDirectory('../application/controllers'); |
// Step 7: Dispatch the request using the front controller. |
$frontController->dispatch(); |
view plain | print | ? |
At this point you should start to see your application taking shape. The bootstrap.php script sets up the environment in which the rest of your application will be executed, as well as specifying some application-wide behavior. This script typically should not contain business logic for your application, however.
The action controllers under the directory mentioned in step 6 above comprise the part of your application that will process the user request next. Action controllers, also called page controllers, represent the 'controller' part of the model-view-controller pattern. There is obviously a lot that the happens after the dispatch() method takes over and before it hands over control to your action controller, but you don't necessarily need to know the details to write full featured applications. See the Reference Guide for details on how requests are dispatched. For now let's move on to creating the action controllers themselves.
![]() | Relative Paths Remember that QuickStart/public/index.php is the first script to which all requests are rewritten, so we must build our relative paths with respect to this file. That's how we came up with the '../library' and'../application/controllers' paths above. |
Create an Action Controller
In Zend Framework's MVC implementation, both the default action controller and the default action are named 'index'. You should therefore set up the default action controller by creating QuickStart/application/controllers/IndexController.php with the following contents:
<?php |
/** @see Zend_Controller_Action */ |
require_once 'Zend/Controller/Action.php'; |
class IndexController extends Zend_Controller_Action |
{ |
public function indexAction() |
{ |
} |
} |
view plain | print | ? |
Because we're using the standard router, requests for http://localhost will be routed to the indexAction method on the IndexController action controller, as will requests to http://localhost/index and http://localhost/index/index.
![]() | Controller and Action Name Conventions To work correctly with the standard router, action method names should follow the lowerCamelCase convention with the suffix 'Action'. Action controller classes, on the other hand, should follow the UpperCamelCase convention with the suffix 'Controller'. While the standard router should work for almost all applications, routing in Zend Framework is completely customizable. See the Reference Guidefor details. |
It may seem like indexAction() is doing nothing at all, but again Zend Framework is doing useful things for you behind the scenes. In this case it is routing the request to the appropriate view to return the correct response. Unless otherwise configured, the view it will look for isviews/scripts/index/index.phtml, where the views directory is contained in the same folder as the controllers directory you passed toZend_Controller_Front::run(). The file extension for views is yet another best practice recommended for Zend Framework applications; since view templates look suspiciously like PHP scripts in ZF, it is easier to distinguish view templates from other PHP files if you use the .phtmlextension instead of .php.
![]() | Checkpoint Let's create the view script now with the following contents:
Now go to http://localhost; you should see 'Hello, Zend Framework MVC!' with very basic formatting. |
![]() | Template Engines Although ZF has its own template engine that renders templates very similar to standard PHP, you can easily configure Zend Framework to use other template engines such as Smarty or PHPTAL. See thereference guide for details. |
Build a Form
Admittedly, our application at this point isn't very interesting. Adding some interactive content would certainly help, so let's start rendering and processing basic HTML forms using Zend_Form. Replace the contents of the IndexController.php file with the following:
/** @see Zend_Controller_Action */ |
require_once 'Zend/Controller/Action.php'; |
class IndexController extends Zend_Controller_Action |
{ |
public function indexAction() |
{ |
} |
/** |
* This function returns a simple form for adding a comment |
*/ |
public function getCommentForm() |
{ |
$form = new Zend_Form(array( |
'method' => 'post', |
'elements' => array( |
'comment' => array('textarea', array( |
'required' => true, |
'label' => 'Please Comment:' |
)), |
'submit' => array('submit', array( |
'label' => 'Add Comment' |
)) |
), |
)); |
return $form; |
} |
} |
view plain | print | ? |
Since this form has been built using the Zend_Form component, form handling should be a cinch. Validation, filtering, rendering, displaying errors, and a lot more form-related functionality are dramatically simplified with Zend_Form. By looking closely at the getCommentForm()method above, you should notice that it returns a form with a required text area for the comment and a button to submit that comment. Let's display this form in our index view to see how it looks after rendering. Replace the indexAction() method in your IndexController.php file with the following:
public function indexAction() |
{ |
$form = $this->getCommentForm(); |
if ($this->getRequest()->isPost()) { |
if ($form->isValid($_POST)) { |
$comment = $form->getValue('comment'); |
$this->view->comment = $comment; |
} |
} |
$this->view->form = $form; |
} |
view plain | print | ? |
A few things are happening here. First, we create the form to use in the rest of the method. Next, we check whether the user is submitting the form data- in which case we would expect an HTTP POST request- or loading a blank form- in which case we would expect an HTTP GET request. If the user is submitting a comment, we pass this data in the $_POST variable to the form for validation. If all goes well during validation, we get the filtered values from the form (in this case no filters have been set). We can pass these values to the view by setting the$values on the view object.
You must now alter your view so that it knows what to do with the form and any values that are passed to it. Replace the contents of thescripts/index/index.phtml file with the following:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> |
<html xmlns="http://www.w3.org/1999/xhtml"> |
<head> |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
<title>Zend Framework Quick Start</title> |
</head> |
<body> |
<h1>Basic Blog</h1> |
<?php if(isset($this->comment)) { ?> |
<p> |
You just submitted the following comment: |
<?= $this->escape($this->comment); ?> |
</p> |
<?php } ?> |
<?= $this->form; ?> |
</body> |
</html> |
view plain | print | ? |
Now your view is checking if there are any values to display and, if so, listing them. Regardless of whether values are displayed or not, the form is rendered near the end of the view.
![]() | Always keep security in mind! To build secure applications, you must always keep an eye out for vulnerabilities in your code and apply security best practices where appropriate. |
![]() | Checkpoint Let's see what our application can do now. When you go to http://localhost you should see something like this: Unable to render embedded object: File (get_form.gif) not found. And if you enter the comment "Hello, Zend_Form!" and hit the 'Add Comment' button, you should now see something like this: Unable to render embedded object: File (post_form.gif) not found. And if you do not enter a comment and hit the 'Add Comment' button, you'll see something like this: Unable to render embedded object: File (error_form.gif) not found. |
This last checkpoint should give you a taste of the power that Zend_Form can bring to your applications. Simply by setting the 'required' attribute on your 'comment' form element to true, you have built a validated form that will display an error if the comment text area is empty. The error message itself can be specified during form creation.
![]() | Better Looking Forms No one will be waxing poetic about the beauty of this form anytime soon. No matter- form appearance is fully customizable! See the decorators section in the reference guide for details. |
Access a Database
We now have a form to collect and validate data, but until the application can persist that data its value will be very limited. Since most applications use relational databases for data storage, let's try saving our blog comments using the Open Source MySQL relational database.
![]() | Pick your Favorite MySQL Distribution We won't get in to detailed installation instructions for MySQL in this QuickStart. Fortunately, there are several free distributions of MySQL that make installation trivial. One such distribution is[http://www.zend.com/en/products/core/]. Almost any modern MySQL distribution will work for this QuickStart. |
After installing MySQL, log in with a privileged user (root, for example) and create the database that we'll use to store user submitted data:
CREATE DATABASE IF NOT EXISTS quickstart; |
view plain | print | ? |
This statement simply creates the quickstart database in your MySQL instance if it doesn't exist already.
Now create the table which will store user comments as the same privileged user:
USE quickstart; |
DROP TABLE IF EXISTS `comments`; |
CREATE TABLE `comments` ( |
`comment_id` int(10) unsigned NOT NULL auto_increment, |
`comments` longtext NOT NULL, |
PRIMARY KEY (`comment_id`) |
); |
view plain | print | ? |
We first switch to the quickstart database, so that the comments table will be created within this database. We then create the comments table if it doesn't already exist using the CREATE TABLE statement. The comments table will have 2 fields: a unique comment ID that is automatically generated by MySQL and the comment text itself.
Zend Framework comes with an implementation of the Table Data Gateway and Row Data Gateway patterns. These patterns in combination add a simple, yet powerful object relational mapping (ORM) functionality to ZF.
<?php |
require_once 'Zend/Db/Table/Abstract.php'; |
class CommentsTable extends Zend_Db_Table_Abstract |
{ |
protected $_name = 'comments'; |
protected $_primary = 'comment_id'; |
/** |
* This function returns the form used for |
* adding comments in our comments table |
*/ |
public static function getAddCommentForm() |
{ |
require_once 'Zend/Form.php'; |
$form = new Zend_Form(array( |
'method' => 'post', |
'elements' => array( |
'comments' => array('textarea', array( |
'required' => true, |
'label' => 'Write your comments' |
)), |
'submit' => array('submit', array( |
'label' => 'Send' |
)) |
), |
)); |
return $form; |
} |
/** |
* This function returns all the comments |
* in our comments database table |
*/ |
public static function getComments() |
{ |
$commentsTable = new CommentsTable(); |
return $commentsTable->fetchAll(); |
} |
/** |
* This function creates a new row in our |
* comments database table with the data given |
*/ |
public static function createNewComments($data) |
{ |
$commentsTable = new CommentsTable(); |
$comment = $commentsTable->createRow($data); |
$comment->save(); |
} |
} |
view plain | print | ? |
Congratulations!
You have now built a very simple application using some of the most commonly used Zend Framework components. Zend Framework makes many more components available to you and your applications, including web services, search, PDF reading and writing, authentication, authorization, and much more. You'll find that there are components that address most requirements you are likely to encounter while building a web application. The Reference Guide is a great place to find out more about the components you've used in this QuickStart as well as other Zend Framework components. We hope you find Zend Framework useful and- more importantly- fun!
source link:http://framework.zend.com/wiki/display/ZFDEV/Official+ZF+QuickStart+Draft