mod_rewrite
.
tar.gz
or
zip
download, or you can use the command line:
$wgethttp://framework.zend.com/download/tgz
$tar-xvzfZendFramework-0.1.2.tar.gz
library
directory and place it somewhere convenient. In this tutorial, I rename
library
to
lib
to provide a clean and simple directory structure:
app/
views/
controllers/
www/
.htaccess
index.php
lib/
www
directory is the document root,
controllers
and
views
are empty directories you'll use later, and the
lib
directory is from the preview release download.
Zend_Controller
. In many ways, it provides the foundation of the application you're developing, and it's also part of what makes the Zend Framework more than just a collection of components. Before you can use it, however, you need to direct all incoming requests to a single PHP script. This tutorial uses
mod_rewrite
for this purpose.
mod_rewrite
is an art in itself, but luckily, this particular task is very simple. If you're unfamiliar with
mod_rewrite
or configuring Apache in general, create a
.htaccess
file in the document root and add the following directives:
RewriteEngineon
RewriteRule!\.(js|ico|gif|jpg|png|css)$index.php
Zend_Controller
is to remove the
mod_rewrite
dependency. In order to provide an example that works with the preview release, this tutorial uses
mod_rewrite
.
httpd.conf
directly, you must restart the web server. Otherwise, if you use a
.htaccess
file, you should be good to go. You can quickly test this by placing some identifiable text in
index.php
and making a request for an arbitrary path such as
/foo/bar
. For example, if your host is
example.org
, request the URL http://example.org/foo/bar.
include_path
to include the path to the framework library. You can do this in
php.ini
, or you can just put the following directive in your
.htaccess
file:
php_value include_path "/path/to/lib"
Zend
class contains a collection of static methods that are universally useful. This is the only class you must include manually:
include
'Zend.php'
;
?>
Zend.php
, you have access to all of the methods from the
Zend
class. Loading other classes is simplified with the
loadClass()
method. For example, to load the
Zend_Controller_Front
class:
include
'Zend.php'
;
Zend
::
loadClass
(
'Zend_Controller_Front'
);
?>
loadclass()
method is
include_path
aware, and it also understands the organization and directory structure of the framework. I use it to load all other classes.
Zend_Controller_Front
, a front controller. In order to begin understanding how it works, place the following code in your
index.php
file:
include
'Zend.php'
;
Zend
::
loadClass
(
'Zend_Controller_Front'
);
$controller
=
Zend_Controller_Front
::
getInstance
();
$controller
->
setControllerDirectory
(
'/path/to/controllers'
);
$controller
->
dispatch
();
?>
include
'Zend.php'
;
Zend
::
loadClass
(
'Zend_Controller_Front'
);
$controller
=
Zend_Controller_Front
::
getInstance
()
->
setControllerDirectory
(
'/path/to/controllers'
)
->
dispatch
();
?>
/foo/bar
, you get an error. That's good! It lets you know something is happening. The major complaint is that
IndexController.php
is not found.
/foo/bar
,
foo
is the controller, and
bar
is the action. The default value for each is
index
.
foo
is the controller, the framework looks for a file called
FooController.php
in the
controllers
directory. Because this does not exist, the framework falls back to
IndexController.php
. Not finding either, it reports the error.
IndexController.php
in the
controllers
directory (which you set with
setControllerDirectory()
):
Zend
::
loadClass
(
'Zend_Controller_Action'
);
class
IndexController
extends
Zend_Controller_Action
{
publicfunction
indexAction
()
{
echo
'IndexController::indexAction()'
;
}
}
?>
IndexController
class handles requests for which the controller is
index
or for which the indicated controller does not exist, as just explained. The
indexAction()
method handles requests for which the action is
index
. Remember that
index
is the default value for both the controller and the action. If you try a request for
/
,
/index
, or
/index/index
, the
indexAction()
method is executed. (Trailing slashes do not alter this behavior.) A request for any other resource is going to result in an error.
IndexController
before continuing. The
noRouteAction()
method is called whenever a request is made for a controller that doesn't exist. For example, a request for
/foo/bar
executes
noRouteAction()
if
FooController.php
does not exist. However, a request for
/index/foo
still results in an error, because
foo
is the action, not the controller.
noRouteAction()
to
IndexController.php
:
Zend
::
loadClass
(
'Zend_Controller_Action'
);
class
IndexController
extends
Zend_Controller_Action
{
publicfunction
indexAction
()
{
echo
'IndexController::indexAction()'
;
}
publicfunction
noRouteAction
()
{
$this
->
_redirect
(
'/'
);
}
}
?>
$this->_redirect('/')
to illustrate a possible action to take in
noRouteAction()
. This causes requests for nonexistent controllers to be redirected to the root document (front page).
FooController.php
:
Zend
::
loadClass
(
'Zend_Controller_Action'
);
class
FooController
extends
Zend_Controller_Action
{
publicfunction
indexAction
()
{
echo
'FooController::indexAction()'
;
}
publicfunction
barAction
()
{
echo
'FooController::barAction()'
;
}
}
?>
/foo/bar
, you should see that
barAction()
is being executed, because
bar
is the action. Not only can you already support friendly URLs, but you can also do so in a very organized way with just a few lines of code. Cool!
__call()
method to handle requests for undefined actions such as
/foo/baz
:
Zend
::
loadClass
(
'Zend_Controller_Action'
);
class
FooController
extends
Zend_Controller_Action
{
publicfunction
indexAction
()
{
echo
'FooController::indexAction()'
;
}
publicfunction
barAction
()
{
echo
'FooController::barAction()'
;
}
publicfunction
__call
(
$action
,
$arguments
)
{
echo
'FooController:__call()'
;
}
}
?>
Zend_View
is a class that helps you organize your view logic. It is template-system agnostic, and for the sake of simplicity, I don't use a template system in this tutorial. You're free to use one if you prefer.
Zend_View
, change the code in
IndexController.php
as follows:
Zend
::
loadClass
(
'Zend_Controller_Action'
);
Zend
::
loadClass
(
'Zend_View'
);
class
IndexController
extends
Zend_Controller_Action
{
publicfunction
indexAction
()
{
$view
=new
Zend_View
();
$view
->
setScriptPath
(
'/path/to/views'
);
echo
$view
->
render
(
'example.php'
);
}
publicfunction
noRouteAction
()
{
$this
->
_redirect
(
'/'
);
}
}
?>
example.php
in the
views
directory:
ThisIsanExample
Thisisanexample.
example.php
. This isn't very useful yet, but keep in mind that you're working toward a very structured and organized way to develop web applications.
Zend_View
a bit clearer, modify your template (
example.php
) to include some data:
echo
$this
->
escape
(
$this
->
title
);
?>
echo
$this
->
escape
(
$this
->
body
);
?>
$this->escape()
method must be used on all output. Even if you create the output yourself, which is going to be the case in this example, escaping all output is a very good habit that can help you prevent cross-site scripting (XSS) vulnerabilities by default.
$this->title
and
$this->body
properties exist to demonstrate dynamic data. These should be defined in the controller, so modify
IndexController.php
to assign them:
Zend
::
loadClass
(
'Zend_Controller_Action'
);
Zend
::
loadClass
(
'Zend_View'
);
class
IndexController
extends
Zend_Controller_Action
{
publicfunction
indexAction
()
{
$view
=new
Zend_View
();
$view
->
setScriptPath
(
'/path/to/views'
);
$view
->
title
=
'DynamicTitle'
;
$view
->
body
=
'Thisisadynamicbody.'
;
echo
$view
->
render
(
'example.php'
);
}
publicfunction
noRouteAction
()
{
$this
->
_redirect
(
'/'
);
}
}
?>
$this
in the template is that it is executed within the scope of the
Zend_View
instance.
example.php
is just an ordinary PHP script, so you can do anything you want. Just try to be disciplined enough to limit your use of templates to only what is required to display data. Your controller (or a module to which the controller dispatches) should handle all of your business logic.
Zend_View
before continuing. Instantiating the
$view
object within each method of the controller requires a lot of extra typing, and our primary goal is to make it easier to quickly develop web applications. It's also a hassle to call
setScriptPath()
in each case if all of the templates reside in a single directory.
Zend
class includes a registry that helps you eliminate this overhead. You can store your
$view
object in the registry by using the
register()
method:
Zend
::
register
(
'view'
,
$view
);
?>
registry()
method:
$view
=
Zend
::
registry
(
'view'
);
?>
Zend_InputFilter
. This class provides a simple but rigid approach to input filtering. You instantiate it by passing an array of data to be filtered:
$filterPost
=new
Zend_InputFilter
(
$_POST
);
?>
$_POST
) to
NULL
, so direct access is no longer possible.
Zend_InputFilter
instead provides a small, focused collection of methods that filter data according to specific criteria. For example, if you want the alphabetic characters of
$_POST['name'
], you can use the
getAlpha()
method:
/*$_POST['name']='John123Doe';*/
$filterPost
=new
Zend_InputFilter
(
$_POST
);
/*$_POST=NULL;*/