Archive for the ‘Frameworks’ Category
Increase speed and reduce bandwidth usage with ZF and Apache
Apache’s mod_deflate module provides the DEFLATE output filter that allows output from your server to be compressed before being sent to the client over the network.
There are two ways of enabling gzip compression:
- Using Apache’s mod_deflate
- Using PHP’s built-in functions
Encoding the output and setting the appropriate headers manually makes the code more portable. Keep in mind that there are hundreds of Linux distributions, each slightly different to significantly different. To allow portability the application should not make assumptions about the OS or config involved.
Using Apache
1. Enable mod_deflate
Debian/Ubuntu:
$ a2enmod deflate $ /etc/init.d/apache2 force-reload
2. Configure mode_deflate
$ nano /etc/apache2/mods-enabled/deflate.conf # # mod_deflate configuration # <IfModule mod_deflate.c> AddOutputFilterByType DEFLATE text/plain AddOutputFilterByType DEFLATE text/html AddOutputFilterByType DEFLATE text/xml AddOutputFilterByType DEFLATE text/css AddOutputFilterByType DEFLATE application/xml AddOutputFilterByType DEFLATE application/xhtml+xml AddOutputFilterByType DEFLATE application/rss+xml AddOutputFilterByType DEFLATE application/javascript AddOutputFilterByType DEFLATE application/x-javascript DeflateCompressionLevel 9 BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4\.0[678] no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html DeflateFilterNote Input instream DeflateFilterNote Output outstream DeflateFilterNote Ratio ratio </IfModule>
Using PHP
Create a gzip compressed string in your bootstrap file:
try {
$frontController = Zend_Controller_Front::getInstance();
if (@strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) {
ob_start();
$frontController->dispatch();
$output = gzencode(ob_get_contents(), 9);
ob_end_clean();
header('Content-Encoding: gzip');
echo $output;
} else {
$frontController->dispatch();
}
} catch (Exeption $e) {
if (Zend_Registry::isRegistered('Zend_Log')) {
Zend_Registry::get('Zend_Log')->err($e->getMessage());
}
$message = $e->getMessage() . "\n\n" . $e->getTraceAsString();
/* trigger event */
}
Reference
Is this the best open source CMS ever created?
Meet TYPOlight, a powerful Web content management system that specializes in accessibility (back end and front end) and uses XHTML and CSS to generate W3C/WAI compliant pages.
Accessibility
A growing number of countries around the world have introduced legislation which either directly addresses the need for websites to be accessible to people with disabilities, or which addresses the more general requirement for people with disabilities not to be discriminated against. TYPOlight does not treat accessibility as just an additional feature and is thoroughly accessible.
Web 2.0
PHP 5 and Ajax are modern “Web 2.0″ technologies that you can find in a lot of contemporary applications. TYPOlight has a solid codebase built on the new object-oriented programming features of PHP 5 and can therefore be considered a future-proof software. To ensure back end accessibility, every Ajax feature includes a graceful fallback in case JavaScript is disabled.
Page features
- Different page types
- Multiple websites in one tree
- Manual or timed publication
- Hidden pages
- Password protect pages
Editing features
- Clipboard feature
- Edit multiple records
- Built-in rich text editor (TinyMCE)
- Different content elements and modules
- Multilingual spellchecker
- Insert tags (similar to server side includes)
- Manual or timed publication
File manager
- Multiple file uploads
- Image thumbnails and file preview
- Edit uploaded files with the source editor
- File operation permissions
- Copy, move, rename files or folders
- Delete folders recursively
Form generator
- Automatic input validation
- Store uploaded files on the server
- Send form data via e-mail
- Send uploaded files as e-mail attachment
Search engine
- Automatic page indexing
- Search indexing on protected pages
- Phrase search, wildcard search, AND/OR search
- Search result caching and pagination
Full feature list
- Intuitive user interface
- Accessible XHTML strict output
- Meets W3C/WAI requirements
- Web 2.0 support (mootools-based)
- Live update service
- Accessible administration area
- Multiple back end languages and themes
- Generates search engine friendly URLs
- Multi-language support
- Powerful permission system
- Versioning and undo management
- Advanced search and sorting options
- Front end output 100% template based
- Automatic e-mail encryption (spam protection)
- Supports SMTP in addition to PHP’s mail function
- Supports multiple websites in one tree
- Supports GZip compression
- Print articles as PDF
System features
- Open Source (LGPL)
- Web-based administration
- Platform independent
- Over 150 third party extensions
- Multilingual documentation
Links
New Zend Framework Book Published
This book shows you how to build websites fast using PHP and MySQL. What’s more, it shows you how to supercharge your use of these technologies by taking advantage of a powerful, free web development solution known as the Zend Framework, which helps developers build websites with speed and efficiency.
This book embraces a teaching strategy of learning by doing, showing you how to build website features you’ll actually want to use within your own websites. Among other things you’ll learn how to manage data submitted through web forms, send unformatted and HTML e-mails through your website, manage user registrations, logins, and recover forgotten passwords, and even create the structure for a simple social network.
Along the way, you’ll learn how to take advantage of popular online services such as Google Maps, Amazon Web Services, the Facebook Platform, and PayPal to create even more compelling websites.
An Alternative to Zend_Controller: The Model
Part 1 – An Alternative to Zend_Controller: Introduction
Part 2 – An Alternative to Zend_Controller: The Router
Domain Layer
The domain layer is separated from the other layers and has no dependencies on Zf_Controller.
app/
domain/
Model/
User.php
UserDao.php
lib/
Zend/
Zf/
Adding the domain directory to your include path allows you to load and access Model classes from anywhere within your project:
Bootstrap file
set_include_path(APPLICATION_PATH . '/../lib'
. PATH_SEPARATOR . APPLICATION_PATH . '/../domain);
Index Controller
class IndexController extends Zf_Controller_Action
{
public function indexAction()
{
// DAO pattern
$dao = new Model_UserDao();
...
}
}
The getInstance() method can be used to set or retrieve a singleton instance of a Model class:
class IndexController extends Zf_Controller_Action
{
public function indexAction()
{
$dao = $this->getInstance('Model_UserDao');
// or...
$dao = new Model_UserDao();
$this->setInstance($dao);
$this->userAction();
}
public function userAction()
{
$dao = $this->getInstance('Model_UserDao');
...
}
}
Below is an example of the UserDao class that contains methods to insert, update, and retrieve data:
class Model_UserDao extends Zf_Persistence_Db_Adapter
{
public function find($id)
{
$db = $this->getAdapter();
...
}
}
abstract class Zf_Persistence_Db_Adapter
{
protected $_db = null;
public function setAdapter(Zend_Db_Adapter_Abstract $db)
{
$this->_db = $db;
}
public function getAdapter()
{
if (null === $this->_db) {
if (!Zend_Registry::isRegistered('Zend_Db')) {
throw new Zf_Persistence_Exception('...');
}
$this->setAdapter(Zend_Registry::get('Zend_Db'));
}
return $this->_db;
}
}
More Info
An Alternative to Zend_Controller: The Router
Part 1 – An Alternative to Zend_Controller: Introduction
Here’s the good news: Zf_Controller doesn’t have a Router. It uses a very simple mapping to determine the name of the controller and action. Optionally, you may define parameters in the URI, for example:
http://domain.com/controller/action/value1/value2
An example of how routes are matched:
URI: http://domain.com/news/tag/zend-framework
Controller
class NewsController extends Zf_Controller_Action
{
public function tagAction()
{
print_r($this->_getAllParams());
}
}
Outputs
Array
(
[controller] => News
[action] => tag
)
Variable Defaults
It is often helpful to be able to assign default values to parameters that aren’t passed, that way we don’t have to check if the parameter has been set or not. The $_params property is an array with keys representing variable names and default values.
URI: http://domain.com/news/tag/zend-framework
Controller
class NewsController extends Zf_Controller_Action
{
protected $_params = array(
'name' => null,
'show' => 10
);
...
}
Outputs
Array
(
[controller] => News
[action] => tag
[name] => zend-framework
[show] => 10
)
A parameter sent via the URI will always overwrite a default parameter. That’s the whole point of using default values.
Variable Requirements
The $_paramsMatch property is used to set variable requirements. These are defined as parts of a regular expression:
URI: http://domain.com/news/tag/zend-framework/50
Controller
class NewsController extends Zf_Controller_Action
{
protected $_params = array(
'name' => null,
'show' => 10
);
protected $_paramsMatch = array('show' => '\d+');
...
}
In the example above, Zf_Controller will assign the value to the “show” variable only if the value is a number. If not, it will assign the default value, in this case “10″.
If you think that you need more flexibility than this, I suggest extending Zend_Controller_Action instead.
An Alternative to Zend_Controller: Introduction
Zend Framework is very flexible and one of its strengths is that it allows developers to implement their own components. The Zend_Controller component, for example, is very powerful. Of course, it’s not my intention to replace it, but to offer an alternative that decreases the number of decisions a developer needs to make when developing an application.
Meet Zf_Controller. The Zf_Controller component has the following goals:
- Abstract complexity: Try to reduce the level of details so the developer can focus on a few concepts at a time.
- Emphasize Convention over Configuration: Emphasize CoC, meaning that the user only needs to specify unconventional aspects of the application.
- Maintain backwards compatibility: Allow the developer to replace Zf_Controller with Zend_Controller in case the application grows in size or complexity.
- Improve performance: Load less classes, execute less code.
- Remove circular references: Avoid circular references.
- Remove Singleton classes: Avoid implementing the Singleton pattern.
- Research: Learn more about the framework, what it does, how it works.
Project Structure
Zend_Controller allows you to use the project structure that best suits your needs. On the other hand, Zf_Controller is more rigid, it only allows you to use the standard project structure:
project/
app/
config/
controllers/
ErrorController.php
IndexController.php
views/
layouts/
scripts/
error/
index/
index.phtml
domain/
Model/
Example.php
lib/
Zend/
Zf/
Zf_Controller classes:
Zf/
Controller/
Action/
Helper/
Layout.php
Action.php
Front.php
Bootstrap File
Zend_Controller:
define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../app'));
set_include_path(APPLICATION_PATH . '/../lib'
. PATH_SEPARATOR . get_include_path());
require_once "Zend/Loader.php";
Zend_Loader::registerAutoload();
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$routes = include_once APPLICATION_PATH . '/config/routes.php';
$router->addRoutes($routes);
$layout = Zend_Layout::startMvc();
$layout->setLayoutPath(APPLICATION_PATH . '/views/layouts');
$frontController->dispatch();
Zf_Controller (no Router):
define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../app'));
set_include_path(APPLICATION_PATH . '/../lib'
. PATH_SEPARATOR . APPLICATION_PATH . '/../domain);
require_once "Zend/Loader.php";
Zend_Loader::registerAutoload();
$frontController = new Zf_Controller_Front();
$frontController->setLayoutPath(APPLICATION_PATH . '/views/layouts');
$frontController->dispatch();
Action Controller
The default action controller and the default action are named “index”:
class IndexController extends Zf_Controller_Action
{
public function indexAction()
{}
}
Error Controller
Zend_Controller:
class ErrorController extends Zend_Controller_Action
{
// Action used by Zend_Controller
public function errorAction()
{
$error = $this->_getParam('error_handler');
echo $error->exception->getMessage();
}
}
Zf_Controller:
class ErrorController extends Zf_Controller_Action
{
// Action used by Zf_Controller
public function indexAction($e)
{
echo $e->getMessage();
}
}
Rendering a View Script
Zf_Controller does not use the ViewRenderer helper class. To make the code more readable and testable, you need to call the render() method and return a value:
class IndexController extends Zf_Controller_Action
{
public function indexAction()
{
$view = $this->initView();
$view->message = 'Hello';
// Renders views/scripts/index/index.phtml
return $this->render();
}
public function testAction()
{
$view = $this->initView();
$view->message = 'Goodbye';
// Renders views/scripts/index/index.phtml
return $this->render('index');
}}
index.phtml file:
<p><?php echo $this->message ?></p>
Using a Layout
By setting the path to your layouts in the Bootstrap file, you automatically enable the default layout “layout.phtml”:
$frontController = new Zf_Controller_Front(); $frontController->setLayoutPath(APPLICATION_PATH . '/views/layouts');
To disable the layout:
class IndexController extends Zf_Controller_Action
{
protected $_isLayoutEnabled = false;
}
To use a different layout:
class IndexController extends Zf_Controller_Action
{
protected $_layoutScript = 'main.phtml';
}
main.phtml file:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <?php echo $this->headTitle() ?> <?php echo $this->headScript() ?> <?php echo $this->headStyle() ?> </head> <body> <div id="content"><?php echo $this->layout()->content ?></div> </body> </html>
Implementing your own Front Controller in Zend Framework
There’s no doubt that the additional complexity of implementing the default Front Controller in ZF results in a number of benefits. The most important ones are flexibility and extensibility. The Front Controller implementation takes into consideration the future growth of your application and its design reduces the level of effort required to extend it. A good example of this is the plugin architecture.
But, what if after evaluating the requirements of your system, you determine that there’s not sufficient complexity to implement the default Front Controller? What if you don’t need all that flexibility, a URL mapper, a ViewRendered plugin or an ActionStack helper. Maybe all you need is just a couple of controllers, and that’s it. It’s clear that the standard Front Controller does provide more options and meets every possible use case requirement, but at the cost of complexity and a lot of classes.
So, what to do? Do you choose a different tool for the job, or replace the default Front Controller with your own implementation? How hard can it be? Is it really that difficult to replace the most important component of the Zend Framework and maintain backwards compatibility?
You are about to find out.
In this series of posts, I’ll try to cover a few things I’ve learned about implementing my own Front Controller in Zend Framework. Most of the ideas and code are based on my previous posts:
- Zend Framework: The Cost of Flexibility is Complexity
- Zend Framework Automatic Dependency Tracking
- Zend Framework Controller: 22% Drop in Responsiveness
- Refactoring the Front Controller of the Zend Framework
- Improving the performance of Zend_Controller
- Zend Framework Architecture
Will simplicity finally meet power?
Zend Framework Debug Bar
The Scienta ZF Debug Bar is a plugin for the Zend Framework. It provides useful debug information displayed in a small bar at the bottom of every page. Time spent, memory usage and number of database queries are presented at a glance. Additionally, included files, a listing of available view variables and the complete SQL command of all queries are shown in separate panels.
Great plugin Joakim. Thanks for sharing!
Omeka: A Web-based Publishing System

The Center for History and New Media has released an open source version of their Web-based publishing system built on top of the Zend Framework.
Omeka is a Web-based publishing platform for scholars, librarians, archivists, museum professionals, educators, and cultural enthusiasts. Its “five-minute setup” makes launching an online exhibition as easy as launching a blog. Omeka is designed with non-IT specialists in mind, allowing users to focus on content and interpretation rather than programming. It brings Web 2.0 technologies and approaches to academic and cultural websites to foster user interaction and participation. It makes top-shelf design easy with a simple and flexible templating system. Its robust open-source developer and user communities underwrite Omeka’s stability and sustainability.
Thank you guys for open sourcing this great application!
Links
- Website
- Documentation
- Demo (demo/sandbox)
- Source Code
Domain-Driven Design with Zend Framework
Part 1: Domain-Driven Design and MVC Architectures
Part 2: Domain-Driven Design: Data Access Strategies
Part 3: Domain-Driven Design: The Repository
Some of the Domain-driven design concepts explained in my previous posts are applied in this sample application. I’m also going to use the Zend Framework infrastructure to speed up some development tasks.
Directory Structure
app/ -> Application and UI Layers domain/ -> Domain Layer lib/ -> Infrastructure Layer
Application and UI Layers
app/
controllers/
UserController.php
views/
layouts/
scripts/
Domain Layer
This layer should be well separated from the other layers and it should have few dependencies on the framework(s) you are using. I’m going to group all the classes and interfaces under the namespace “Project” and add it to my include path:
domain/
Project/
Dao/
Db/
IUser.php
IUserProfile.php
User.php
UserProfile.php
Model/
User/
IRepository.php
Repository.php
User.php
UserProfile.php
Users.php
Infrastructure Layer
This layer acts as a supporting library for all the other layers:
lib/
Zend/
...
Zf/
Persistence/
Db/
Adapter.php
Exception.php
Replicated.php
Domain/
Collection.php
Entity.php
Exception.php
Repository.php
User Entity
The User and UserProfile objects have a one-to-one relationship and form an Aggregate. An Aggregate is as a collection of related objects that have references between each other. Within an Aggregate there’s always an Aggregate Root (parent Entity), in this case User:
class Project_Model_User extends Zf_Domain_Entity
{
/* SELECT id, name FROM user WHERE id = ? */
private $properties = array(
'id' => null,
'name' => null
);
/* @var Project_Model_UserProfile */
private $profile;
public function __construct($array)
{
$this->populate($array);
}
}
abstract class Zf_Domain_Entity
{
private $properties = array();
public function __call($method, $args) {}
public function __set($key, $value) {}
public function __get($key) {}
public function __isset($key) {}
public function __unset($key) {}
public function populate($values) {}
public function hasDependency($property) {}
public function setDependency($property, $object) {}
public function getDependency($property) {}
}
Usage:
$array = array('id'=>1, 'name'=>'Federico');
$user = new Project_Model_User($array);
$user->setProfile($profile);
echo $user->getId(); // Outputs 1
echo $user->getName(); // Outputs Federico
Users Collection
A collection is simply an object that groups multiple elements into a single unit.
class Project_Model_Users extends Zf_Domain_Collection
{
public function __construct($users)
{
foreach ($users as $user) {
if (!($user instanceof Project_Model_User)) {
throw new Zf_Domain_Exception(...);
}
$this->append($user);
}
}
}
abstract class Zf_Domain_Collection implements Countable, Iterator
{
...
}
User DAO
The UserDAO class allows data access mechanisms to change independently of the code that uses the data:
class Project_Dao_Db_User extends Zf_Persistence_Db_Adapter
{
public function find($id)
{
$db = $this->getAdapter();
$query = $db->select();
$query->from('user');
$query->where('id = ?', $id);
$result = $db->fetchRow($query);
return $result;
}
public function findAll()
{
...
return $resultSet;
}
}
User Repository
A Repository is basically a collection of Aggregate Roots. Collections are used to store, retrieve and manipulate Entities and Value objects, however, object management is beyond the scope of this post.
The UserRepository object injects dependencies on demand, making the instantiation process inexpensive. A caller method is responsible for dynamically creating the setter and getter methods. You can easily mock objects by passing a custom config array via the constructor.
class Project_Model_User_Repository extends Zf_Domain_Repository
{
/* @var Project_Dao_Db_User */
private $userDao;
/* @var Project_Dao_Db_UserProfile */
private $userProfileDao;
/* @var array IoC Spec */
private $inject = array(
'userDao' => 'Project_Dao_Db_User',
'userProfileDao' => 'Project_Dao_Db_UserProfile'
);
public function getUserById($id)
{
$row = $this->getUserDao()->find($id);
$user = new Project_Model_User($row);
$row = $this->getUserProfileDao()->findByUserId($id);
$profile = new Project_Model_Profile($row);
$user->setProfile($profile);
return $user;
}
public function getUsers()
{
$users = array();
$rows = $this->getUserDao()->findAll();
foreach ($rows as $row) {
$users[] = new Project_Model_User($row);
}
return new Project_Model_Users($users);
}
}
abstract class Zf_Domain_Repository
{
...
public function __call($method, $arguments)
{
$property = lcfirst(substr($method, 3));
if (!property_exists($property)) {
throw new Zf_Domain_Exception(...);
}
if (null === $this->$property
&& array_key_exists($property, $this->inject)) {
$this->$property = new $this->inject[$property];
}
return $this->$property;
}
...
}
Usage:
$repo = new Project_Model_User_Repository(); $user = $repo->getUserById(1); $profile = $user->getProfile(); $users = $repo->getUsers();
Links
If you’re interested in learning more about Domain-driven design, I recommend the following articles: