Integrating Smarty with the Zend Framework
1. A few words about Smarty
Official Smarty website says: “Smarty is a template engine for the PHP development language.” Actually it was made by same people who made PHP and it’s the oldest and most well known template engine for PHP.
I’ve used Smarty many times before and I think, this engine is reliable enough to be used in big and high loaded projects.
2. Initialization and configuration
First, the good idea is to put Smarty configuration (paths to templates, configs, template cache e.t.c.) to your Zend project config.
To me the best place to do that is xml file which will be loaded to Zend_Registry on application bootstrap:
Xml config:
<?xml version="1.0"?> <configdata> <development extends="production"> <caching>true</caching> <cache_lifetime>1000</cache_lifetime> <template_dir>templates</template_dir> <compile_dir>temptemplates_c</compile_dir> <cache_dir>temptemplates_cache</cache_dir> </development> </configdata> |
bootstrap part:
class BR_Config_SmartyConfig { public $caching; public $cache_lifetime; public $template_dir; public $compile_dir; public $config_dir; public $cache_dir; } $xmlConfig = new Zend_Config_Xml('smarty.xml', 'development'); $configuration = new BR_Config_SmartyConfig(); $configuration->caching = $xmlConfig->caching; $configuration->cache_lifetime = $xmlConfig->cache_lifetime; $configuration->template_dir = $xmlConfig->template_dir; $configuration->compile_dir = $xmlConfig->compile_dir; $configuration->cache_dir = $xmlConfig->cache_dir; $registry = Zend_Registry::getInstance(); $registry->configuration = $configuration; |
Okay, now we have Smarty configuration as object in Zend_Registry and it is accessible as:
$registry = Zend_Registry::getInstance(); $configuration = $registry->configuration; |
3. The View
My class BR_View_Smarty is extending the Zend_View_Abstract class. In the constructor the parent constructor from Zend_View_Abstract is called first. After that a Smarty object is instantiated, configured and stored in a private attribute.
NOTE: don’t forget to include Smarty.class.php file. I’m doing it in index.php file (entry point to my application) like this:
define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application/')); set_include_path( APPLICATION_PATH . '/../library' . PATH_SEPARATOR /* this is folder with Zend libs and application itself*/ . APPLICATION_PATH . '/../libs' . PATH_SEPARATOR /* this is folder with third party libs: smarty folder is there */ . get_include_path() ); require_once 'smarty/Smarty.class.php'; |
So, now we are ready to implement View:
Step 1. Class, derived from Zend_View_Abstract with local property of Smarty type:
class BR_View_Smarty extends Zend_View_Abstract { private $_smarty = false; public function __construct($data = array()) { parent::__construct($data); $registry = Zend_Registry::getInstance(); $config = $registry->configuration; // I'd like to tell my IDE that $config is BR_Config_SmartyConfig object $config instanceof BR_Config_SmartyConfig; $this->_smarty = new Smarty(); $this->_smarty->caching = $config->caching; $this->_smarty->cache_lifetime = $config->cache_lifetime; $this->_smarty->template_dir = $config->template_dir; $this->_smarty->compile_dir = $config->compile_dir; $this->_smarty->config_dir = $config->config_dir; $this->_smarty->cache_dir = $config->cache_dir; } |
Step 2. Implement view rendering.
The method _run() is the only method that needs to be implemented in any subclass of Zend_View_Abstract. It is called automatically within the render() method.
All we have to do here is to call Smarty’s display method in View’s _run method:
protected function _run($template_name) { $this->display($template_name); } |
Okay, now we can render our, be how do we get data to render?
Step 3. Setting view variables.
To set Smarty view variable we need to call assign(‘name’, ‘value’) method on $smarty object.
Zend_View_Abstract has assign method too. So, all we have to do is to override assign method of Zend_View_Abstract and use $smarty->assign there:
public function assign($var, $value = null) { if (is_string($var)) { $this->_smarty->assign($var, $value); } // we can pass assoc array for bulk view variable assignment elseif (is_array($var)) { foreach ($var as $key => $value) { $this->_smarty->assign($key, $value); } } } |
also you can use magic method __set for view variable assignment:
public function __set($key, $val) { $this->assign($key, $val); } |
Step 4. Time for output.
Output method of Zend_View_Abstract is used to set some header to avoid accidental static content caching and then render method is called.
public function output($name) { header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); header("Cache-Control: no-cache"); header("Pragma: no-cache"); header("Cache-Control: post-check=0, pre-check=0", FALSE); print parent::render($name); } |
4. How to use this class
To set Zend Framework View engine to the one that we’ve implemented we have to override it on application bootstrap:
//don't forget to init configuration here $view = new BR_View_Smarty(); Zend::register('view', $view); |
Now we have our view set up. So let’s use it from controller:
public function indexAction() { $viewTemplate = 'index.tpl'; $view = Zend::registry('view'); $view->assign('title', 'Index page'); $view->assign('text', 'Index page text.'); // bulk variable assignment $numbers = array(); $numbers[0] = 9.29; $numbers[1] = 10; $numbers[2] = 17; $view->assign($numbers); $view->output($viewTemplate); } |
…and we’re done.
Perfect article! Saved my life! Best article about this integration i’ve viewed!