Zend Framework: Using Smarty as template engine

(PHP) · Русский (139,606 views)

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 2006-03-10 at 6.45 pm · 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 2006-03-10 at 6.47 pm · Permalink

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

Gregory Szorc @
said on 2006-03-16 at 5.58 am · 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 2006-03-16 at 7.53 am · 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 2006-03-17 at 5.31 am · 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 2006-03-17 at 3.28 pm · 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 :-)

fjonzo @
said on 2006-03-20 at 11.51 am · 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 2006-03-20 at 12.04 pm · 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');
fjonzo @
said on 2006-03-21 at 2.41 pm · 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 2006-03-22 at 4.10 pm · 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 2006-03-28 at 8.44 pm · 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 2006-03-29 at 11.43 am · 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 2006-04-09 at 7.38 pm · 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 2006-04-26 at 10.15 am · Permalink

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

said on 2006-04-26 at 11.00 am · Permalink

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

BTW: will recommend this blog to my friends.

OpenMacNews @
said on 2006-05-02 at 2.48 am · 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 2006-05-27 at 11.56 am · Permalink

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

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

Why don't you
said on 2006-06-07 at 1.56 pm · Permalink

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

Gigel @
said on 2006-07-04 at 7.51 am · 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 2006-07-17 at 2.59 am · Permalink

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

Gerrit
said on 2007-02-04 at 11.46 pm · 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 2007-03-23 at 5.47 pm · 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 2007-03-24 at 11.42 am · 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 2007-03-24 at 7.09 pm · Permalink

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

said on 2007-03-25 at 12.53 am · Permalink

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

CMS
said on 2007-06-06 at 10.14 am · Permalink

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

mel @
said on 2007-07-10 at 1.30 pm · 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 2007-07-18 at 5.57 pm · 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 2007-07-19 at 7.49 pm · Permalink

You can turn rendering off with:

1
$frontController->setParam('noViewRenderer', true);
st0ne_c0ld (Ru)
said on 2007-07-20 at 9.58 am · Permalink

It helped. Thanks krypin!

said on 2007-07-27 at 6.21 pm · Permalink

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

said on 2007-08-18 at 12.57 am · 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 2007-08-29 at 7.41 am · Permalink

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

said on 2007-09-11 at 4.07 pm · 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 2007-10-05 at 8.12 pm · 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 2008-02-05 at 11.06 pm · Permalink

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

Евгений @
said on 2008-02-15 at 4.27 pm · Permalink

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

Lance
said on 2008-04-17 at 8.03 pm · 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 2008-04-28 at 10.18 pm · 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 2008-04-29 at 1.13 am · 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 2008-07-04 at 1.15 pm · 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

arbol @
said on 2008-08-18 at 10.19 pm · 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 2008-10-01 at 4.36 pm · Permalink

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

said on 2008-10-01 at 7.49 pm · 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…

zendrej @
said on 2009-03-10 at 12.56 pm · Permalink

I could not find ‘zend.php’ and failed to include this. I would be thankful if anyone can help me

The below index.phtml is not rendering values too

1
<?=$this->val?>

Regards,
rej

said on 2009-03-17 at 7.29 pm · Permalink

This is a little outdated…

It works… but instead of using Zend::register(’smarty’, $smarty) you should use Zend_Registry::set(’smarty’, $smarty) and instead of using Zend::registry(’smarty’) you should use Zend_Register::get(’smarty’). And ofcourse you must: require_once ‘Zend/Registry.php’ in the bootstrap.

said on 2009-03-17 at 7.33 pm · Permalink

I’m against this method of incorporating smarty into ZF. This method assumes you will be rendering a smarty view with each action.

Also… this will produce an error with current versions on ZF that automatically render a view at the end of an action. With this method you must call $this->_helper->viewRenderer->setNoRender(true) in every action to disable zend from attempting to render a default view after the smarty display.

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.