The best Smarty + Zend View Helpers solution!

csdn的blog真垃圾, 我费了一个下午翻译出来的文章, 结果保存的时候丢了, 白费功夫了, 算了,只接转帖英文原文吧, 顺便强烈BS一下CSDN。

The best Smarty + Zend View Helpers solution!

Tags: , The solutions in this post will be based on the SmartyView class, introduced in , so check it out if you feel it might help you understand this one.

Originally posted in my old blog at My Opera

Coming on again with the Smarty and Zend View related articles, let's this time take a look at how to get Zend's View Helpers running with Smarty.

Other examples for this that I have seen use a syntax like this: {helper helper=Url p='array(something)' p2=stuff}, which is kind of ugly and the array parsing is done with eval, and we know that
Eval is Evil.

Wouldn't a more elegant solution let you use helpers just like you use Smarty plugins? In the style of just typing the name of the helper and simple parameters? Let's see how to make that happen!

 

The solutions in this post will be based on the SmartyView class, introduced in Smarty + Zend View, take three, so check it out if you feel it might help you understand this one.

Starting


So, we want to have a nice syntax for calling Zend's viewhelpers from Smarty templates. First, we have some issues we have to find solutions for:

  • Smarty does not “know” about View Helpers
  • View helpers may need arrays or associative arrays as parameters. Smarty has no support for doing this out-of-the-box

    The first one is quite simple to solve: Since the Zend_View class knows about viewhelpers and can call them, the SmartyView class also does that. Since we need to create a new class based on Smarty anyway, we can add a method for saving the View instance to it so that the new Smarty class can also call view helpers.

    The second one needs more work. Since Smarty's syntax for passing parameters to functions differs a lot from the typical syntax, we need to think of a nice Smarty-like way of passing arrays and associative arrays as parameters. We also need to dig in the Smarty compiler class which converts the Smarty templates into PHP code. Isn't it great that I did the digging for you and you can just read about it here? :up:

    For the syntax, I decided on this:
{helperName param=foo arr=bar arr=baz assoc.one=test assoc.two=hello}
This would be the same as writing this in normal Zend_View templates:
$this->helperName('foo', array('bar','baz'), array('one' => 'test', 'two' => 'hello');


I think this is very Smarty-like and at least I like the fact that I can call the parameters whatever I want as I could use it to make it more obvious what the parameters will change. Consider the following:

{makeList source=$myData sortBy=name}
or something like
{makeList $myData name}

Extending Smarty


So, let's first extend the Smarty class to add our shiny new features!

I'm going to call the class SmartyAdvanced, since I'm bad at making up good catchy names. Feel free to suggest anything better ;)

So as we learnt above, we need to add some methods into the Smarty class, namely a method for saving a Zend_View instance into it and a method for calling View Helpers from the compiled templates.

Thus…

<? php
require_once   " smarty/libs/Smarty.class.php " ;
 
class  SmartyAdvanced  extends  Smarty
{
  
private   $_zendView ;
 
  
public   function  __construct()
  {
    parent
:: __construct();
    
$this -> compiler_class  =   " SmartyAdvanced_Compiler " ;
  }
 
  
public   function  setZendView(Zend_View_Abstract  $view )
  {
    
$this -> _zendView  =   $view ;
  }
 
  
public   function  callViewHelper( $name , $args )
  {
    
$helper   =   $this -> _zendView -> getHelper( $name );
 
    
return   call_user_func_array ( array ( $helper , $name ) , $args );
  }  
}
?>


So here's our brand new SmartyAdvanced class. The constructor calls the Smarty class' constructor and sets the compiler class name to SmartyAdvanced_Compiler… we'll look at it a bit later.

The other two functions serve as the view helper methods. setZendView should be pretty obvious, and callViewHelper simply gets the view helper from the Zend_View class and calls it with the parameters provided.

Extending Smarty_Compiler


As you know, Smarty templates are compiled into PHP code to speed up the execution. Since some of the things we do are tampering with very internal things in Smarty, like the syntax, we need to extend the compiler to do things our way and not their way.

So we need to modify the compiler to understand our custom syntax and to make it so that Smarty will try to call View Helpers if it can't parse a template function call with its own functions.

There's one thing I want to point out before the code: In the constructor, the Zend_View object is specified by just making a new Zend_View instance. This is bad, but necessary.

Unless we want to go in and modify Smarty's code, possibly breaking our code in the case of an update, we have to instantiate a view here. A better option would be to use a view factory,
as shown in one of my previous posts.


    
    
<? php
require_once   " smarty/libs/Smarty_Compiler.class.php " ;
 
class  SmartyAdvanced_Compiler  extends  Smarty_Compiler
{
  
private  $_ zendView ;
 
  
public   function  __construct()
  {
    parent
:: __construct();
    
$this -> _zendView  =   new  Zend_View();
  }
 
  
function  _compile_compiler_tag( $tagCommand ,   $tagArgs ,   & $output )
  {
    
// We first try to use Smarty"s own functionality to parse the tag
     $found   =  parent :: _compile_compiler_tag( $tagCommand , $tagArgs , $output );
 
    
if ( ! $found )
    {
      
try
      {
        
// Check if helper exists and create output
         $helper   =   $this -> _zendView -> getHelper( $tagCommand );
 
        
$helperArgs   =   array ();
 
        
if ( $tagArgs   !==   null )
        {
          
// Start parsing our custom syntax
           $params   =   explode ( "   " , $tagArgs );
          
foreach ( $params   as   $p )
          {
            
// Split each key=value pair to vars
             list ( $key , $value =   explode ( " = " , $p , 2 );
            
$section   =   "" ;
 
            
// If there"s a dot in the key, it means we
            //need to use associative arrays

             if ( strpos ( " . " , $key !=   - 1 )
              
list ( $key , $section =   explode ( " . " , $key );
 
            
// Use Smarty"s own functions to parse the value
            //so that if there"s a variable, it gets changed to
            //properly point at a template variable etc.

             $value   =   $this -> _parse_var_props( $value );
 
            
// Put the value into the arg array
             if ( $section   ==   "" )
            {
              
if ( array_key_exists ( $key , $helperArgs ))
              {
                
if ( is_array ( $helperArgs [ $key ]))
                  
$helperArgs [ $key ][]  =   $value ;
                
else
                  
$helperArgs [ $key =   array ( $helperArgs [ $key ] , $value );
 
              }
              
else
                
$helperArgs [ $key =   $value ;
            }
            
else
            {
              
if ( ! is_array ( $helperArgs [ $key ]))
                
$helperArgs [ $key =   array ();
 
              
$helperArgs [ $key ][ $section =   $value ;
            }
          }
        }
 
        
// Save the code to put to the template in the output
         $output   =   " <?php echo $this->callViewHelper( " $tagCommand " ,array( " . $this -> _createParameterCode( $helperArgs ) . " )); ?> " ;
        
$found   =   true ;
      }
      
catch (Zend_View_Exception  $e )
      {
        
// Exception means the helper was not found
         $found   =   false ;
      }
    }
 
    
return   $found ;
  }
 
  
// This function creates the code for the helper params
   private   function  _createParameterCode( $params )
  {
    
$code   =   "" ;
 
    
$i   =   1 ;
    
$pCount   =   count ( $params );
    
foreach ( $params   as   $p )
    {
      
if ( is_array ( $p ))
        
$code   .=   " array( " . $this -> _createParameterCode( $p ) . " ) " ;
      
else
        
$code   .=   $p ;
 
      
if ( $i   !=   $pCount )
        
$code   .=   " , " ;
 
      
$i ++ ;
    }
 
    
return   $code ;
  }
}
?>




Okay so that's a bit more than previously. With that, we're all done for Smarty mods!




Using the new classes



Using the new classes is pretty easy. We need to do a small change to the SmartyView class' constructor. Replace…

$this -> _smarty  =   new  Smarty();

with the following

if ( isset ( $config [ " smartyClass " ]))
  
$this -> _smarty  =   new   $config [ " smartyClass " ];
else
  
$this -> _smarty  =   new  Smarty();


Doing this will enable us to pass the Smarty class we want to use as a parameter.

Like this…

$view   =   new  SmartyView( array (
        
" compileDir "   =>   " ./template_c " ,
        
" helperPath "   =>   " ./application/views/helpers " ,
        
" pluginDir "   =>   " ./plugins " ,
        
" smartyClass "   =>   " SmartyAdvanced "
        ));
 
$view -> getEngine() -> setZendView( $view );

All that is needed is to give the new SmartyAdvanced class name as the smartyClass parameter for the SmartyView configuration. Then we need to pass the view instance to setZendView so that Smarty will be able to call helpers.

Conclusion


Despite Smarty's code being not very modification/extension-friendly, it's possible to add a lot of interesting features to it as you can see. With these extensions, using View Helpers with Smarty as the template engine is much nicer in my opinion.

The code for SmartyAdvanced and SmartyAdvanced_Compiler can be found
here.


数据治理是确保数据准确性、可靠性、安全性、可用性和完整性的体系和框架。它定义了组织内部如何使用、存储、保护和共享数据的规则和流程。数据治理的重要性随着数字化转型的加速而日益凸显,它能够提高决策效率、增强业务竞争力、降低风险,并促进业务创新。有效的数据治理体系可以确保数据在采集、存储、处理、共享和保护等环节的合规性和有效性。 数据质量管理是数据治理中的关键环节,它涉及数据质量评估、数据清洗、标准化和监控。高质量的数据能够提升业务决策的准确性,优化业务流程,并挖掘潜在的商业价值。随着大数据和人工智能技术的发展,数据质量管理在确保数据准确性和可靠性方面的作用愈发重要。企业需要建立完善的数据质量管理和校验机制,并通过数据清洗和标准化提高数据质量。 数据安全与隐私保护是数据治理中的另一个重要领域。随着数据量的快速增长和互联网技术的迅速发展,数据安全与隐私保护面临前所未有的挑战。企业需要加强数据安全与隐私保护的法律法规和技术手段,采用数据加密、脱敏和备份恢复等技术手段,以及加强培训和教育,提高安全意识和技能水平。 数据流程管理与监控是确保数据质量、提高数据利用率、保护数据安全的重要环节。有效的数据流程管理可以确保数据流程的合规性和高效性,而实时监控则有助于及时发现并解决潜在问题。企业需要设计合理的数据流程架构,制定详细的数据管理流程规范,并运用数据审计和可视化技术手段进行监控。 数据资产管理是将数据视为组织的重要资产,通过有效的管理和利用,为组织带来经济价值。数据资产管理涵盖数据的整个生命周期,包括数据的创建、存储、处理、共享、使用和保护。它面临的挑战包括数据量的快速增长、数据类型的多样化和数据更新的迅速性。组织需要建立完善的数据管理体系,提高数据处理和分析能力,以应对这些挑战。同时,数据资产的分类与评估、共享与使用规范也是数据资产管理的重要组成部分,需要制定合理的标准和规范,确保数据共享的安全性和隐私保护,以及建立合理的利益分配和权益保障机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值