Zend Framework: Using Smarty as template engine

Posted by Dmytro Shteflyuk on under PHP · Русский (203,762 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

st0ne_c0ld (Ru)
said on July 18, 2007 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 July 19, 2007 at 7:49 pm · Permalink

You can turn rendering off with:

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

It helped. Thanks krypin!

said on July 27, 2007 at 6:21 pm · Permalink

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

said on August 18, 2007 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 August 29, 2007 at 7:41 am · Permalink

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

said on September 11, 2007 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 October 5, 2007 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 February 5, 2008 at 11:06 pm · Permalink

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

Евгений @
said on February 15, 2008 at 4:27 pm · Permalink

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

Lance
said on April 17, 2008 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 April 28, 2008 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 April 29, 2008 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 July 4, 2008 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 August 18, 2008 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 October 1, 2008 at 4:36 pm · Permalink

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

said on October 1, 2008 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 March 10, 2009 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 March 17, 2009 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 March 17, 2009 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.

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.