![]() | Under Construction This QuickStart is currently under construction and community review. You may find the content helpful, but the examples may not work as described. We should have a final draft completed in the next few days. Please leave any feedback as a comment on this document. Thanks, and happy ZF'in! |
Zend Framework QuickStart
Co-authored by Aldemar Bernal & Bradley Holt
Zend Framework is an open source, object oriented, web application framework with a flexible architecture. ZF is often referred to as a 'component library' because it has many loosely coupled components that you can use more or less independently. However, Zend Framework also provides a core model-view-controller (MVC) implementation that you can use to provide basic 'best practices' structure to your web applications. This QuickStart will introduce you to the MVC pattern and Zend Framework's implementation of this pattern, along with the Zend_Controller, Zend_View, Zend_Layout, Zend_Form, and Zend_Db components.
Within minutes, we will have built a very simple blog application with a common page layout using these components. You will find the complete source code for this application in this archive.
MVC and Why You Should Care
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. Let's take a look at what this pattern can do for your applications.
There are a few things the relatively young web development community has figured out over the years:
- Mixing code with the complex markup required for today's pretty applications makes for an ungodly mess.
- Most interface designers aren't very good at modeling backend business logic, and there is little evidence that the average backend developer is any better at creating decent user interfaces.
- All non-trivial applications have a fundamental set of behaviors that define what the application should ultimately do for its users. These behaviors can usually be described independently of what is presented to the user.
For these reasons and many others, separating your code along the lines of separate roles in your organization or application responsibilities is a very good thing. And the model-view-controller pattern can help you do exactly this.
Let's break down the pattern and take a look at the individual pieces:
- Model — This is the part of your application that defines its basic functionality behind a set of abstractions. The data access layer and some business logic is defined in the model.
- View — Views define exactly what is presented to the user. Usually controllers pass data to each view to render in some format. This is where you'll find the html markup in your MVC applications.
- Controller — Controllers bind the whole pattern together. They may manipulate models, decide which view to display based on the user's request and other factors, pass along the data that each view will need, or hand off control to another controller entirely.
Of course there is more to be said about this indispensable pattern, but this should give you enough background to understand the application we'll be building in this QuickStart.
| Use-at-Will MVC Zend Framework provides a very simple- yet powerful- MVC implementation which most ZF developers use in their applications. But, as is the case for all ZF components, our MVC components are use-at-will. You can still take advantage of ZF's database, forms, web services, etc. components without necessarily using its MVC implementation. |
Building an Application
Application Structure on the File System
Let's first create this basic MVC project structure for our application under the directory QuickStart:
Since the public directory will contain all files that are made directly accessible by 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.
| Just for argument's sake. . . We will assume that your web server is running on your local machine and that your public directory is accessible via the web 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 its project file structure is no exception. There is nothing special about this particular project structure except some MVC components will work out of the box with no configuration if you structure your project this way. See the Zend Framework Reference Guide for more information. |
Download and Install Zend Framework 1.5
Download Zend Framework 1.5 and extract the contents of the library folder to your project's library directory. Your library directory should now contain the top-level Zend directory which contains all of the Zend Framework components.
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 appropriately route the request. More about the FrontController and request routing later.
For the Apache web server, create the file QuickStart/public/.htaccess with the following content:
This rewrite rule will dispatch all requests for URLs that do not end in .js, .ico, .gif, .jpg, .png, or .css using index.php. This is because files with these extensions are static resources; requests for URL's that don't end with these extensions will be served dynamic content and must be handled by our PHP scripts. The index.php file therefore serves as the entry point to our application.
| Make sure your web server is configured to read .htaccess files! Some web servers may ignore .htaccess files unless otherwise configured. Make sure that your web server is configured to read the .htaccess file in the QuickStart/public directory. |
| Checkpoint Let's just 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. |
Create Index and Bootstrap Files
Let's take a quick look at that index.php file now. Replace the contents of QuickStart/public/index.php with the following:
The 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 QuickStart/application directory.
| 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. |
Now we need to create our bootstrap.php file, so called because it 'bootstraps' the application on each user request. Create the QuickStart/application/boootstrap.php file with the following contents:
At this point you should start to see your application taking shape. Let's take a look at the steps we take in the bootstrap script one by one:
- Enable all errors so we can see when something goes wrong.
- Add our QuickStart/library/ directory to the include path so the Zend Framework classes are accessible to the PHP runtime.
- Register the autoloader. 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.
- Get the front controller. The Zend_Front_Controller class implements the Singleton pattern, which is just a best practice for ensuring there is only one instance of Zend_Front_Controller created for each request.
- Error handlers allow you to display whatever message you want in whichever format you want if an error is detected in your application. This is very useful in production applications, but for our purposes it is not necessary and will obscure the root cause of the error. Since the error handler is enabled by default, we should disable it.
- Point the front controller to the action controller directory.
- Dispatch the request using the front controller.
The action controllers under the directory mentioned in step 6 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 controller to your action controller, but you don't necessarily need to know the details to write feature-full applications. See the Reference Guide for more information. For now let's move on to creating the action controllers themselves.
| Relative Paths Remember that the QuickStart/public/index.php script 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 the Zend Framework MVC implementation, the default action controller is index and the default action is also index. You should therefore set up the default action controller by creating QuickStart/application/controllers/IndexController.php with the following content:
Because we're using the default request 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 With the default configuration, the action method names should use the lowerCamelCase convention with the suffix 'Action'. Action controller classes, on the other hand, should use the UpperCamelCase convention with the suffix 'Controller'. |
It may seem like indexAction() is doing nothing at all, but again Zend Framework is doing useful things 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 is views/scripts/index/index.phtml, where the views directory is contained in the same folder as the controllers directory you passed to Zend_Controller_Front::run(). The extension for views is yet another best practice recommended for Zend Framework applications; since view templates in ZF are simply PHP files by default, it is easier to distinguish view templates from other PHP files if you use the .phtml extension instead of .php.
| Checkpoint Let's create this view now with the following content: 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 which are very similar to standard PHP, you can easily configure Zend Framework to use other template engines, such as Smarty or PHPTAL. See the reference guide for more information. |
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 process basic HTML forms using Zend_Form. Replace the contents of the IndexController.php file with the following:
Since this form has been built using the Zend_Form component, even the trickiest parts of form handling should be easy to implement. Validation, filtering, rendering, displaying errors, and a lot more form-related functionality are made available by Zend_Form using its simple and intuitive API. By looking through the getCommentForm() method, you should notice that there is a required text area for the comment and a button to submit that comment in the form that is returned. Let's display this form in our index view to see how it appears when it is rendered. Replace the indexAction() method in your IndexController.php file with the following:
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 viewing a page with a blank form- in which case we would expect an HTTP GET request. If the user is submitting data, 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.
Now you must 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 the scripts/index/index.phtml file with the following:
Now your view is checking if there are any values to display and, if so, listing them. Regardless of whether there are values to display or not, the form is rendered near the end of the view. Now, when you go to http://localhost you should see something like this:
<Browser Image Coming Soon>
And if you enter a comment and hit the Send button, you should now see something like this:
<Browser Image Coming Soon>
| Escape user generated data before outputting it! Note that before we output comments to the response, we first escape them like so: $this->escape($value);. If we didn't escape this output, malicious or simply uninformed users could do all kinds of nasty things that might affect the appearance or behavior of this page. In particular, scripts could be invoked that might compromise the security of your application. Always escape data that has been entered or edited by a user before adding it to the response! |
| My sincere apologies. I have not been able to get back to the QuickStart since the 1.5 release. All the things we put off until after the release have been catching up with me. |
Conclusion
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 for you 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 when 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 all of the other Zend Framework components. We hope you find Zend Framework useful and- more importantly- fun!
It's really a balance between simplicity and creating a somewhat realistic example that will actually ramp up newcomers sufficiently so they can start playing around with their own applications. If we over-simplify things to meet the expectation RoR and other projects set, we won't be leaving our newcomers with enough knowledge to do anything. In fact, one could argue that the only reason that RoR and clones have 5-minute time-to-hello-worlds is because they over-simplify web apps on the whole to optimize this relatively insignificant use case (when considered over the entire experience with a application framework). We're already working on tooling that delivers this without the compromises and strict conventions.
I see your point, however. I'll see how we might be able to use the downloadable code to make things simpler. And of course we'll write a separate QuickStart when our CLI tools are available. I've already heard requests to keep the explicit one alongside such a CLI-based QuickStart, however, to underscore our use-at-will architecture- which will include tooling, CLI and otherwise- and foster a deeper understanding of the framework.
I'd be interested in your feedback once we've completed the final version of the QuickStart for 1.5.
I notice you are using regular php tags and then an echo statement in view scripts:
instead of short open tags:
Most (if not all) of the ZF docs I've read so far use short open tags in view scripts. Is this an intentional departure from previous docs?
Not an intentional departure, no. We can use the short tags if you think that almost all users have them enabled and would know what to do if they don't.
I don't really think it's a big deal one way or the other - just noticed it was different than before and I'm sure a lot of people look to the Zend Framework documentation for best practices. I think Matthew had mentioned something on list about adding a stream wrapper for those people who don't have short tags enabled. BTW, the QuickStart looks great!
Here is the link of ZF code standard
http://framework.zend.com/manual/en/coding-standard.coding-style.html
You will see this: "Short tags is NEVER allowed"
However, in the documents, there are some examples did not follow this rule. Maybe they will be revised later.
It is allowed but only in view scripts. Matthew explains it best here: http://www.nabble.com/shouldn't-ZF-promote-not-using-short-tags-td15897713s16154.html
Sorry, here is a better link: http://www.nabble.com/shouldn%27t-ZF-promote-not-using-short-tags-td15897713s16154.html
Here's a corrected version of the last index.phtml file:
<!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($this->values)
<?php echo $this->form; ?>
</body>
There where to endforeach statements..
OK - that didn't work!
<!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($this->values)
<?= $this->form; ?>
</body>
Is what you want.
Solution for form:
1. step
replace second endforeach; with }
2. step
replace all:
<?=
with:
<?php print
Thats it - this worked for me...
Luke
Second step was caused by php.ini settings, where I have set: short_open_tag = Off
Wil, you should put your name as a co-author as well. You put as least as much work into it as I did, if not more!
because the db part is still missing, here is how it worked for me (one should know how to perform each step when trying to use the zf, so no in-depth explaining):
if not yet installed: get the pdo db libs from php.net (NOTICE: they are contained inside the ZIP file, not inside the istaller package!) and add the following lines to your php.ini:
extension=php_pdo.dll
extension=php_pdo_mysql.dll
1) create a database "quickstart" and add the user/pass to it like it is configured in quickstart\application\config\quickstart.ini
2) create the table that holds the data (reverse engineered, real struct may differ):
CREATE TABLE `comments` (
`comment_id` int(10) unsigned NOT NULL auto_increment,
`comments` text NOT NULL,
PRIMARY KEY (`comment_id`)
);
3) that's all. i used phpmyadmin for it
hope that helps.
Several comments here. Let's begin with who your expected audience is. People who come to this page do so via the "Quick Start" link on the homepage, so it's safe to assume that none of them will have any experience with Zend Frameworks. You can probably assume that they have some experience in PHP, some knowledge of OOP, and some experiance in web development, but there's no reason to expect much more than that. Indeed for this Quick Start there is no reason that anyone should need to know any more than that.
The reason I mention all that is because anything that you say that is outside the reader's knowledge base will either be meaningless to them or turn them off the product.
>> Let's first create this basic MVC project structure for our application under the directory QuickStart:
It would probably be helpful to link "MVC" somewhere. Not everyone will be familiar with the term, but it's pretty critical to understanding what's going on. This is part of the "know your audience" rule.
>> Since the public directory will contain all files that are made directly accessible by our web server, you must either create a new directory in your web server which points to your public folder or set your default web server document root to this directory. Please check your web server's documentation on how to do this.
I'm not sure what this means especially the part about creating "a new directory in your web server which points to your public folder". I believe that the only thing the user really has do do here is make sure the QuickStart project is created underneath the DocumentRoot.
_>> For the rest of this QuickStart we will assume that your web server is running on your local machine and that your public directory is accessible via the web at http://localhost._
I would move this to the very beginning and have a link to a page discussing how to install an Apache/PHP/MySQL stack for those who haven't done so.
>> Create a Rewrite Rule
I didn't understand any of this and the "Front Controller" link didn't help. I don't know that I need to understand it other than to know that its purpose is to redirect (dispatch?) .html and .php files to index.php.
>> Create the file QuickStart/public/index.php with the following content: <?php require '../application/bootstrap.php'; The code here deviates from that in the index.php file that was downloaded.
>> Create the QuickStart/application/boootstrap.php file with the following contents:
Well, there's no bootstrap.php in the quickstart.zip file I just downloaded. At this point the QuickStart guide has deviated so far from the downloaded example that there's no point in going on, at least for me.
All good points. I'll read through the existing draft and update it to reflect your feedback. Obviously, this is a work in progress right now. My intention was to finish it very quickly after the 1.5 release, but all those things that we said could wait until 'after the 1.5 drop' have now been coming back to haunt me. I'm very sorry about this and hope you still got something out of the tutorial so far.
There is an error in the Comment example code. In the index.phtml file there is an extra <? endforeach; ?> that should instead be a closing bracket <? } ?>
Other than that, nice guide.
I totally agree to Bill Norton.
I use php for several years now in small to mid-sized projects but I never ever had my hands on ZF.
Since there was so much tamtam about the new ZF, I decided to give it a try and - you might guess it - followed the eye catching and very promising Quickstart link. And landed here.
The Quickstart won some contest. The Quickstart id official. The Quickstart itself is pretty useless. And unmaintained. There should be exactly noone who was able to have a running whatever after going through the Quickstart (which even is not complete for months now - in business months) without at least a little reverse engineering of the DB (remember the no-ZF-experience-thingie).
Nothing is explained (the WHYs and HOWs are missing), the firstmost point (creating a rewrite rule) I "have to do" is even not needed at all.
After all, all this is VERY disappointing. Moreover: A Quickstart should be created by the company (and I think ZEND has the bucks to spend them on such a little thing) that wants a bigger market coverage and not by the community which is the market.
I'm sorry that you find the QuickStart so disappointing. We really intended to address a lot of feedback that we've gotten from the 1.0 release, and I'm sure it would have come off better for the 1.5 release if I had found- or just made- more time to finish the QuickStart. That is entirely my fault, and I'll say it again to you personally: I'm very sorry.
But I don't agree with many of your points. We didn't intend to get in to all the why's and how's. This QuickStart is meant to be gone through in 30 minutes if one really concentrates on it. There are other sources for the full background such as the reference guide; this is meant to get developers building functional applications as quickly as possible.
Second, I'm really happy to hear that you have so much confidence in the business aspect of Zend Technologies, but allow me to give you a little more insight in to how things get done at Zend WRT ZF. We have a dedicated team of 5
developers for Zend Framework. AFAIK , this is no more than most other PHP framework projects. Every one of the Zend developers on the ZF project has at least 100 non-trivial things he sees significant value in having available immediately. From this huge pool of things to do, we as a team pick what we feel are the most important with a lot of input from the community. In fact, it's so hard in some cases to skip over something that we'd really like to see done that most of use work long hours to fit some of our pet projects in on a regular basis.
We have relied- and will continue to rely- very heavily on the contributions of our community, and I believe this is what's best for Zend, ZF, and ZF's users. We typically look at our community more as collaborators instead of a market audience. Our success is determined entirely by the success of our users using the framework, and I think this creates a healthy alignment of interests.
With that perspective, I believe wholeheartedly that our community should be involved with this effort. That's why we ran the contest, and that's precisely why you can comment on this document with feedback. I encourage you to share you viewpoint if you disagree, but I will warn you that trying to convince me that the ZF community should not be involved with a major initiative will be an uphill battle. ![]()
Hear Hear!!! (totally agree with Bill Norton)
I came up with an error page:
Fatal error: Uncaught exception 'Zend_Controller_Dispatcher_Exception' with message 'Invalid controller specified (error)' in ...
I was excited to get started but this must not be the start point where Zend Framework homepage suggests. I wish you didn't publish an unfinished work or at least published a working part of it.
I'm looking forward to the complete article.
ZF Home Page
Issue Tracker
SVN Browser
Wiki Dashboard
Only just looked it over, but would like to suggest the hoops to jump through be reduced right down to:
1. download it
2. unpack it
3. run it
Setting up a web server config and also DB per demo seems like overkill to me these days.
I believe all you really need to do is make any links in the demo to be document root aware such that it works from its own subdirectory and at any path depth under document root allowing other demos to share the document root however the user wishes them organised.
The other point is that an instant DB based demo would need to be bundled with an SQLite DB file by default, perhaps with the option of following additional steps to configure own choice DBs where "pear install sqlite" is somehow not an option/desired.
Other project demos work out of the box like this (eg. Xajax) and I think it's kind of becoming expected. I Hope ZF demos go that way too for maximum ease of use.
Anyway, great start to see this. I'm sure ZF newbies to 1.5 will be grateful. I know I would have been!