coding >> Zend Framework and Smarty integration (6,827 views)

Table of contents for Zend Framework

  1. Zend Framework and Smarty integration
  2. A better Zend Framework & Smarty integration
  3. Zend_Layout example

I have been using Smarty (php template engine) for quite some time but I am really new to Zend Framework, in fact I started using it for the first time yesterday.

To do the integration i found two very good articles:

  1. http://devzone.zend.com/node/view/id/120
  2. http://kpumuk.info/php/zend-framework-using-smarty-as-template-engine/

However both articles refer to an older version of Zend Framework and they are a bit confusing if you are a Zend beginner like me. On this post i assume Zend Framework version 1.5 and Smarty 2.6.19 (but should work with older Smarty too).

First I assume you have a directory structure similar to this:
/application
    /controllers // in here we put our controllers
    /library // in here the classes we extends i.e. Smarty_View
    /models // in here the database tables related classes
/cache // smarty cache directory
/configs // config files
/htdocs // document root (public)
    /images
    /css
    /js
/Smarty // smarty engine
/templates // smarty templates
/templates_c // smarty compiled templates

Using ZF becomes very easy to place a MVC (Model View Controller) architecture in place, (ZF does all the plumbing for you).

ZF has a front controller that acts as a dispatcher, this intercept all the requests and then depending on the URL the request is dispatched to the right controller. For this reason we need a .htaccess file inside our htdocs document root, with the following rewrite rule:
RewriteEngine on
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php

The above rule will ensure that all the requests that are not for resources with this extensions (js|ico|gif|jpg|png|css) will be handled by our index.php file.

Inside the htdocs directory I have the index.php file which has only one line in it:

<?php
require_once '../application/bootstrap.inc';

the closing ?> php tag is missing on purpose, is not really required by php and not using it prevents some issues regarding additional white space sent before headers.

Now my bootstrap.inc inside the /application directory looks like this:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<?php
 
/* Report all errors directly to the screen for simple diagnostics in the dev environment */  
error_reporting(E_ALL | E_STRICT);  
ini_set('display_startup_errors', 1);  
ini_set('display_errors', 1); 
 
/* The following two simple lines, allow us to use ZF classes without including the 
 * them in our scripts, they will be automatically loaded
 * so we don't need the require lines on top of our scripts before we use any of 
 * the ZF classes
 */
require_once "Zend/Loader.php"; 
Zend_Loader::registerAutoload(); 
 
/*
 * here I am loading my configuration file
 * and i am placing the returned object inside Zend registry
 * this is a bit like having it as a global variable
 */
$config = new Zend_Config(require '../configs/config.php');
Zend_Registry::set('config', $config);
 
/* 
 * Smarty_View is a class that extends Zend_View_Abstract class, 
 * This is the class that connects ZF with Smarty
 * the constructor takes a configuration array
 * the only param we need to pass is the 'scripPath'
 * which tells the class where our smarty tpl templates are.
 * At the end of the code block the object is placed 
 * in Zend registry
 */ 
$viewConfig = array();
$viewConfig['scriptPath'] = $config->template_dir;
require_once 'library/Smarty_View.inc';
$view = new Smarty_View($viewConfig);
Zend_Registry::set('view', $view);
 
/*
 * This last block is all about ZF front controller, its a singleton class, 
 * only one instance is available to the application. 
 * Its job is to dispatch all the incoming requests to the right controller
 */
/* Set the singleton instance of the front controller */ 
$frontController = Zend_Controller_Front::getInstance(); 
/* Disable error handler so it doesn't intercept all those errors we enabled above */ 
$frontController->throwExceptions(true); 
/* Point the front controller to your action controller directory */ 
$frontController->setControllerDirectory($config->site_dir.'/application/controllers'); 
/* the following is an important line, we are telling ZF 
 * that we are going to be responsible of our views
 * in fact we are going to do it using Smarty
*/
$frontController->setParam('noViewRenderer', true);
/* OK, do your stuff, front controller */ 
$frontController->dispatch();

The above file loads the config.php that is inside the /config directory:

1
2
3
4
5
6
7
8
9
10
<?php
define("SITE_ROOT", dirname($_SERVER['DOCUMENT_ROOT']));
return array ('site_dir' => SITE_ROOT,
              'smarty_dir' => SITE_ROOT."/Smarty/",
              'template_dir' => SITE_ROOT."/templates",
              'compile_dir' => SITE_ROOT."/templates_c",
              'config_dir' => SITE_ROOT."/configs",
              'cache_dir' => SITE_ROOT."/cache",
              'caching' => 0,
              'compile_check' => true);

Following is the /library/Smarty_View.inc file:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php
class Smarty_View extends Zend_View_Abstract
{
    private $_smarty;
 
    /**
     * the array in the constructor contains the configuration file
     * we loaded in the bootstrap.inc file
     * the only field here is the 'scriptPath'
     * which is the directory of our smarty templates
     */
    public function __construct($data=array())
    {
        parent::__construct($data);
        $config = Zend_Registry::get('config');
 
       // make smarty class accessable
        require_once $config->smarty_dir."Smarty.class.php";
 
        $this->_smarty = new Smarty();
        $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;
        $this->_smarty->caching = $config->caching;
        $this->_smarty->compile_check = $config->compile_check;
    }
 
    /**
     * called internally, will display our template.
     * Its an override, it has no parameters
     * however a template file name is passed 
     * and we can retrieve it with the func_get_arg function
      */
    protected function _run()
    {
        $this->_smarty->display(func_get_arg(0));
    }
 
    /**
     * assign is an override, but in the application
     * i use it the same way i would have used 
     * the smarty assign function
     */
    public function assign($name, $value=null)
    {
        $this->_smarty->assign($name, $value);
    }
 
   /**
    * @param name string is our template file (.tpl)
    * this function can have any name, i called this way
    * to mirror smarty display function
    *
    * internally render will call _run 
    * which will display our template
    */
    public function display($name)
    {
        print parent::render($name);
    }
}

Now all the elements are in place and the connection Smarty – Zend Framework is done.
To test it you can create the following controller IndexController.php to be placed inside the /application/controller directory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class IndexController extends Zend_Controller_Action
{
    public function indexAction()
    {
        $view = Zend_registry::get('view');
        $view->display('index.tpl'); // index.tpl must be in our templates directory
    }
 
    /**
     * any path that is not catch by any of our actions
     * will be catched by this function by default
     * @param $methodName string
     * @param $args array
     */
    public function __call($methodName, $args)
    {
        $this->_view->display('404.tpl');
    }
 
}

The above represents the default controller with the default action, this, translates into:
http://example.com/index or just http://example.com/.

Controllers class names must end with the word Controller while actions must end with the word Action.
If we create a controller class called AdminController with an action called loginAction we could hit the loginAction function with this path: http://example.com/admin/login/

A note, regarding the installation of ZF:
I have placed the current ZF download (ZendFramework-1.5.1) inside my php directory then i have changed my php.ini include_path adding the whole path to the library directory /path/to/ZendFramework-1.5.1/libray.

One final note, all of the above can be achieved in different ways, some probably better, but this i think is a good starting point.


Leave a Comment or Trackback from your own site.

25 Responses to “Zend Framework and Smarty integration”

  1. Girija Laxmi Mishra says:

    it is showing error in require_once “Zend/Loader.php”; line
    Loader.php is not included.

  2. Hi Girija,
    thanks for your comment.

    Your need to include the Zend directory in php include path with the following code:

    define("SITE_ROOT", dirname($_SERVER['DOCUMENT_ROOT']));
     
    set_include_path(get_include_path().PATH_SEPARATOR
    				 .SITE_ROOT.'/lib'.PATH_SEPARATOR);

    if your Zend directory is in something like:

    /var/www/zend/lib/Zend

    than you do:

    set_include_path(get_include_path().PATH_SEPARATOR
                                       .'/var/www/zend/lib');
  3. rahul says:

    i hv downloaded your zip file and saved it into htdocs but its not running.it is showing some error like this

    Warning: require_once(Zend/Loader.php) [function.require-once]: failed to open stream: No such file or directory in C:\xampp\htdocs\zendsmarty\application\bootstrap.php on line 19

    Fatal error: require_once() [function.require]: Failed opening required ‘Zend/Loader.php’ (include_path=’.;C:\xampp\php\pear\;C:/xampp/application/lib;C:/xampp/application/models;C:/xampp/application/include;’) in C:\xampp\htdocs\zendsmarty\application\bootstrap.php on line 19

  4. Hi Rahul,

    thanks for you comment, the solution to your problem is in the comment above yours.

    You need to include the actual Zend directory (the one that contains the framework) in php include path.

    if your document root is C:\xampp\htdocs\zendsmarty
    and for example your Zend framework is in C:\xampp\htdocs\zendsmarty\lib\Zend
    then on top of your bootstrap.php file before the line with require_once('Zend/Loader.php');
    write the following code:

    set_include_path(get_include_path().PATH_SEPARATOR
                                       .'C:/xampp/htdocs/zendsmarty/lib');

    hope it helps, let me know if it fix the problem.

  5. rahul says:

    hi andrea

    thanx for d help but sorry my problem is not solved..i did what u said ..n hey i m new to this .so i am unable to find the problem too.
    now i am finding this error message.

    Warning: require_once(Zend/Loader.php) [function.require-once]: failed to open stream: No such file or directory in C:\xampp\htdocs\zendsmarty\application\bootstrap.php on line 21

    Fatal error: require_once() [function.require]: Failed opening required ‘Zend/Loader.php’ (include_path=’.;C:\xampp\php\pear\;C:/xampp/application/lib;C:/xampp/application/models;C:/xampp/application/include;;C:/xampp/htdocs/zendsmarty/lib’) in C:\xampp\htdocs\zendsmarty\application\bootstrap.php on line 21

    Thanx in advance

  6. Rahul,

    where is, in your file structure, your Zend Framework directory ?
    And could you copy and paste your bootstrap.php file as a reply to this comment ?

  7. rahul says:

    hi my file structure is the same as in your zip file.i just copied your folder and put it into my htdocs.this is my bootstrap file

    setViewScriptPathSpec(“:module/:controller/:action.:suffix”);
    // integrate smarty with Zend Framework
    $vr->setView(new SmartyView());
    $vr->setViewSuffix(‘tpl’);
    Zend_Controller_Action_HelperBroker::addHelper($vr);

    // set up error log
    // I am using apache error log file here, probably better to use your own log file
    $logger = new Zend_Log(new Zend_Log_Writer_Stream($config->site_root.’/error_log’));
    Zend_Registry::set(‘logger’, $logger);

    // Set the singleton instance of the front controller
    $front = Zend_Controller_Front::getInstance();
    // setting controllers
    $front->setModuleControllerDirectoryName(”);
    $front->addModuleDirectory($config->site_root.’/application/modules’);
    // OK, do your stuff, front controller
    $front->dispatch();

  8. Rahul,

    your bootstrap.php file should look like this:

    &lt;?php
    // in here we define the root directory of our site
    // is the directory above htdocs
    define("SITE_ROOT", dirname($_SERVER['DOCUMENT_ROOT']));
     
    /* Report all errors directly to the screen for simple diagnostics in the dev environment */  
    error_reporting(E_ALL);  
    ini_set('display_startup_errors', 1);  
    ini_set('display_errors', 1); 
     
    // Set our include path
    $include_path = get_include_path().PATH_SEPARATOR;
    $include_path .= SITE_ROOT.'/application/lib'.PATH_SEPARATOR;
    $include_path .= SITE_ROOT.'/application/models'.PATH_SEPARATOR;
    $include_path .= SITE_ROOT.'/application/include'.PATH_SEPARATOR;
    set_include_path($include_path);
     
    /* Set up autoload so we don't have to explicitely require each Zend Framework class */ 
    require_once "Zend/Loader.php"; 
    Zend_Loader::registerAutoload(); 
     
    // load config file
    $config = new Zend_Config(require 'config.php');
    Zend_Registry::set('config', $config);
     
    $vr = new Zend_Controller_Action_Helper_ViewRenderer();
    // important when developing using modules, so you can have various modules,setViewScriptPathSpec(":module/:controller/:action.:suffix");
    // integrate smarty with Zend Framework
    $vr-&gt;setView(new SmartyView());
    $vr-&gt;setViewSuffix('tpl');
    Zend_Controller_Action_HelperBroker::addHelper($vr);
     
    // set up error log
    // I am using apache error log file here, probably better to use your own log file
    $logger = new Zend_Log(new Zend_Log_Writer_Stream($config-&gt;site_root.'/error_log'));
    Zend_Registry::set('logger', $logger);
     
    // Set the singleton instance of the front controller
    $front = Zend_Controller_Front::getInstance(); 
    // setting controllers
    $front-&gt;setModuleControllerDirectoryName('');
    $front-&gt;addModuleDirectory($config-&gt;site_root.'/application/modules');
    // OK, do your stuff, front controller
    $front-&gt;dispatch(); 
    // for example an admin module, an e-commerce module and the default module
    $vr-&gt;setViewScriptPathSpec(":module/:controller/:action.:suffix");
    // integrate smarty with Zend Framework
    $vr-&gt;setView(new SmartyView());
    $vr-&gt;setViewSuffix('tpl');
    Zend_Controller_Action_HelperBroker::addHelper($vr);
     
    // set up error log
    // I am using apache error log file here, probably better to use your own log file
    $logger = new Zend_Log(new Zend_Log_Writer_Stream($config-&gt;site_root.'/error_log'));
    Zend_Registry::set('logger', $logger);
     
    // Set the singleton instance of the front controller
    $front = Zend_Controller_Front::getInstance(); 
    // setting controllers
    $front-&gt;setModuleControllerDirectoryName('');
    $front-&gt;addModuleDirectory($config-&gt;site_root.'/application/modules');
    // OK, do your stuff, front controller
    $front-&gt;dispatch();

    Your error is happening because PHP cannot find the Zend/Loader.php file in its class path.

    Inside the folder you downloaded Zend there are application, htdocs directories.
    For the whole thing to work if your $_SERVER['DOCUMENT_ROOT'] == 'C:/xampp/htdocs' then the application directory should be in 'C:/xampp/application'
    in your bootstrap.php file change the line: define("SITE_ROOT", dirname($_SERVER['DOCUMENT_ROOT']));
    with: define("SITE_ROOT", 'C:/xampp');

    Let me know if it helps.

  9. rahul says:

    hi andrea !! thanx for your help ..but sorry to say its still not working ;-)..i have done the things what you said..will u plz tell me where u hv defined $vr-&gt which u used in bootstrap file.it is showing something like this

    Parse error: syntax error, unexpected ‘&’ in C:\xampp\htdocs\zendsms\application\bootstrap.php on line 29
    THAnx

  10. Rahul,
    the code (bootstrap.php) in my previous comment is been parsed wrongly and angle brackets ‘>’ have been encoded, in other words this $vr-&gt should be $vr->

    I will send you the file directly by email.

  11. rahul says:

    HI Andrea !! as i said earlier m beginner in this field even i dn’t have enough knowledge about PHP..i really need your help to save my job..Plz help me out from this problem ;-)

    Thanx

  12. rahul says:

    Thanx for your help andrea .u r such a grt man. my loader problem is solve now.now i think there is minor problem n hope u’ll help me in this
    thanx

    Warning: SmartyView::require_once(C:/xampp/application/lib/Smarty-2.6.20/Smarty.class.php) [smartyview.require-once]: failed to open stream: No such file or directory in C:\xampp\htdocs\zendsms\application\include\SmartyView.php on line 10

    Fatal error: SmartyView::require_once() [function.require]: Failed opening required ‘C:/xampp/application/lib/Smarty-2.6.20/Smarty.class.php’ (include_path=’.;C:\xampp\php\pear\;C:/xampp/htdocs/zendsms/application/lib;C:/xampp/htdocs/zendsms/application/models;C:/xampp/htdocs/zendsms/application/include;’) in C:\xampp\htdocs\zendsms\application\include\SmartyView.php on line 10

  13. If you are using the bootstrap.php I sent you by email then change this line:

    define(“SITE_ROOT”, dirname($_SERVER['DOCUMENT_ROOT']));

    with this:

    define(“SITE_ROOT”, ‘C:/xampp/htdocs/zendsms’);

  14. rahul says:

    ohhhhh Thanx a lot andrea …really thanx a lot..may god bless u :-) its working now

  15. I am glad, you welcome.

  16. Thanks a lot andrea belvedere, I’m very much grateful. I’ve been trying about three weeks now to set up this frame work but i couldn’t until I came across your tutorials. Thanks a lot.

  17. Hello Mr. Andrea Belvedere could you please help me on how to develop a desktop application like the SPEED SIGN IN. looking forward to hear from you, thank you very much.

  18. Hi Augustine, thanks for your comments.
    About SSI the client side is an Internet Explorer plug-in, in other words a BHO (Browser Helper Object).
    A quick google search on “Browser Helper Object” should quickly point you to the right direction.

  19. Hello Mr. Andrea, Thanks very much.
    I’m going to work on it, I will contact you whenever I’m stack.
    Thank you, you are such a Great Man.

  20. jack says:

    Hi Andrea, thank you, great tutorial. However the modules no longer work for me…i mean when you navigate to site/modx…that modx is not rendered instead it will look in the templates folder. But when i remove the smarty integration it works fine.

  21. Hi Jack,
    thanks for you comment, did you try downloading the example from  http://www.andreabelvedere.com/coding/a-better-zend-framework-smarty-integration ? Is a much better approach then the example showed on this post.

    To be able to help you I need more details regarding your particular settings and bootstrap script.

  22. nicolas says:

    hey Andrea, i need your help with this one below.  is there something i have to change in code?thank in advance and regards.Fatal error: Uncaught exception ‘Zend_View_Exception’ with
    message ‘script ‘index.tpl’ not found in path
    (c:\\xampp\htdocs\zendsmarty\templates\)’ in
    C:\xampp\htdocs\zendsmarty\htdocs\Zend\View\Abstract.php:926
    Stack trace:
    #0 C:\xampp\htdocs\zendsmarty\htdocs\Zend\View\Abstract.php(829):
    Zend_View_Abstract->_script(‘index.tpl’)
    #1 C:\xampp\htdocs\zendsmarty\application\library\Smarty_View.php(60):
    Zend_View_Abstract->render(‘index.tpl’)
    #2
    C:\xampp\htdocs\zendsmarty\application\controllers\IndexController.php(7):
    Smarty_View->display(‘index.tpl’)
    #3 C:\xampp\htdocs\zendsmarty\htdocs\Zend\Controller\Action.php(513):
    IndexController->indexAction()
    #4
    C:\xampp\htdocs\zendsmarty\htdocs\Zend\Controller\Dispatcher\Standard.php(289):
    Zend_Controller_Action->dispatch(‘indexAction’)
    #5 C:\xampp\htdocs\zendsmarty\htdocs\Zend\Controller\Front.php(946):
    Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http),
    Object(Zend_Controller_Response_Http))
    #6 C:\xampp\htdocs\zendsmarty\application\bootstrap.php(62) in C:\xampp\htdocs\zendsmarty\htdocs\Zend\View\Abstract.php on line 926

  23. Ramya says:

    Hi Andrea,     Can u prepare one user screen with text fields , connecting with database with the integration of zend framework & smarty as using ur folder structure given in this siteRegards,Ramya

  24. latha says:

    Hi Andrea… i’m new to zend smarty concepts.i’m using MAC machine.i run the example “smarty zend integration” from this site, it works. But how can i create my own project in this environment? my doubt is how to i create my own controller from the terminal? for example, i want to create a table, then i use model to create Db table. how cal i create functions for the particular form and it’s operation? Please explain to me.

  25. tuba says:

    Although I am not going to use Smarty but still the tutorial helped me a lot to configure skin directories as per my choice. thank you!

Leave a Reply