Zend Framework: Using Smarty as template engine

Posted by Dmytro Shteflyuk on under PHP

Zend Framework’s View class has very bad capability for extending. It contains template variables but does not allow to access them, it has array with different pathes (templates, filters), but does not allow to add another type or access them. Therefor only way to use Smarty with Zend Framework is to abandon Zend_View and manipulate Smarty object directly.

First we need to create Smarty object. I do it in index.php after including Zend.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
require('Zend.php');

include 'smarty/Smarty.class.php';
$smarty = new Smarty();
$smarty->debugging = false;
$smarty->force_compile = true;
$smarty->caching = false;
$smarty->compile_check = true;
$smarty->cache_lifetime = -1;
$smarty->template_dir = 'resources/templates';
$smarty->compile_dir = 'resources/templates_c';
$smarty->plugins_dir = array(
  SMARTY_DIR . 'plugins',
  'resources/plugins');

I don’t like global variables therefor I’ve added Smarty object into Zend Framework’s registry:

1
Zend::register('smarty', $smarty);

Using is pretty simple. Just initialize Smarty variables in your Controller class and display template:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class IndexController extends Zend_Controller_Action
{
  function index()
  {
    $smarty = Zend::registry('smarty');
    $smarty->assign('title', 'Test');
    $smarty->display('index.tpl');
  }

  function noRoute()
  {
    $smarty = Zend::registry('smarty');
    $smarty->display('error404.tpl');
  }
}

As you can see Smarty integration with Zend Framework is very simple task. Zend_View has ability to use your own filters and helper functions, but with Smarty you don’t need them because Smarty has its own plugins, filters, modifiers. Just forget about Zend_View and use best template engine for PHP in the world!

Books recommended

54 Responses to this entry

Subscribe to comments with RSS

Holografix
said on March 10th, 2006 at 18:45 · Permalink

Nice Dmytro :)

1
echo $smarty->display('index.tpl');

Wouldn’t it be just $smarty->display('index.tpl') ? or echo $smarty->fetch('index.tpl') ?

Best regards
holo

said on March 10th, 2006 at 18:47 · Permalink

Thanks, you are right :-) I’ll fix it now.

Gregory Szorc
said on March 16th, 2006 at 05:58 · Permalink

I already did something like this for a project I am working on. My solution was to create a class that extended Zend_View_Abstract. That way, you can still use all the methods with the Zend View API. My basic implementation is as follows:

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
class My_Smarty_View extends Zend_View_Abstract
{
  private $_smarty;
 
  public function __construct($config = array()) {
    parent::__construct($config);
   
    $this->_smarty = new Smarty();
   
    //i have a config object for my application
    $root = Zend::registry('config')->get('root', 'project');
   
    $this->_smarty->template_dir  = $root.'application/views/';
    $this->_smarty->compile_dir = $root.'tmp/templates_c/';
    $this->_smarty->config_dir = $root.'tmp/configs/';
    $this->_smarty->cache_dir = $root.'tmp/cache/';
   
  }
  public function assign($spec) {
    $args = func_get_args();
    call_user_func(array('parent', 'assign'), $args);
   
    if (is_string($spec)) {
      $arg = func_get_arg(1);
      $this->_smarty->assign($spec, $arg);
    } elseif (is_array($spec)) {
      foreach ($spec as $k=>$v) {
      $this->_smarty->assign($k, $v);
      }
    }
    else {
      throw new Zend_View_Exception('assign() expects a string or array');
    }
  }
}

Then in my controllers, I can just do a Zend::registry('view'), $view->assign('foo', 'bar') and $view->render('foo')

said on March 16th, 2006 at 07:53 · Permalink

Thanks for comment, Gregory

I tried to create something similar but I don’t see advantages of this approach. For different projects I need to setup different directories with plugins (for example if I use my own plugins), templates (if I use themes-based architecture). You’ve extended Zend_View_Abstract but you don’t use almost all its functionality. I don’t think this is a good object-oriented practice – to extend but not to use methods of base class.

said on March 17th, 2006 at 05:31 · Permalink

I’ve been playing with this too, but it seems a wee bit wasteful to create a Smarty object if you don’t know if you’ll be needing it or not (for example, the index controller may process a form, or output a file without ever needing to have the Smarty class instantiated).

I take your point that it also not very clean to extend a class that is not truly a descendant, but it may be more prudent to create a factory class for View that can select a backend on-the-fly (e.g. a Zend_View or a Smarty_View). Then that class can create the backend object only when a render() method is called to save resources.

said on March 17th, 2006 at 15:28 · Permalink

Simon, you are right with inefficiency of creating Smarty object without knowing is it neccessary to generate responce. There is possible solution is to create factory object which will construct Smarty object on demand. But both methods has their own pros and cons and I don’t know which method is more preferable. I’ll think over your idea on weekend :-)

said on March 20th, 2006 at 11:51 · Permalink

Hi,

I have been reading through your proposal and made up my mind. In a web application, I would like to use some layouts containing elements like navigation, news..,and of course the content of the actual request.

How would you implement layouts in the Zend Framework?

Without using Smarty I used the following method:

in Controller:

1) check request variables, authentication..

2) get required data from DB

3) use Zend_View to render the modules and the content for the actual request, save them as variables in the $viewObject:

1
2
3
$view->module_news = $view->render('modules/news'); // news
$view->module_navigation = $view->render('modules/navigation');  // navigation
$view->content = $view->render('action.php');  // content

4) render and output the desired layout for the action:

1
echo $view->render('layouts/default.php');

In the layout template placeholder variables for content and modules are set:

1
2
3
$this->modules_news
$this->content
$this->modules_navigation

How would do this with Smarty?

said on March 20th, 2006 at 12:04 · Permalink

Hello, fjonzo

With Smarty you can use layouts in following way:

1) check request variables, authentication..

2) get required data from DB

3) Assign all required variables to Smarty object.

1
2
3
4
5
6
7
// Common variables for all pages.
// Their can be setted up in the index.php file.
$smarty->assign('news', $newsData);
$smarty->assign('navigation', $navigationData);
// content_template means name of the content template file.
// Usually I've assigned this variable in the controller file.
$smarty->assign('content_template', 'about.tpl');

4) In main layout (layouts/default.tpl) you can use {include file=""} construction

1
2
3
<div id="navigation">{include file="modules/navigation.tpl"}</div>
<div id="news">{include file="modules/news.tpl"}</div>
<div id="content">{include file=$content_template}</div>

5) Render main layout

1
$smarty->display('layouts/default.tpl');
said on March 21st, 2006 at 14:41 · Permalink

Thanks a lot,

I played around with Smarty and ZF and Smarty seems to be many times superior to Zend_View. But one thing that worries me is stepping out of the framework.

Norm 2782
said on March 22nd, 2006 at 16:10 · Permalink

I wonder why the Zend Framework would bother writing a new template engine, instead of:
1) using Smarty 2.x
2) helping develop Smarty 3.x (if there’s gonna be a 3.x…)

Shammai Ellman
said on March 28th, 2006 at 20:44 · Permalink

I have the same question as Norm2782.
Why isn’t Zend integrating Smarty into their framework.
I have developed my own database driven framework that works just like the Zend Framework even before ZF came out. I use Smarty as the template engine because it is fast and stable. I am glad to see that others are interested in incorporating Smarty into a standard framework and I hope Zend takes the hint.
Perhaps we can start our own extension group for the Zend Framework and try to get Zend to incorporate it.

said on March 29th, 2006 at 11:43 · Permalink

Norm2782, Shammai, thanks for comments

As I understood, Zend Framework team does not want to relay on third-party components. They are providing a simplest solution (but very powerfull and efficient) and everyone can extend or replace any part of system with his own parts.

said on April 9th, 2006 at 19:38 · Permalink

[…] Why use a template engine like Smarty or Template_Lite? When using the MVC pattern is seems to fit well. This article here provides a good example using Smarty with the Zend Framework. […]

said on April 26th, 2006 at 10:15 · Permalink

Идея не нова, но многим будет это полезно. Автору респект

said on April 26th, 2006 at 11:00 · Permalink

Very nice, Dmytri! Thanks for useful introduction into smarty+ZFW!

BTW: will recommend this blog to my friends.

OpenMacNews
said on May 2nd, 2006 at 02:48 · Permalink

hi Dmytri,

i’m returning to Smarty after a disappointing foray through some CMSs — and having been trying to get my head around ZF. thx! for a great intro to Smarty+ZF!

i’ve also just read Ralf Egger’ts post:

INTEGRATING SMARTY WITH THE ZEND FRAMEWORK
http://devzone.zend.com/node/view/id/120

which he claims as being ‘inspired’ by *this* …

i’m hoping that you might be able to close-the-loop and comment on some of his effort there in light of your own thinking.

thx!

richard

said on May 27th, 2006 at 11:56 · Permalink

>Как можно заметить, интеграция Smarty с Zend Framework – довольно >простая задача.

Після циєї статті ц дійсно просто. Дякую!

Why don't you
said on June 7th, 2006 at 13:56 · Permalink

just admit that Zend sucks and use PhpED instead?
This one manages Smarty right.

said on July 4th, 2006 at 07:51 · Permalink

what does smarty do with the zend framework ?
zend framework is a mvc framework, it has a viewer and a controller … is enough to separate bussines logic from presentation logic, smarty is useles, unles you want users to submit their templates, also in this case you have alternatives… using apache htaccess to limit some of php functions.
Smarty the interpreted language inside an interpred language (PHP), usless piece of code … one question bothers me … why are so many people use this useles thing anyway ? ….oh right … mediocre programmers …. a lot of php programmers are beginers …. but they must evolve as programmers … or maybe just learn how to program … not to write code … this means that you need to know more than a programming language …
Anyway, evolve … smarty people …

kabom!
said on July 17th, 2006 at 02:59 · Permalink

Gigel its all about how the code looks in smarty templates :)

Gerrit
said on February 4th, 2007 at 23:46 · Permalink

Gigel,
its not about mediocre programmers is about separating concerns.
Designers work on layout, programmers work on code. I know many programmers who cannot do a descent looking layout to save themselves and a number of web designers who cannot program.
When you work on a project that involves more than one person you may understand.

said on March 23rd, 2007 at 17:47 · Permalink

[…] Smarty & ZendFramework Posted Marzo 12, 2007 In attesa che il ZendFramework arrivi alla versione stabile 1.0 ecco un ottimo e semplice modo per integrare il template engine Smarty nel modello MVC proposto da Zend (ho preso spunto da questo articolo). […]

said on March 24th, 2007 at 11:42 · Permalink

Note that it is possible to use Zend_View helpers in Smarty too. All you need to do is this:

1
$smarty->assign("helpers", new Zend_View);

And then you can use it in your templates:

1
{$helpers->formText("field1")}
Max
said on March 24th, 2007 at 19:09 · Permalink

Добрый день. Меня заинтересовала ваша публикация,в ближайшее время на моем сайте откроется большое количество разделов, в одном из которых я хотел бы разместить данную публикацию. Можно ли это сделать и на каких условиях? Если можно – то на [email protected], с уважением Максим.

said on March 25th, 2007 at 00:53 · Permalink

Можно разместить со ссылкой на оригинал :-)

CMS
said on June 6th, 2007 at 10:14 · Permalink

Должен сказать спасибо, подобная задача стояла, решение нашел у вас :)

mel
said on July 10th, 2007 at 13:30 · Permalink

hi,
I am a novice when it comes to Zend Framework along with smarty. The question that i’m posing now may seem very silly.But the thing that confuses me is:

require(‘Zend.php’);

what is the content of this file?
why is it required?

One more question is, since i am a novice in this, which website other than http://www.zend.com can i visit to understand both zend and smarty, or books i can purchase to learn more on this topic.
Thanks.

st0ne_c0ld (Ru)
said on July 18th, 2007 at 17:57 · Permalink

Единственная адекватная статья, из которой(правда только после второго прочтения) ставноится понятно, как их вместе готовить. Респект.

The one disadvantage I found is I still have to create files like:
/views/scripts/blabla1/blabla1.phtml
Because the Zend_Controller_Front throws exceptions when file like this don’t exists.

krypin
said on July 19th, 2007 at 19:49 · Permalink

You can turn rendering off with:

1
$frontController->setParam('noViewRenderer', true);
st0ne_c0ld (Ru)
said on July 20th, 2007 at 09:58 · Permalink

It helped. Thanks krypin!

said on July 27th, 2007 at 18:21 · Permalink

Три раза подряд прочел… Интересное решение

said on August 18th, 2007 at 00:57 · Permalink

Good article and start point.
I successfully run with the latest Zend Framework 1.0.1 and latest Smarty 2.6.18.

said on August 29th, 2007 at 07:41 · Permalink

Сегодня прикрутил Smarty к ZF, решил посмотреть другие решения. Автор молодец. Smarty рулит.

said on September 11th, 2007 at 16:07 · Permalink

Hi fellows,
it is interesting to see the discussion.
I thing it’s more clean to use smarty on his own. So you are also better prepared to upcomming ZF’s.
BTW. Where would images and CSS be stored best? in template/xxx oder in a folder by itsself?

said on October 5th, 2007 at 20:12 · Permalink

[…] conclusión que acaba pareciendo código spaghetti. Eso sí,parece que se puede utilizar Smarty como motor de plantillas, con el que en su día no estuve demasiado cómodo trabajando y no me […]

said on February 5th, 2008 at 23:06 · Permalink

[…] Втория вариант е относително елементарен, което и ме накара да се спра на него. На мен лично нещо не ми проработи идеята със Zend::registry, затова предпочетох да коментирам реда и да си дефинирам променливата като глобална. От там нататък всичко беше 6+ и нямаше никакви проблеми. Ето как трябва да изглежда един примерен IndexController: PHP: […]

Евгений
said on February 15th, 2008 at 16:27 · Permalink

Спасибо автору!
Именно этот подход я использую уже несколько месяцев, однако все это время меня не оставляет в покое тот факт, что было бы все-таки удобнее реализовать что-то вроде smarty-авторендеринга, что бы по умолчанию происходила обработка конкретного шаблона, как это делается с phtml. Нет ли у кого подобных наработок?

Lance
said on April 17th, 2008 at 20:03 · Permalink

Repeating Mel’s post becauase-I don’t understand this line either:

Require ‘Zend.php’;

I can’t find any Zend.php in the Zend framework libraries so I’m trying to figure out what was meant by this line also.

guai
said on April 28th, 2008 at 22:18 · Permalink

Всем привет.

Напэашпил файлик, думаю будет полезен собравшимся.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
require_once 'Zend/View.php';

class View extends Zend_View
{
    protected $_smarty;
    public $_useSmarty=true;

    protected function _run()
    {
        if($this->_useSmarty):
            if(!isset($this->_smarty))
            {
                require_once SMARTY_DIR.'Smarty.class.php';
                $this->_smarty=new Smarty();
                include MY_SMARTY_CFG_FILE;
            }
            $this->_smarty->assign($this->getVars());
            $this->_smarty->display(ROOT_DIR.func_get_arg(0));
        else:
            $args=func_get_args();
            call_user_method_array ('_run',$parent=parent,$args);
        endif;
    }
}

Так подрубается:

1
2
3
4
5
6
7
8
9
10
chdir('..');
require_once 'config.php';
require_once 'view.php';

require_once 'Zend/Controller/Front.php';
require_once 'Zend/Controller/Action/Helper/ViewRenderer.php';

Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_ViewRenderer(new View()));

Zend_Controller_Front::run('app/ctrls');

Так отрубается:

1
2
3
4
5
6
7
8
9
10
11
12
13
require_once 'Zend/Controller/Action.php';

class IndexController extends Zend_Controller_Action
{
    public function init()
    {
    $this->view->_useSmarty=false;
    }

    public function indexAction()
    {
    }
}

Думаю понятно, что к чему.
Зендовский код не загажен ничем, специфичным для Смарти, шаблоны лежат где и были по дефолту, тока на смарти.
Кстати, мона без палева довернуть определение движка шаблонов по расширению файла. Тока не знаю нафига.
А кэширование имхо лучше юзать зэндовское, оно матёрее.

ЗЫЖ это под 1.5.1

guai
said on April 29th, 2008 at 01:13 · Permalink

Исчо раз фсем привет.

Кой-чего переправил по сравнению с предыдущем постом:

view.php:

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
require_once 'Zend/View.php';

class View extends Zend_View
{
    protected $_smarty;
    public $_useSmarty=true;

    protected function _run()
    {
        if($this->_useSmarty):
            if(!isset($this->_smarty)) {
                require_once SMARTY_DIR.'Smarty.class.php';
                $this->_smarty=new Smarty();
                include MY_SMARTY_CFG_FILE;
            }
            $this->_smarty->clear_all_assign();
            $this->_smarty->assign($this->getVars());
            $this->_smarty->assign_by_ref('THIS',$this);
            $this->_smarty->display(ROOT_DIR.func_get_arg(0));
        else:
            $args=func_get_args();
            call_user_method_array ('_run',$parent=parent,$args);
        endif;
    }
}

config.php:

1
2
3
4
5
6
7
//set_include_path(realpath('..'));
define('DS',DIRECTORY_SEPARATOR);

// SMARTY
define('ROOT_DIR',realpath('.').DS);
define('SMARTY_DIR',ROOT_DIR.'smarty'.DS);
define('MY_SMARTY_CFG_FILE',ROOT_DIR.'smarty.cfg.php');

smarty.cfg.php:

1
2
3
4
5
6
$this->_smarty->plugins_dir=array(
    SMARTY_DIR.'plugins',
    ROOT_DIR.'my_smarty_plugins');
$this->_smarty->template_dir=__(ROOT_DIR.$this->getScriptPath(''));
$this->_smarty->compile_dir=ROOT_DIR.'tmp';
$this->_smarty->force_compile=true;

Самое интересное:
наколбасил свой плугин для смарти:
файл my_smarty_plugins/compiler.zf:

1
2
3
4
function smarty_compiler_zf($tag_attrs, &$compiler)
{
    return "\$THIS=\$this->_tpl_vars['THIS'];$tag_attrs;";
}

И вот для чего это фсё делалось:
файл \app\views\scripts\layout.phtml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html
   PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
    {zf echo $THIS->headTitle() }
    {zf echo $THIS->headScript() }
    {zf echo $THIS->headStyle() }
</head>
<body>
    {include file='footer.phtml'}

    <div id="nav">{zf echo $THIS->placeholder('nav') }</div>

    <div id="content">{zf echo $THIS->layout()->content }</div>

    {include file='header.phtml'}
</body>
</html>

Матёро, не?

said on July 4th, 2008 at 13:15 · Permalink

How could I pass form element with server side validation functions through smarty?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$this->setName('frmDrawing');
$this->setName('frmDrawing');
$this->setView(new Zend_View());
        $this->getView()->headScript()->appendFile('/zenddemo/public/js/Zend/Form.js');
       
$id = new Zend_Form_Element_Hidden('id');
$name = new Zend_Form_Element_Text('name');
$drawing_name->setLabel('Drawing Name')
           ->setRequired(true)
           ->addFilter('StripTags')
           ->addFilter('StringTrim')
           ->addValidator('NotEmpty');
           
$submit = new Zend_Form_Element_Submit('submit');
$submit->setAttrib('id', 'submitbutton');
        $this->addElements(array($id, $name, $submit));

With default template we can create form element in model and we can pass to template.

1
<?php echo $this->form ;?>

Through above code we can show compete form and on submit method we can also check server validation which we provide in model declaration.

Is any similar way available through smarty? from where we can directly assign server validation function in model and on submit it will execute that function and return appropriate value.

Thanks

said on August 18th, 2008 at 22:19 · Permalink

Hi Amit Shah, I found this solution at Advanced Features/Objects, may be it will be useful for you.

I register the php object with an smarty method

1
2
// registering the object (will be by reference)
$smarty->register_object('foobar',$myobj);

and then use it on .tpl file like this

1
{foobar->method}

Bye

clockworkbird
said on October 1st, 2008 at 16:36 · Permalink

Использование Smarty целесообразно только в случае переноса готового проекта, использующего Smarty на ZF. Если говорить о новом проекте, то используйте Zend_Layout и Zend_View и забудьте о “лучшем шаблонном движке для PHP в мире”. Безусловно Смарти таковым и является, но при использовании ZF необходимость в нем просто отпадает.

said on October 1st, 2008 at 19:49 · Permalink

Integrating Smarty with the Zend Framework…

Ralf Eggert wrote:

” Inspired by this article I started to play around a bit to integrate the Smarty template engine into the Zend Framework. My ambition was to minimize the required code in the controller actions but stay close to the given Zend_V…

More comments: 1 2

Comments are closed

Comments for this entry are closed for a while. If you have anything to say – use a contact form. Thank you for your patience.