Zend_Controller is the heart of Zend Framework’s MVC system. To understand why and how Zend_Controller works you need to have a basic knowledge of MVC. But you’ll get more in-depth idea of MVC by starting to write codes anyway.
So, let’s start by creating file system layout. Here’s my simple layout:
application/
controllers/
IndexController.php
FooController.php
views/
scripts/
index/
index.phtml
foo/
bar.phtml
library/
Zend/
.htaccess
index.php
To work with Zend_Controller you need to create a rewrite roules in .htaccess
file,
RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php
I’m assuming that we use Apache mod_rewrite here, you might want to look other configuration for different web server here.
index.php
is our bootstrap file where all requests are routed through. It controls all the workflows. Open up your editor and write this code,
<?php
if ( ! defined( "PATH_SEPARATOR" ) ) {
if ( strpos( $_ENV[ "OS" ], "Win" ) !== false )
define( "PATH_SEPARATOR", ";" );
else
define( "PATH_SEPARATOR", ":" );
}
set_include_path(get_include_path() . PATH_SEPARATOR . "library");
require_once 'Zend/Controller/Front.php';
Zend_Controller_Front::run('application/controllers');
Zend_Controller_Front::run
is a shortcut to tell the controller to search controller files in application/controllers
directory for each request and dispatch it.
By default, the first segment of a URL path maps to a controller, and the second to an action. For example, given the URL http://www.example.com/foo/bar
, the path is /foo/bar
, which will map to the controller foo
and the action bar
. If no action is provided, the action index
is assumed, and if no controller is provided, the controller index
is assumed (following the Apache convention that maps a DirectoryIndex automatically).
So, http://www.example.com/foo
will map to the controller foo
and the action index
. While http://www.example.com
will map to the controller index
and the action index
.
By default, the controller files reside on the directory which we declared in Zend_Controller_Front::run
method. The file name use the the controller name with uppercase on the first letter added with Controller
words. For example, URL http://www.example.com/foo
will search FooController.php
in application/controllers
directory. While http://www.example.com
will search IndexController.php
.
The next step is to write the action controller, the actual code for handling the request. First, let’s open up application/controllers/IndexController.php
and enter the following,
<?php
require_once 'Zend/Controller/Action.php';
class IndexController extends Zend_Controller_Action
{
public function indexAction()
{
}
}
As you might suspect, indexAction
method is the action controller, where executed for index action, i.e where the URL is http://www.example.com
Similarly, you can handle URL http://www.example.com/foo/bar
by writing this code into application/controllers/FooController.php
,
<?php
require_once 'Zend/Controller/Action.php';
class FooController extends Zend_Controller_Action
{
public function barAction()
{
}
}
Now, if you access http://www.example.com/foo/bar
you’ll get,
Fatal error: Uncaught exception 'Zend_Controller_Dispatcher_Exception' with message 'Invalid controller specified (error)' in ...
Good, don’t worry about the error. It tells you that you’re missing something. But before we get to that, it is a good practice to write a controller to handle such errors. By default, Zend_Controller will execute errorAction()
method in ErrorController.php
when it can’t find the appropriate controller files or when something is wrong. So open up application/controllers/ErrorController.php
and write the following,
<?php
require_once 'Zend/Controller/Action.php';
class ErrorController extends Zend_Controller_Action
{
public function errorAction()
{
die("An error occurred; please try again later.");
}
}
Now, if you access URL like this http://www.example.com/none/nothing
, you’ll get,
An error occurred; please try again later.
No, you can’t treat this as 404 Not Found like. Because it’s executed not only when the controller can not be found, but also when there’s something missing in your codes. For example when you forget the view parts.
Right, by default ViewRenderer action helper is enabled. What this means is that by simply defining an action method and a corresponding view script, you will immediately get content rendered. By default, Zend_View is used as the View layer in the MVC. The ViewRenderer does some magic, and uses the controller name (e.g., foo
) and the current action name (e.g., bar
) to determine what template to pull. By default, templates end in the .phtml extension, so this means that, http://www.example.com/foo/bar
will render the template in views/scripts/foo/bar.phtml
.
So, let’s open up views/scripts/foo/bar.phtml
file and write the following templates,
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>My first Zend Framework App</title>
</head>
<body>
<p>You say foo bar!</p>
</body>
</html>
And now you can view your site http://www.example.com/foo/bar
, yes it says
You say foo bar!
Great!
That’s it. Now you have the basic concept of how Zend_Controller works. As you might notice, i say “by default” many times, this is because you can change the way it works according to your needs. All by extending the abstract and interface class. We’ll talk more about this on later post.