Computer programming in PHP for business and passion
In: Joomla| PHP| Zend Server
11 Jun 2010Zend Server CE is the Community Edition of the PHP application server by Zend Technologies. It’s a free environment that can be used to run PHP applications using additional features compared to the PHP.net version. Some of these features are:
Using the Zend Optimizer+ we can speed up the execution of a PHP application without any change on the code. Basically the Optimizer+ is a caching system for the bytecode generated from the PHP interpreter.
The Zend Data Cache is a caching system for PHP and can be used to cache variables, objects, etc. This means that you have to modify your code to use this cache. However, the change of the PHP code is very simple and limited. For more info about the Zend Data Cache we suggest to read the White Paper “A pratical guide to data caching with Zend Server” of Shahar Evron, Product Manager of Zend Technologies.
Basically using Zend Server CE we can speed up the execution of a PHP application but the question is how much faster? The answer depends on the PHP application and compared with what?
In this post I run a benchmark of Joomla, the famous CMS written in PHP, using Zend Server CE vs. APC and Memcached. To run this benchmark I worked together with Renato Salvatori of Cost, an IT company specialized in Joomla.
In details, we run the benchmark into two phases:
In order to use the Joomla caching with Zend Server we used a plugin written by me and Renato Salvatori, you can download it below in the post.
Benchmark methodology
We used the default installation of Joomla 1.5.17 using the example data for the content of the site. We tested the home page of Joomla using Apache Benchmark (ab) with 100 requestes and 10 concurrency users (-n 100 -c 10). We run each experiment 6 times and we took the average of the results. We measured the time per request (mean across all the concurrent requests in ms) and the transfer rate (Kbyte/sec).
All the experiments reported in this post have been executed using a CPU Intel Core 2 at 2.10 Ghz with 2 GB of RAM running Gnu/Linux OS with kernel 2.6.28 . We used the following software configuration: Zend Server 5 CE, Apache 2.2.11, PHP 5.3.2, Joomla 1.5.17, Memcached 1.4.5, APC 3.1.3p1, MySQL 5.0.45.
APC vs Zend Optimizer+
In the first step of the experiment we run the benchmark with the caching of Joomla disabled. We tested the response time of the home page with and without the bytecode accelerator of Zend Optimizer+ and APC. We reported the results in Table 1.
| time per request, mean across all concurrent requests (ms) | transfer rate (Kbyte/sec) | |
| No Cache, No Optimizer+, No APC | 114,017 | 286,87 |
| No Cache, APC | 80,135 | 408,27 |
| No Cache, Optimizer+ | 71,019 | 460,70 |
The results show that Zend Optimizer+ is the faster one. Using Zend Server 5 CE Joomla runs 60% faster of the PHP.net (with no accelerator) and 13% faster of APC. We reported the transfer rate of the results in Figure 1 (high value means better performance).

Data cache experiment
In the second step of the experiment we run the benchmark using the caching plugins of Joomla on the following caching systems: File, APC, Memcached, Zend Server CE (file), Zend Server CE (shared memory). We split the experiment into two steps: the first using the APC byte code accelerator, and the second using the Zend Optimizer+ code accelerator. Below we reported the results of this experiment (Table 2 and 3).
| time per request, mean across all concurrent requests (ms) | transfer rate (Kbyte/sec) | |
| Cache: File | 53,383 | 612,91 |
| Cache: APC | 49,275 | 664,23 |
| Cache: Memcached | 50,507 | 647,73 |
| Cache: ZendServer file | 51,541 | 634,51 |
| Cache: ZendServer shm | 46,527 | 703,50 |
As you can see the best result, in term of performance, comes with the usage of Zend Server CE (with shared memory caching system, shm). Zend Server CE is 14% faster than File, 9% faster than Memcached, and 6% faster than APC.
| time per request, mean across all concurrent requests (ms) | transfer rate (Kbyte/sec) | |
| Cache: File | 40,716 | 803,54 |
| Cache: APC | 38,898 | 841,13 |
| Cache: Memcached | 39,058 | 837,90 |
| Cache: ZendServer file | 39,102 | 836,95 |
| Cache: ZendServer shm | 36,531 | 895,79 |
The same results comes with Zend Optimizer+ enabled and APC disabled. The faster caching system is Zend Server CE with shared memory. Zend Server CE is 11% faster than File, 7% faster than Memcached, and 6% faster than APC.
If we compare the data cache results using APC or Zend Optimizer+ we discover that the best results comes with Zend Optimizer+, the data caching system of Joomla runs faster of 35% compared with APC (Figure 2, high value means better performance).

Figure 2: Transfer rate (Kbyte/sec)
Summarizing, using the Zend Optimizer+ and the Data Cache of Zend Server CE you can speed up the execution of Joomla from 60% to 300% compared with PHP.net (with no accelerator) and from 13% to 35% compared with APC.
The Joomla caching plugin for Zend Server CE
In order to use the data caching of Zend Server CE with Joomla you have to install the plugin joomla_zendserver.zip. You can download it here.
The installation of this new plugin is very easy, you have only to unpack the zendserver.tar.gz file and copy the files zendserver_disk.php and zendserver_shm.php in the folder libraries/joomla/cache/storage/ of Joomla.
After that you can choose the cache handler Zendserver_disk and Zendserver_shm from the System tab of the Global Configuration menu of the Administration interface of Joomla. That’s it!
Conclusion
In this post we showed that Zend Server CE is the faster PHP stack to run Joomla applications. The benefits, in term of performance, are great: up to 35% faster of APC and up to 300% of PHP.net (with no accelerators).
If you are interested in other benchmarks of Zend Server CE you can read the White Paper “Optimizing Drupal Performance” by Acquia and Zend Technologies.
In the future, I would like to run more benchmarks on Zend Server CE using other PHP open source softwares. If you have any proposals please add a comment, thanks.
In: IIS| Microsoft SQL Server| PHP| Windows Server| Zend Server
15 Apr 2010If you have a PHP application that use session data and you want to scale using multiple servers or build a reliable architecture you have to share the session data between all the servers in some ways. One of the easy way to do that is to use a load balancer to distribute the traffic between multiple servers and use a database to share the session data.
In the open source community there are many examples on how to share session data using database but i didn’t found an example using MS SQL Server with the new Microsoft SQL Server Driver for PHP so I decided to write a new session handler from scratch. I used the last version 1.1 of the Microsoft SQL Server Driver. I tested the session handler using two Windows Server 2003 running IIS6 and Zend Server 5 CE. I used a SQL Server 2005 database to share the PHP session between the two servers (see diagram below).

The custom session handler
I built a PHP class named SQLSrv_Session with the following static methods: open, close, read, write, destroy, and gc (garbage collector). Basically these are the methods that you have to provide to built a custom PHP session handler (see the session_set_save_handler function of PHP for more info). For security reasons I provided a method (sqlsrv_escape) to escape the session data to write in the MS SQL Server. After the definition of the class I used the register_shutdown_function of PHP to call the session_write_close. This is a fix for a issue of the PHP session manager as of PHP 5.0.5 (see the comments on the pgp.net page of session_set_save_handler). Finally, in order to change the default session handler to the SQLSrv_Session I used the session_set_save_handler as follow:
1 2 3 4 5 6 7 | ini_set('session.save_handler', 'user'); session_set_save_handler(array('SQLSrv_Session', 'open'), array('SQLSrv_Session', 'close'), array('SQLSrv_Session', 'read'), array('SQLSrv_Session', 'write'), array('SQLSrv_Session', 'destroy'), array('SQLSrv_Session', 'gc')); |
In this way we configure PHP to use a custom session handler (user) and choose the new methods of the session manager.
If you want to use the SQLSrv_Session handler you have to include the SQLSrv_Session.php in of all of your scripts (i suggest to use require_once “SQLSrv_Session.php”; at the beginning of your PHP scripts).
After that you can use the PHP session as usual using the $_SESSION global variable. The PHP session manager will use the SQLSrv_Session class to manage the session data instead of the default one.
Installation
In order to use this custom session handler you have to enable the sqlsrv extension from the Zend Server web interface (or in the php.ini if you are a fan of the old school). To manage PHP extensions using Zend Server is very simple, you can do everything using the web interface, under the menu Server Setup > Extensions. You can Turn on the extension with a click and restart the PHP environment with another click on the button Restart PHP, located at the bottom of the page.
To use the sqlsrv extension ver. 1.1 you must have installed the Microsoft SQL Server 2008 Native Client. You can check the system requirements of the SQL Server Driver for PHP here.
After that, to start to use the custom session handler you have to create a database in your MS SQL Server to store the session data.
This database will contain one table with the following structure:
session_id VARCHAR(32) as primary key session_value VARCHAR(MAX) NULL updated_on DATETIME not NULL
To configure the SQLSrv_Session class to use the table created in the previous step you have to use the following constants: DB_HOST, DB_USER, DB_PASS, DB_NAME, and DB_SESSION_TABLE. After that you will be able to use the custom session handler.
Testing
In the .zip attached in this post you can find a simple PHP script to test the custom session handler. This script basically try to use the session handler storing some random values into the $_SESSION. You can check the data stored in your SQL Server database to see if all is working good. To test the destroy method of the custom session handler you have to call the test.php?destroy (passing the destroy parameter in the URL).
Please let me be clear on this point, I provided only some test on this class and I used it only in a simple PHP scenario. If you are planning to use this code on a production environment you have to provide a complete test on your application. However I will be happy to help you if you will find issue using this class, so please comment this post.
Performance consideration
The solution provided in this post is very simple, easy to install and manage, these are its advantages. If your PHP application is used in an high traffic scenario and you need performance this solution is not good enough. It’s a well known fact that share session data using a database is not so fast, there are better ways to do that. For instance, using Memcached to share data in memory or using the Session Cluster of Zend Server 5, especially for business critical scenarios. However, if you are looking for an easy and cheapest solution to share PHP session between multiples IIS servers, using MS SQL Server, this can be actually a good solution for you.
Special thanks
I would like to thanks Gobal Deva to helping me to test the SQLSrv_Session class.
Download
In: PHP| Zend Core| Zend Framework| i5/OS
30 Jan 2010Recently I started to develop on IBM i5 systems using PHP. PHP is becoming a very popular languages in the IBM i5 community to produce web applications and to modernize “green screen” applications. If you want to know how to use PHP on IBM i5 systems you have to look at the Zend Core for i5, the PHP distribution of Zend Technologies.
Zend Core for i5/OS provides the i5 Toolkit for PHP, an API system to call i5 functionalities from PHP. One of the function of this API is the i5_spool that is able to manage spool files for specific i5 users. In this post I present a class to convert a spool file in PDF using the Zend_Pdf class of the Zend Framework.
The class is the i5Spool and you can download it here.
You can easly convert a spool file in PDF choosing the page format, the page margins, the font type, the font size, the interline, etc.
Here an example of usage:
1 2 3 4 5 6 7 8 9 10 11 12 | require_once 'i5Spool.php'; $spool= new i5Spool('host','username','password'); $sp = array ( 'JOBNAME' => 'QPADEV0012', 'SPLFNAME' => 'QPJOBLOG', 'SPLFNBR' => 3, 'USERNAME' => 'ENRICO', 'JOBNBR' => '697478' ); header("Content-Disposition: inline; filename=spool.pdf"); header("Content-type: application/x-pdf"); echo $spool->toPdf($sp); |
In the line 2 we create an i5Spool object passing the host, username and password to connect to the i5 system. In order to export a spool to PDF we use the toPdf method.
We have to pass the information related to the spool file: job name (JOBNAME), job number (JOBNBR), user (USERNAME), spool name (SPLFNAME) and spool number (SPLFNBR).
The toPdf function returns a string contains the PDF so you have to print it if you want to pass to the browser (line 12).
The toPdf method has a second optional parameter, an array contains the format of the PDF page.
The format of a PDF page is composed by (the default values are reported in parenthesis):

For instance if you want to change the font size, the margins and the interline you can use the follow array as second parameter of the toPdf method:
1 2 3 4 5 6 7 | $format= array ( 'font-size' => 10, 'interline' => 11, 'margin-left' => 30, 'margin-top' => 30, 'margin-bottom' => 30 ); |
For more info about the i5 Toolkit for PHP you can visit this web page: http://files.zend.com/help/Zend-Core-i5-Help/i5_php_connector_api.htm
In: PHP| conference
1 Dec 2009
Do you want to present a talk to the next phpDay conference in Italy? This year the conference will be the 14th-15th May 2010 in Alba Adriatica (a very nice place on the beach!).
The main topic of the conference is “PHP and quality”. Let’s go to propose you talk in english or in italian. You have time to send a proposal until the 15th of March.
The phpDay is the most important PHP conference in Italy since 2001. The conference is managed by GRUSP, the italian association of php users and developers.
For more info you can visit the web site of the GRUSP association here.
In: Books| PHP| Zend Framework
12 Nov 2009I’m reading the new book of Keith Pope, “Zend Framework 1.8, web application development” of PackT Publishing and my first impression is very good!
This book introduces the Zend Framework (ZF) using a direct approach to build a real web application in depth, in particular an e-commerce web site (you can download the source code of this application from the PackT web site).
In my opinion this is a very good approach because the main difficulties when you start a new php application using the ZF and in general the MVC paradigm are: how to structure the application, where to write the code, how to build the models, etc.
I guess this is one of the first book about the new version 1.8 of ZF. As you know starting from the version 1.8 the team of ZF has introduced the Zend_Application class to easly manage the configuration and the bootstrap phase of the application using a .ini file. The usage of the Zend_Application is showed in the Chapter 3 of the book.
Especially useful is the part of Model design in the Chapter 4, where the author shows step by step how to build a model and why. For instance the author presents the Model of a Product showing the balance between the Controller and the Model, and the general rules to follow: code reuse, controller readability, maintainability, etc.
I’m glad to the author to have inserted the Chapter 12 about testing the application using PHPUnit. This is a very important part of every software developing life cycle and sometimes in the real life someone forgot to test! Me too, i’m honest
In conclusion I strongly suggest this book if you are interested in developing php web applications using the Zend Framework, whether you are a newbie or and experienced ZF developer.
For more information about this book you can go to the publisher web site here.
In: PHP| Security| Zend Framework
22 Oct 2009In this post i’m going to refactoring the ZF Secure Login application, that i provided in my previous post, using the new Zend_Application class, out from the version 1.8 of Zend Framework.
Here you can find the source of the new application (12 Kb)
From the Reference Guide of ZF: “Zend_Application provides a bootstrapping facility for applications which provides reusable resources, common- and module-based bootstrap classes and dependency checking. It also takes care of setting up the PHP environment and introduces autoloading by default.”
Using this class I arranged the new application with some structural changes. In particular I modified the application folder with the following directories: configs, controllers, forms, layouts, models, plugins, views.
In the configs folder i provided an application.ini where i reported all the parameters of the application.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | [production] phpSettings.display_startup_errors = 0 phpSettings.display_errors = 0 includePaths.library = APPLICATION_PATH "/../library" bootstrap.path = APPLICATION_PATH "/Bootstrap.php" bootstrap.class = "Bootstrap" resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers" resources.layout.layout = "layout" resources.layout.layoutPath = APPLICATION_PATH "/layouts" resources.frontController.plugins[] = "App_Plugin_SessionCheck" resources.db.adapter = "PDO_MYSQL" resources.db.params.host = "localhost" resources.db.params.username = "root" resources.db.params.password = resources.db.params.dbname = "zf_example" resources.session.namespace= "SecureLogin" auth.active= on auth.timeout= 60 password.salt= "df7hsKJ3284sdhfj33BC" [staging : production] [testing : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 [development : production] phpSettings.display_startup_errors = 1 phpSettings.display_errors = 1 |
As you can see the application.ini is splitted into 4 different sections: production, staging, testing and development.
These sections are related to the different scenarios where to run the application.
In the production section you can find all the configuration data of the application, like the db parameters, the name of the bootstrap class, the layout path and the frontControllers plugin, etc (in this case the plugin is the SessionCheck that I used in the Initializer class of the previous architecture).
For the folders: controllers, layouts, models and views I provided the same structure of the previous architecture. So nothing is changed in their files.
The new two directories are forms and plugins. In the forms folder I provided an App_Form_Login class to manage the login Zend_Form. In the plugins folder I put the front controller plugin, named App_Plugin_SessionCheck, to manage the authentication.
In the previous architecture of the project i used the plugin Initializer with the method checkSession.
As you can notice almost all the classes of the application starts with App_ to indicate the applications folder. This looks much better for maintenance reason, to reach the classes more easly.
So basically the main difference of this new application, from an architectural point of view, are represented by the folder application, with the subfolder configs, forms and plugins.
The other differences are in the bootstrap phase. In this application the public index.php contains the following source:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // Define path to application directory defined('APPLICATION_PATH') || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application')); // Define application environment defined('APPLICATION_ENV') || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'production')); // Ensure library/ is on include_path set_include_path(implode(PATH_SEPARATOR, array( realpath(APPLICATION_PATH . '/../library'), get_include_path(), ))); /** Zend_Application */ require_once 'Zend/Application.php'; // Create application, bootstrap, and run $application = new Zend_Application( APPLICATION_ENV, APPLICATION_PATH . '/configs/application.ini' ); $application->bootstrap() ->run(); |
Basically an include path and an instance of the Zend_Application class with the application.ini to be used.
The other main difference is rappresented by the Bootstrap.php file located under the application folder.
This file contains the following source:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | class Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initModuleAutoloader () { $al = new Zend_Application_Module_Autoloader(array('namespace' => 'App' , 'basePath' => dirname(__FILE__))); } protected function _initView () { // Initialize view $view = new Zend_View(); $view->doctype('XHTML1_STRICT'); $view->headTitle('ZF Secure Login'); // Add it to the ViewRenderer $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('ViewRenderer'); $viewRenderer->setView($view); // Return it, so that it can be stored by the bootstrap return $view; } protected function _initSession () { $options = $this->getOptions(); $session = new Zend_Session_Namespace($options['resources']['session']['namespace']); Zend_Registry::set('session', $session); } } |
Here we defined the view structure of the application and the initialization of the Session.
With this new architecture all the resources, accross different classes, can be accessed using the Zend_Registry class.
We don’t use the Globals.php class anymore. This class, in the previuos architecture, contained the singletons entities used along all the application classes. I discovered that using a Global class you can become crazy to provide Unit Testing and in general to debug an application.
To reach the configuration data, from a controller, I used the method getInvokeArg(’bootstrap’)->getOptions(), for instance in the loginAction of the IndexController I retrieved the value of the auth.timeout of the application.ini using this piece of code:
1 2 | $options= $this->getInvokeArg('bootstrap')->getOptions(); $this->view->form = new App_Form_Login($options['auth']['timeout']); |
Moreover in this new application I simplify the security using the rand auto value of the token in the Zend_Form_Element_Hash. I used only a single salt value to improve the security of the md5 password stored into the table user of the MySQL database. In this way I provided a separation from the data of the database and the application. In this case if someone breaks into the database and not the application is not able to decrypt the password stored into the db. In the previous post i used different salt for every password but i stored it into the same db table.
The passwords are stored into the database using the MySQL statement ‘MD5(CONCAT(salt,password))’ where salt is the value stored into the password.salt of application.ini and password is the plain text of the password to store.
In conclusion the new application, using the Zend_Application class, seems to be much more structured, much more configurable with the use of the application.ini file, and last but not least we have to write less code, and this is the best part for a developer
In: PHP| Security| Zend Framework
3 Jul 2009After a long pause i’m come back on my blog with a post about the development of a secure web login system in PHP with the use of Zend Framework. The issue to build a login system in a web application is quite common. The security aspect of a login system is absolutely important and in this post i have summarized some of the main security points. Of course this is not the final solution but, in my opinion, is a good point of start for PHP developers.
I have built a simple Zend Framework application with a login and home page. The login is a form with a username and a password text box. This fields are mapped into a MySQL database, with a simple table with the following structure:
1 2 3 4 5 6 7 8 9 | CREATE TABLE users ( username VARCHAR(32) NOT NULL , password CHAR(32) NOT NULL , salt CHAR(20) NOT NULL , email VARCHAR(80) , active BOOLEAN NOT NULL DEFAULT 1 , last_access DATETIME NOT NULL , PRIMARY KEY (username) ); |
As you can see we store the password with a CHAR(32) field, this is because we use the MD5() hash function to secure the storing of the data. As you know if you store a password with an hash function is, in theory, impossible to invert the hash value and find the password in plain. I wrote in theory because, as Joe Devon writes in his comment, you can use Google to retrieves the most common hash values (for instance try this web site http://md5.rednoize.com/).
In order to improve the security of the MD5 i used a salt value. I added a salt field of CHAR(20) into the users table with a random string value. The MD5 of the password is generated with a MD5(CONCAT(salt,’password’)) where ‘password’ is the password string value. With this salt method is more difficult to use a dictionary attack of the MD5 values.
With this system even the administrator of the site can’t know the password of their users. This is very important for privacy reason (do you trust websites that are able to recover your password?).
This application uses the following Zend Framework classes to build the secure login:
I have structured the application into the following directories:

The main directoris are: application, etc, library, public.
In application i put the usual MVC structure of a Zend Framework, with the files bootstrap.php and Initializer.php. The Initializer class is a plug-in of the Front Controller where i wrote the authentication check of the login. I think it’s a good solution for a login system because in this way we can manage the authentication system without any modification of the Controllers. This means that if a user is able to see a Controllers he is just authenticated.
In the etc directory i put the configuration file config.ini and the database structure into the sub-dir db.
In the library directory i put the common php classes that i reuse in my Zend Framework applications and a sub-directory name Forms with all the forms of the application.
In the public directory i put the document root of the application with .css, .js, images and the index.php that is the only php scripts published into the document root.
We focus now on the Initializer plugin, that is the core of the login system.
This Initializer plugin comes from the structure proposed by the Zend Studio for Eclipse where i have inserted some more methods.
In particular i have added the preDispatch and checkSession methods.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /** * preDispatch */ public function preDispatch () { $this->_controller= $this->_front->getRequest()->getControllerName(); if (($this->_controller!='index') && ($this->_controller!='error')) { if (Globals::getConfig()->authentication->active) { $this->checkSession(); } } } /** * checkSession */ private function checkSession() { if (empty(Globals::getSession()->username)) { $this->_response->setRedirect('/index/login')->sendResponse(); exit; } } |
The preDispatch method is called from the Zend Framework flow first to dispatch every actions and for this reason it’s a good point where insert an authentication system. In the preDispatch method we get the name of the Controller and we check if the actual controller is different from index and error, if it’s true i call the checkSession method.
Notice that i used another if to check if the authentication system is on, using the attribute active of the config.ini file. This system can be useful to switch on and off the authentication, changing a single value into a configuration file.
The index and error are the controllers out of the authentication system, this because they contain public pages that must be visible without autentication.
The checkSession method is very simple, it checks if the session variable username is empty, if it is empty means that the user is not authenticated and the execution flow must be redirect to the login page. Note the presence of the exit() function, it’s very important because without it an authorized user can execute actions because the flow of Zend Framework continues after the sendResponse (thanks to Ankit for his comment).
As you have noticed i used the Globals class to take some singleton objects related to the management of the database conncetion, the session and the configuration file. I usually built these singletons because i have only one instance of database, session and configuration file during the execution of my PHP applications. Moreover with a singleton i can speed up the reading of these values during the execution of the same instance of an application.
The login form of the application is built into the library/Forms/Login.php script. I used the Zend_Form_Element_Hash class of the Zend Framework to secure against CSRF attacks (click here for info about CSRF attacks). I used the setSalt method to improve the security with a pseudo-random value obtained with the function md5(uniqid(rand(), TRUE)) and the setTimeout to set a Time To Live (TTL) for the token (the value of timeout is specified into the config.ini).
... $token = new Zend_Form_Element_Hash('token'); $token->setSalt(md5(uniqid(rand(), TRUE))); $token->setTimeout(Globals::getConfig()->authentication->timeout); $this->addElement($token); ...
With this hidden value, the token, inserted into a form we are sure that the POST data comes from our page and not from others.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | ... public function loginAction() { $flash = $this->_helper->getHelper('flashMessenger'); if ($flash->hasMessages()) { $this->view->message = $flash->getMessages(); } $this->view->form= new Forms_Login(); $this->render('login'); } ... public function submitAction() { $form= new Forms_Login(); if (!$form->isValid($_POST)) { if (count($form->getErrors('token')) > 0) { return $this->_forward('csrf-forbidden', 'error'); } else { $this->view->form = $form; return $this->render('login'); } } $username= $this->getRequest()->getPost('username'); $password= $this->getRequest()->getPost('password'); $authAdapter = new Zend_Auth_Adapter_DbTable( Globals::getDbConnection(), 'users', 'username', 'password', 'MD5(CONCAT(salt,?)) AND active=1' ); $authAdapter->setIdentity($username) ->setCredential($password); $result= $authAdapter->authenticate(); Zend_Session::regenerateId(); if (!$result->isValid()) { $this->_helper->flashMessenger->addMessage("Authentication error."); $this->_redirect('/index/login'); } else { Globals::getSession()->username= $result->getIdentity(); Zend_Loader::loadClass('Users'); $users= new Users(); $data= array ('last_access' => date('Y-m-d H:i:s')); $where= $users->getAdapter()->quoteInto('username = ?', Globals::getSession()->username); if (!$users->update($data,$where)) { throw new Zend_Exception('Error on update last_access'); } $this->_redirect('/home'); } } ... |
In the loginAction i built the login form (line 7).
The data of the login page are submitted to the submitAction method. In this action we check the validation of the form (line 13). If there’s a problem on the token data this means that we are under a CSRF attack so we can redirect to a specific error page named csrf-forbidden. The csrf-forbidden page gives a 403 Forbidden value, this to prevent that we send the form data to an unauthorized user (for more info about this subject read the post “Preventing CSRF properly” of Tom Graham).
For the authentication of the user we used the Zend_Auth_Adapter_DbTable adapter (line 23). We check the authorization using the MD5 of the password (MD5(?), where ? is $password) only for the active users (active=1).
If the user is authenticated we update the last_access field of the user table and we redirect to the home page (lines 38-46).
If the user is not authenticated we redirect to the login page with the error message ‘Authentication error.’.
Notice that we regenerated the session id with the Zend_Session::regenerateId() during the login (line 33) and we clean the session during the logout (line 25 of the logoutAction into the HomeController). This for security reason in order to mitigate the possibility of a session fixation attack (click here for info about session fixation).
In this post i didn’t talk about SQL Injection, why? Because the Zend_Db class that we used in this application uses placeholder quoting to prevent SQL Injection. Moreover we used the validator of the Zend_Form in order to filter the input values of username and password (see the addValidators method in the Forms_Login class). So the mantra “Filter Input, Escape Output” is respected.
In this post i provided a secure login application with the use of Zend Framework. The securiy aspect of this application are:
One of the unsecure point of this application is that the username and the password are submitted in plain text. Any attacker that is able to sniff the HTTP communication between client and server can capture these information.
In order to build a real secure system i suggest to use the Secure Sockets Layer protocol (SSL), this is the only way to encrypt the communication between client and server.
Here you can find the source code of the Secure Login Application. In order to execute the code you have to create a MySQL database using the SQL structure reported in /etc/db/dbUsers.sql and modify the etc/config.ini with your db permission.
I tested the application with the Zend Framework v. 1.8.4.
Click here to download the source code (ZFSecureLogin.zip, 13Kb)
In: PHP| Zend Platform
25 Apr 2009One of the features of the Zend Platform is the Job Queue, a server application that is able to schedule and manage the execution of php scripts (jobs).
The Job Queue can be used to create asyncronous execution of php script and provide, for instance, the scalability of a server application (for more info read the White Paper “Scalability and Responsiveness with Zend Platform’s Job Queue” by Dotan Perry and Shie Erlich).
You can manage the Job Queue feature of the Zend Platform with a web interface (see the figure below) or directly in PHP with an API system.

Using the web interface you can schedule the execution of a job (a php script) that is located into the JobQueue directory of the Zend Platform (the default is /usr/local/Zend/Platform/JobQueue in a Linux environment). You can also suspend and resume jobs from the queue, view the statistic of the job queue, view the history of each job execution and setting the parameter of the queue (maximal queue depth, maximal re-queue times, queue alias, scripts folder, etc).
As I said you can use the job queue also from PHP with the use of a API system. Basically the Job Queue Zend API contains two main classes to manage the connection to a queue server and to schedule the execution of jobs. This classes are ZendAPI_Queue and ZendAPI_Job. Is very easy to use this API and you can schedule the execution of your php script in a few lines of code. Let me show this introducing some examples.
In order to connect to a queue server you have to specify the host:port address and the password of the queue server (the default port of the queue server is 10003). Here there is an example:
1 2 3 4 | $queue= new ZendAPI_Queue('192.168.1.10:10003'); if ((empty($queue)) || (!$queue->login('password'))) { throw new Exception('Error on queue connection'); } |
When you have established a connection you can manage the scheduling of a job. For instance here we scheduled the execution of a job named send_email.php for the next 4 hours.
1 2 3 | $job = new ZendApi_Job("send_email.php"); $job->setScheduledTime(time() + 4*3600); $id = $queue->addJob($job); |
If you want to search for a job into a queue server you can use the getJobsInQueue method of the ZendAPI_Queue class.
For instance you can remove the failed jobs from a queue server with the following code:
1 2 3 4 5 6 7 8 9 10 | $queue= new ZendAPI_Queue('192.168.1.10:10003'); if ((empty($queue)) || (!$queue->login('password'))) { throw new Exception('Error on queue connection'); } $jobs_status = array(status=>JOB_QUEUE_STATUS_LOGICALLY_FAILED); $all_failed_jobs = $queue->getJobsInQueue($jobs_status); foreach ($all_failed_jobs as $failed_job) { echo "removing job $failed_job from queue..."; $queue->removeJob($failed_job); } |
In this post i introduced only the main functions of the Job Queue Zend API, for the complete list you can read the User Guide of Zend Platform 3.6 at pag. 295-305.
In my opinion using the Job Queue feature of the Zend Platform you can explore a new way to think about web solutions with asyncronous execution of PHP code.
In: PHP
11 Apr 2009Today i created an example in PHP to display data into a Google map. I used my GMaps class (see my previous post) to retrieve geographic information for all the provinces of Italy, as you know i’m italian. I inserted all the data into a table of MySQL with the following fields: id, province, code, area, latitude, and longitude where code is the italian automobile code and area is the name of the region. For instance the province of Pescara has the following record: 69,’Pescara’,'PE’, ‘Abruzzi’, 42.4648, 14.2141.

The example in PHP uses this database to display the geographic data of all the provinces of Italy. You can select the geographic area (region) in a combobox and display the data on a Google Map.
You can download the source code of the example with the database here.
This is my personal blog about computer programming in PHP for business and passion. I'm Enrico Zimuel a Software Engineer since 1996. I work as Senior Consultant & Architect at Zend Technologies. For more info about me visit my web site.