Posted: December 11th, 2010 | Author: enrico | Filed under: Books | Tags: agile, book, refactoring | No Comments »
Like PHP consultant I meet every day companies that have to fight with legacy code. Often the developers that built the software have left the company and the new programmers prefer rewrite the software from scratch instead of mantain the old one. The business decision to rewrite a software from scratch is always a difficult task because rewriting software means spend time and money. This is an old story and I’m sure you have already seen it.
If you want to know when and how to refactor a PHP application I suggest to have a look at this new book Pro PHP Refactoring by Francesco Trucchia and Jacopo Romei (Apress publisher, 2010). In this book the authors describe what is the software refactoring, when you should refactor a PHP code and how to do that. This book is the summary of all the principles, best practices and suggestions collected by the authors in the last years. It represents a bridge between the PHP language and the refactoring techniques developed by Martin Flower and the agile community.
Most of the chapters show how to refactor your code using different techniques to change the structuring behavior, the class responsibilities, dealing with data rationalization, simplifying method calls, etc.
I found very interesting the second chapter Finding “bas smells” in code, where you can understand when is the time to think about refactoring and the Refactoring tools chapter where the authors show how to choose the right PHP tools to help the refactoring job.
In conclusion, I definitely suggest to have this book in your PHP toolbox, you will find it useful in the right moment.
Posted: October 22nd, 2009 | Author: enrico | Filed under: Zend Framework | Tags: md5, PHP, refactoring, Zend Framework, Zend_Application | 17 Comments »
In 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