
Hello! The other day a job turned up - to add a site on the zend framework. The programmer, who began to develop this project did not have time to date, did not fulfill the requirements of the customer and as a result he was replaced. Having opened the source code for the first time, I was horrified by the number of errors that the developer made, and he claimed to the customer that he was an experienced specialist. Next, I will try to tell you about some of the mistakes that they made. This material will be useful for beginners ZF-programmers, as instructions on how to do not
. I will also tell you about some moments not directly related to the framework, but also being vivid examples of developer ignorance.
Using built-in model methods, instead of writing your own
The first thing that immediately caught my eye was the execution of requests through the model object directly in the controller code, which completely negates all the advantages of MVC. To make it clear what I mean, I will give an example of the source code:
$model = new Model();
$some_data = $model -> fetchAll ( array ( 'field1 = ?' => 1 , 'field2 = ?' => 0 ));
$all_data = $model -> fetchAll ();
Colored with dumpz.orgSuch a confusion of logic was in each file of the controller, which greatly interfered with reading the code and correcting errors, there were constantly some not obvious dependencies, important data was overwritten. Accordingly, it is not possible to do this in any way, even if you are developing a small project.
Directly access global arrays instead of a Request object.
ZF has a very convenient wrapper over global variables in the form of an object of class Zend_Controller_Request_Http. This class provides us with a lot of data access capabilities and is used by the framework in the dispatching process. Therefore, do not neglect the use of the query object.
')
Lack of context-switching when necessary
To implement the processing of ajax requests, you can use the so-called. context-switch which is a convenient way to change the response format. If you are using json, then in the controller's init method set something like the following:
$this -> _helper -> AjaxContext () -> addActionContext ( 'ajax-handler' , 'json' ) -> initContext ( 'json' );
Colored with dumpz.orgNow all the data transferred to the view in the ajax-handler action will be recoded into json format. This method is preferable to disabling view and manually converting data to json.
Neglect using Zend_Form and Zend_Validate
Do not use php functions for data validation, since in ZF there are very convenient validators that can be grouped together and put on processing certain form fields. Using ZF-validators you reduce the chance that you miss something and thereby make your applications more sustainable.
No validation check
You should check all the data you received from the user, and you should check them in the context of the access rights of this user, for example, if you write the addition / removal of materials from the list of favorites and you have js-functions like the ones below, then you should be very good think:
function addObject(object_id, user_id) {
if (user_id > 0 ) {
$.get( '/realestate/favorite/oid/' + object_id + '/uid/' + user_id, function () {
$( "#addfavorite" + object_id).hide();
});
}
}
function removeObject(object_id, user_id) {
if (user_id > 0 ) {
$.get( '/profile/removefavorite/oid/' + object_id + '/uid/' + user_id, function () {
$( "#removefavorite" + object_id).hide();
});
}
}
Colored with dumpz.orgAs it turned out, the server-side user_id was not checked for equality with the current user ID, which is a serious vulnerability
Using controller class hierarchy instead of ACL
Almost every site has several levels of access: guests, users, administrators, etc. In order to control the access rights of statuses to certain parts of the site, hierarchies of controllers were used. Those. a parent class was created for the admin controllers, a class for the rest of the controllers and something like this was executed in this parent class:
public function preDispatch () {
// *fail*
if ( ! empty ( $_REQUEST [ 'session' ])) {
session_id ( $_REQUEST [ 'session' ]);
} else {
$auth = Zend_Auth :: getInstance ();
if ( ! $auth -> hasIdentity ()) {
$this -> _redirect ( 'backoffice/auth/login' );
}
}
}
Colored with dumpz.orgWhat's wrong with this approach? First of all, the redistribution of access rights is very difficult. Secondly, it is difficult to maintain several roles. You can continue for a long time
For these purposes in ZF, there is a great tool for building access lists or ACLs. Personally, I use a small plugin that checks the access rights of a given user to the requested action / controller in the dispatch process. This method allows you to create permissions in a simple, easily changeable list, like this:
//
$this -> addRole ( 'guest' );
$this -> addRole ( 'user' , 'guest' );
$this -> addRole ( 'manager' , 'user' );
//
$this -> add ( new Zend_Acl_Resource( 'guest_allow' ));
$this -> add ( new Zend_Acl_Resource( 'index/index' ), 'guest_allow' );
$this -> add ( new Zend_Acl_Resource( 'index/registration' ), 'guest_allow' );
$this -> add ( new Zend_Acl_Resource( 'error/error' ), 'guest_allow' );
$this -> add ( new Zend_Acl_Resource( 'user_allow' ));
$this -> add ( new Zend_Acl_Resource( 'index/logout' ), 'user_allow' );
$this -> add ( new Zend_Acl_Resource( 'project/index' ), 'user_allow' );
$this -> add ( new Zend_Acl_Resource( 'task/index' ), 'user_allow' );
$this -> add ( new Zend_Acl_Resource( 'task/complete' ), 'user_allow' );
$this -> add ( new Zend_Acl_Resource( 'task/assigned' ), 'user_allow' );
$this -> add ( new Zend_Acl_Resource( 'manager_allow' ));
$this -> add ( new Zend_Acl_Resource( 'project/add' ), 'manager_allow' );
$this -> add ( new Zend_Acl_Resource( 'task/add' ), 'manager_allow' );
$this -> add ( new Zend_Acl_Resource( 'index/add-user' ), 'manager_allow' );
// , -
$this -> deny ( null , null , null );
$this -> allow ( 'guest' , 'guest_allow' , 'show' );
$this -> allow ( 'user' , 'user_allow' , 'show' );
$this -> allow ( 'manager' , 'manager_allow' , 'show' );
Colored with dumpz.orgFiltering data in the fields responsible for entering a password
Never, never filter the data that comes from the password field! This is fraught with long attempts to find the reason why users can not log in. In my case, the reason was the following:
$f = new Zend_Filter_StripTags();
$pwd = $f -> filter ( $this -> _request -> getPost ( 'pwd' ));
Colored with dumpz.orgConsidering that passwords should be stored in an encrypted form and should never be displayed, the presence of tags or spaces in them can not in any way lead to vulnerabilities, respectively, and filtering to nothing
Provide localization is necessary in advance.
Often for some reason, the localization of the project is taken to the background, i.e. at first we’ll drink everything, and then we will fix the localization. This is a big mistake, because then it will be very difficult to fasten it. It will be necessary to find all non-localized strings, and this is a very long process. It is much easier to immediately handle the lines that require multilanguage.
Refusal to use ViewHelpers
You should always use url and baseUrl view helpers to generate url and paths to static resources. This is important because you cannot be sure how the application will be located with other developers. In our case, the paths were formed as if the application was in the root of the host, which created a number of problems when deploying to my machine.
Using text constants instead of logical variables
In conclusion, I want to tell you about an interesting way to replace logical variables with strings. In the code, I found something like this:
if ( $a > $b )
$this -> view -> result = 'ok'
else
$this -> view -> result = 'fail' ;
Colored with dumpz.orgHere, no additional explanation is required, I think the last line is very eloquent for me.
Conclusion
This is not a complete list of errors that were found in the process of finalizing the project, but I have described the main ones. I hope that someone reading this material will begin to write better code. Thanks for attention!