Sorry for the language change but at the moment it's just way more convenient for me ![]()
Since Tobi blogged about the Zend Framework some time ago, I was tempted to try it for myself again and I'm really impressed by the improvements between versions 0.9.x/1.0 and 1.6 (Download). The whole framework has become easier to handle and better structured despite offering a huge number of components.
I lately became a very big fan of object relational mapper frameworks because it fits pretty much every task I had to face by now and allowed me to avoid writing SQL statements and repeatedly mapping it objects (damn, I'm a lazy programmer ;). Therefore I was a little dissapointed to discover that the Zend_Db component is not an ORM layer in my understanding of this technology.
Fortunately I followed the development of a very powerful ORM for PHP named Doctrine which became stable not a long time ago.
There are many articles on how to include Doctrine as your model in the Zend Framework (ZF) but due to the rapid development of both frameworks most of them are already outdated (and I guess that this article will suffer the same fate pretty soon, too, even though both frameworks are very mature in my opinion).
I decided to write a tutorial on how to connect Doctrine and ZF by adapting the original quick start tutorial and - as I like it to do with my blog tutorials - splitting it up in multiple parts. The first part will be about the installation, putting both frameworks together and performing the basic steps. The next part will deal with the GuestBook demo from the ZF tutorial.
1. Creating folder structure and download libraries
Since ZF is configurable in any way I decided to use a very clear and simple folder structure as shown in the picture below:

The public folder should usually be the only publicly accessible folder for the Webserver.
Now download the full Zend Framework latest release (1.6.2 at this time, registration required) and copy the contents of the library folder in the archive in the libraries folder of our webapplication.
Download the Doctrine library (currently 1.0.3) and copy the contents of the lib folder in the archive to the webapplication libraries folder as well.
2. Creating an index.php and bootstrap.php file
Create the index.php file in the public folder with the following content:
-
<?php
-
-
// APPLICATION_PATH is a constant pointing to our application/ subdirectory.
-
-
// DOCTRINE initializing
-
require_once "Doctrine.php";
-
// DOCTRINE autoloader
-
// ZEND initializing
-
require_once "Zend/Loader.php";
-
// ZEND autoloader
-
Zend_Loader::registerAutoload();
-
-
-
// REQUIRE APPLICATION BOOTSTRAP: Perform application-specific setup
-
try
-
{
-
require APPLICATION_PATH . '/bootstrap.php';
-
}
-
catch (Exception $exception)
-
{
-
echo '<html><body><center>'
-
. 'An exception occured while bootstrapping the application.';
-
{
-
. '<div align="left">Stack Trace:'
-
. '<pre>' . $exception->getTraceAsString() . '</pre></div>';
-
}
-
echo '</center></body></html>';
-
}
-
-
-
// DISPATCH: Dispatch the request using the front controller.
-
Zend_Controller_Front::getInstance()->dispatch();
This is basically the standard index.php file of the ZF MVC components except for the two lines of Doctrine file inclusion and auto loader registration (which belongs in here imho).
Now it's time to create the boostrap.php file in the application directory:
-
<?php
-
-
// APPLICATION CONSTANTS - Set the constants to use in this application.
-
-
function __bootstrap()
-
{
-
// FRONT CONTROLLER - Get the front controller.
-
$frontController = Zend_Controller_Front::getInstance();
-
// CONTROLLER DIRECTORY SETUP - Point the front controller to controller directory
-
$frontController->setControllerDirectory(APPLICATION_PATH . '/controllers');
-
// APPLICATION ENVIRONMENT - Set the current environment
-
$frontController->setParam('env', APPLICATION_ENVIRONMENT);
-
-
// LAYOUT SETUP - Setup the layout component
-
Zend_Layout::startMvc(APPLICATION_PATH . '/views/layouts');
-
// VIEW SETUP - Initialize properties of the view object
-
$view = Zend_Layout::getMvcInstance()->getView();
-
$view->doctype('XHTML1_STRICT');
-
$view->setScriptPath(APPLICATION_PATH . '/views');
-
-
// CONFIGURATION - Setup the configuration object
-
$configuration = new Zend_Config_Xml(APPLICATION_PATH . '/configuration.xml', APPLICATION_ENVIRONMENT);
-
-
// Bootstrap doctrine
-
Doctrine_Manager::connection($configuration->database);
-
Doctrine_Manager::getInstance()->setAttribute('model_loading', 'conservative');
-
Doctrine::loadModels(APPLICATION_PATH . '/models');
-
-
// REGISTRY - setup the application registry
-
$registry = Zend_Registry::getInstance();
-
$registry->configuration = $configuration;
-
}
-
-
__bootstrap();
I use the __bootstrap() function so that you don't have to manually unregister all variables (by putting all bootstrapping in the function all variables are scoped locally, anyway.
The beginning of this function is the standard Zend MVC initialization with the paths from the folder structure I introduced.
ZF introduced configuration files which are a perfect place to store the Doctrine connection string. Personally I prefer the XML adapter which I'm using here and requires the configuration.xml file in the application directory with the following minimal content:
-
<?xml version="1.0" encoding="utf-8"?>
-
<configdata>
-
<development>
-
<database>mysql://root:@localhost/zendtests</database>
-
</development>
-
</configdata>
Using this information Doctrine will be bootstrapped using the conservative model loading and the models path.
3. Creating layout and index controller and layout
In the end of this part of the tutorial we will create the needed index controller and view and the layout.
I won't spend much time on this part (no error pages, no CSS) since it is already part of the Zend framework tutorial and the main focus is on including doctrine.
application/controller/IndexController.php
-
<?php
-
-
/**
-
* IndexController is the default controller for this application
-
*
-
* Notice that we do not have to require 'Zend/Controller/Action.php', this
-
* is because our application is using "autoloading" in the bootstrap.
-
*
-
* @see http://framework.zend.com/manual/en/zend.loader.html#zend.loader.load.autoload
-
*/
-
class IndexController extends Zend_Controller_Action
-
{
-
/**
-
* The "index" action is the default action for all controllers -- the
-
* landing page of the site.
-
*
-
* Assuming the default route and default router, this action is dispatched
-
* via the following urls:
-
* /
-
* /index/
-
* /index/index
-
*
-
* @return void
-
*/
-
public function indexAction()
-
{
-
// $user = Doctrine::getTable('User')->find(1);
-
// print_r($user->toArray(true));
-
}
-
}
application/views/index/index.phtml
-
<h1>Index controller</h1>
-
This is the index controller action
application/views/layouts/layout.phtml
-
<?= $this->doctype() ?>
-
<html xmlns="http://www.w3.org/1999/xhtml">
-
<head>
-
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-
<title>Zend Framework + Doctrine Demo</title>
-
</head>
-
<body>
-
<div style="width: 80%; border: 1px solid #505050; padding: 20px;">
-
<?= $this->layout()->content ?>
-
</div>
-
</body>
-
</html>
The final folder structure for this part should now look like this:
Aktualisiert am 17. November 2008


















Hi Daff,
It's a long time since I've heard from you on JS M V C.
I've migrated over to reimplementing its main concepts (as far as I understand and care for) into jQuery.
If you like, visit my test application
http://peter.chan.free.fr/cms
It runs on PHP on a free (== often overloaded) server, and yet it's fast!
That's "competitive" !
Hi Peter.
Yeah I know... was a little busy studying in Canada and stuff
Your Demo page looks great and runs really smooth.
But why did you decide to run it only on jQuery?
I found that JSMVC and jQuery are working fine together...
Hi Daff,
doctrine hört sich echt interessant an. Hab mal das Manual überflogen und was da so zu lesen ist scheint qualitativ echt hochwertig. Wo siehst du denn die Unterschiede zu Zend_Db_Table und ziehst doctrine diesem vor?
Vielen Dank jeden Fall für den Tipp!
Viele Grüße
Tobi
Hi Tobi.
Also ich habe mich tatsächlich noch nicht so umfassend mit dem DB_Table befasst, weil die ersten Beispiel meiner Meinung nach noch zu stark an die Datenbank gebunden sind und das API in diesem Fall durch das Komponentensystem etwas unstrukturiert wirkt.
Doctrine fühlt sich für mich irgendwie natürlicher an und eine Objektorientierte Abfragesprache hatte ich auch schon mal mit Hibernate ausgetestet. Ich denke es ist einfach eine Philosophie Sache. Bin halt mehr Programmierer im Kopf als SQL statement Zusammenwurschtler (da habe ich manchmal Knoten im Hirn).
Habe hier bei den ganzen Microsoft Jüngern und Legacy Systems Programmierern übrigens einen schweren Stand mit der Idee, den Objektpersistenzkram einem eigenen Framework zu überlassen.
ASP.NET übernimmt lauter unnötige Sachen für die Webprogrammierung, so das es mir manchmal scheint als ob viele Programmierer gar keine Ahnung haben was da überhaupt passiert, aber deine Business Objekte müssen im Grunde jedes Mal per Hand zu den Spalten einer Query gemappt werden (jeder der sich nun fragt warum ich hier einen ASP.NET Kurs belege: in die Richtung gibts einfach nix anderes ;).