Getting Smarty 3.0 to work with Zend Framework 1.9

Assuming you’re using the method demonstrated in the Zend Framework Manual, the first thing you need is to configure the Zend AutoLoader. Add this to the index.php file in your public directory:

// Configure autoloader
require_once 'Zend/Loader/Autoloader.php';
$autoloader = Zend_Loader_Autoloader::getInstance();

// Require Smarty Engine
require_once 'Smarty/Smarty.class.php'; // Assuming that you have the Smarty engine at "library/Smarty"
$autoloader->pushAutoloader('Smarty', 'smartyAutoload');

Change the following line in “Smarty/Smarty.class.php” (about line 91) from this:

if (set_include_path(SMARTY_SYSPLUGINS_DIR . PATH_SEPARATOR . get_include_path()) !== false) {

To this:

if (!class_exists('Zend_Loader_Autoloader') && set_include_path(SMARTY_SYSPLUGINS_DIR . PATH_SEPARATOR . get_include_path()) !== false) {

Next, comment out the line in the Smarty Constructor (about line 237):

//$this->template_dir = array('.' . DS . 'templates' . DS);

We want to keep it a null value (which is the default). If we don’t make this change in the constructor (mentioned just above), we’ll get PHP Notices that Zend_Controller_Action_Helper_ViewRenderer tried to convert an array to a string.

Finally, add this to your bootstrapper class:

protected function _initView()
{
$viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper(‘ViewRenderer’);
$view = new Zend_View_Smarty();

$viewRenderer->setView($view)
->setViewScriptPathSpec(APPLICATION_PATH . ‘/views/scripts/:controller/:action.:suffix’)
->setViewSuffix(‘tpl’);
}

If you’re using modules, you might want to make a slight change to the setViewScriptPathSpec method:

setViewScriptPathSpec(APPLICATION_PATH . ‘/modules/:module/views/scripts/:controller/:action.:suffix’);

You should be good to go. I should mention that this will cause your layouts to be parsed via Smarty as well; which presents its own problems. A potential work around is to include a common header and footer for each individual template, although this is far from ideal. In that case, what you might want to do is disable the view renderer’s auto render feature and create a custom plugin or action helper that will render the templates and layouts. I’m considering expounding on this in another post…

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.