Zend Framework Migration and File Not Found

Recently I went through and upgraded a website from Zend Framework 1.7 to the latest 1.9 minor version. Everything worked great for the most part (aside from a minor code change involving Zend Filter for requests), but there was one significant change that was a bit of a hassle to fix (i.e. “File not found” and “directory listings prohibited” Apache errors).

One of the major changes since 1.7 is the functionality of the Zend Framework class AutoLoader. In previous versions of Zend Framework all you had to do was instantiate the AutoLoader and the classes would magically load as needed. But now it’s not quite so simple. The rationale, and it’s quite good, for the change can be read about in this Zend devzone article.

It’s important to mention at this point that if, for examle, your “IndexController” inherits directly from “Zend_Controller_Action”, you will not need to do any of this because in that scenario, you should not have any of these issues. These hurdles are only applicable if you extend the Zend Framework classes with your own.

Moving on… Instead of just instantiating the AutoLoader, you must now declare all namespaces that will be used throughout your application. For example, in your application controllers directory you might have a class named “BlogController.php” and your class would be named something like “IndexController” which extends a custom controller in the library that looks like “Blog_Controller_Action” and that class would extend “Zend_Controller_Action”. The AutoLoader knows where to find “Zend_Controller_Action”, but it doesn’t know where to look for “Blog_Controller_Action”. There are two solutions to this problem.

The easy answer is you to add the “$autoloader->setFallbackAutoloader(true);” function call, but this is kind of hack. In addition, using the Zend Framework default loader as a fallback means that every request to your site will result in an error, and then Zend Framework will try to use the default loader to resolve the request. This means extra load time and extra stress on the server. Granted, there is an “$autoloader->suppressNotFoundWarnings(true);” function, but it doesn’t work the way you think. Read more about the default autoloader on the Zend Framework manual here.

The correct solution to this problem is to declare all your namespaces and instantiate a unique AutoLoader for your models and controllers. For example:

// Set up autoload.
require_once 'Zend/Loader/Autoloader.php';
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->setFallbackAutoloader(true);
// Just in case there's something we missed, we can leave the fallback

// Add resource loader, otherwise "file not found" errors are raised
$resourceLoader = new Zend_Loader_Autoloader_Resource(array(
    'basePath'  	=> '../library/Blog/',
    'namespace' 	=> 'Blog',
	'resourceTypes'	=> array(
		'model'			=> array(
			'path'		=> 'model/',
			'namespace'	=> 'Model',
		),
		'controller'	=> array(
			'path'		=> 'controller/',
			'namespace'	=> 'Controller'
		)
	)
));

$autoloader->pushAutoloader($resourceLoader);

You can read all the details here. It’s quite a change from the simplicity before, but it’s a good change.

In addition, you’ll need to make sure to update your .htaccess to the following or else you’ll get a bunch of “Directory indexes prohibited by server configuration” errors:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]

This also has been modified and improved over previous versions, for one, it loads Flash files (and other non-standard extensions) without a problem. Strangely, I didn’t see the .htacces directives in the Zend Quickstart tutorial, but it is in the Zend Framework’s manual Application Quickstart. The page names are similar but they are completely different.

In summary, until we made the changes mentioned above to our Zend Framework configuration our Apache error log was riddled with thousands of “File not found” and “Directory indexes forbidden” errors. The AutoLoader change resolved the “file not found” errors, and the .htaccess update resolved the “Directory indexes forbidden” errors. Hope this was useful.