smarty的插件文件是怎么引入的

欣儿 发布于 2013/12/08 00:26
阅读 1K+
收藏 2
smarty的插件文件是怎么引入的?怎么做到的有插件的方法时就引入该方法所在的插件文件,没有的就不引入?
加载中
1
南湖船老大
南湖船老大

引用来自“宏哥”的答案

引用来自“南湖船老大”的答案

引用来自“欣儿”的答案

引用来自“南湖船老大”的答案

/**
     * Takes unknown classes and loads plugin files for them
     * class name format: Smarty_PluginType_PluginName
     * plugin filename format: plugintype.pluginname.php
     *
     * @param  string $plugin_name class plugin name to load
     * @param  bool   $check       check if already loaded
     * @return string |boolean filepath of loaded file or false
     */
    public function loadPlugin($plugin_name, $check = true)
这个函数在具体的执行过程中是怎么用的?比如,知道一个插件的方法会用,然后是怎么找出这个插件方法的文件,并引入

。。。。

插件的命名和存放路径都是有规律的,这个不言自明。这还需要找吗?不需要

几乎所有的烂玩意, 你都如此熟悉

你用什么时间来做真正有意义的事情呢?

让你看看什么叫做 Template:

我厂可是Java和PHP都在用的,PHP的种种又怎么会不知道。至于smarty算不算烂,我个人觉得是除出了原生PHP外的最好选择。就楼上用正则搞得这种练手的东西,就不做评价了。我也写过类似的模板引擎,但最终还是选择了用smarty或者直接PHP代码.单纯的使用正则和语法糖不能解决问题,反而会引入问题。只有像smarty和twig这种基于parse的模板引擎,才能把扩展性和兼容性做到最好。

我也没空测试和细看,就随便问几个问题,这也是我在写PHP的模板引擎过程中先后遇到的问题:

1.任意目录递归include的问题是否实现,也就是所谓的子模板和layout?
2.多层变量/多维数组解析是否实现,比如blog.user.name;
3.在标签里直接调用PHP内置函数和自定义函数是否实现?
4.类似smarty里的module和plugin你又如何解决?没有这个东西的话,模板引擎会比PHP还复杂;
5.报错的处理。如果模板里有语法错误,报错能否精确到模板的精确行,而不是一堆莫名其妙的错误提示?

如果不能很好的解决上面提到的几个问题,那还不如原生PHP。

0
南湖船老大
南湖船老大
/**
     * Takes unknown classes and loads plugin files for them
     * class name format: Smarty_PluginType_PluginName
     * plugin filename format: plugintype.pluginname.php
     *
     * @param  string $plugin_name class plugin name to load
     * @param  bool   $check       check if already loaded
     * @return string |boolean filepath of loaded file or false
     */
    public function loadPlugin($plugin_name, $check = true)



0
欣儿
欣儿

引用来自“南湖船老大”的答案

/**
     * Takes unknown classes and loads plugin files for them
     * class name format: Smarty_PluginType_PluginName
     * plugin filename format: plugintype.pluginname.php
     *
     * @param  string $plugin_name class plugin name to load
     * @param  bool   $check       check if already loaded
     * @return string |boolean filepath of loaded file or false
     */
    public function loadPlugin($plugin_name, $check = true)
这个函数在具体的执行过程中是怎么用的?比如,知道一个插件的方法会用,然后是怎么找出这个插件方法的文件,并引入
0
南湖船老大
南湖船老大

引用来自“欣儿”的答案

引用来自“南湖船老大”的答案

/**
     * Takes unknown classes and loads plugin files for them
     * class name format: Smarty_PluginType_PluginName
     * plugin filename format: plugintype.pluginname.php
     *
     * @param  string $plugin_name class plugin name to load
     * @param  bool   $check       check if already loaded
     * @return string |boolean filepath of loaded file or false
     */
    public function loadPlugin($plugin_name, $check = true)
这个函数在具体的执行过程中是怎么用的?比如,知道一个插件的方法会用,然后是怎么找出这个插件方法的文件,并引入

。。。。

插件的命名和存放路径都是有规律的,这个不言自明。这还需要找吗?不需要

南湖船老大
南湖船老大
回复 @欣儿 : parse需要有《编译语言》这门课的基础才能看懂
欣儿
欣儿
回复 @南湖船老大 : 那,具体的实现原理是什么?
南湖船老大
南湖船老大
回复 @欣儿 : 这就是smarty的精华-parse。实际上可以吧模板引擎看做一种新的语言,比如TPL语言,这种语言可以把TPL转化成PHP代码。
欣儿
欣儿
存放路径当然知道,我想知道的是它怎么根据这个方法而获得相应的方法插件文件并引入插件文件,而不是把所有插件都引入。主要的是怎么发现的这个插件的方法函数被调用?
0
宏哥
宏哥

引用来自“南湖船老大”的答案

引用来自“欣儿”的答案

引用来自“南湖船老大”的答案

/**
     * Takes unknown classes and loads plugin files for them
     * class name format: Smarty_PluginType_PluginName
     * plugin filename format: plugintype.pluginname.php
     *
     * @param  string $plugin_name class plugin name to load
     * @param  bool   $check       check if already loaded
     * @return string |boolean filepath of loaded file or false
     */
    public function loadPlugin($plugin_name, $check = true)
这个函数在具体的执行过程中是怎么用的?比如,知道一个插件的方法会用,然后是怎么找出这个插件方法的文件,并引入

。。。。

插件的命名和存放路径都是有规律的,这个不言自明。这还需要找吗?不需要

几乎所有的烂玩意, 你都如此熟悉

你用什么时间来做真正有意义的事情呢?

让你看看什么叫做 Template:

<?php defined('APPPATH') OR die('No direct access allowed.');
/**
 * Univeral Template Lang(UTL)
 * Copyright (C) 2010 anthony.chen
 * The placeholder is "{}", blank is not allowed
 *
 * A. Say "No" to: 
 * 1. <%variable%> involves pressing shift twice 
 * 2. Smarty's {$variable} syntax is even too much 
 * B. Say "Yes" to: 
 * 1. {variable} 
 *    {$localvariable} 
 * 2. {objectVariable.member} 
 * 3. {arrayVariable['title']} 
 * 4. {if:thisVariableHasValue} 
 * 		Output here 
 *    {else} 
 *   	Alternative output here 
 *    {end} 
 * 5. {foreach:dataArray,i,value} 
 *    {i}: {value}<br /> 
 *    {end} 
 * 6. {switch:variable} 
 *    <b>default case</b> 
 * 	  {case:testVariable} 
 * 		<b>variable:</b> testVariable 
 *    {case:'textual value'} 
 *     <b>variable:</b> 'textual value' 
 *    {endswitch} 
 * 7. {rows[0]['name']} 
 * 8. {currency(dollarAmount)} - format dollarAmount using the currency() function (previously defined) 
 * 	  {Finanace::currency(dollarAmount)} - format dollarAmount using the currency() function (previously defined) 
 * 9. {set:$var,$value}
 *    {set:$var,'charvalue'}
 * 10.{equals:$var,$value}
 *    {equals:$var,'charvalue'}
 * 11.{include:template,[TRUE/FALSE]} - include the template, optional explicit assign israw, 
 *                                    - The israw inherited if not assigned
 * C. Package Scope Support
 * 1. If the pkg_path is set for the UTL object, the %PKG_PATH% will be
 * 	  replaced by Package Path in include command
 *
 */

class UTL {
	protected $compileDirectory = null; // directory to cache template files in. defaults to /tmp/
	protected $templateDirectory= null; // array of directories to look for templates. can be relative to the baseDirectory
	protected $viewSuffix = ".shtml";
	protected $data; // a stdClass object to hold the data passed to the template
	protected $_template ;
	protected $_delimiters = null;
	protected $_israw = NULL;
	public $pkg_path = NULL;
	
	//global data

	/*
	public $doCache; // flag for whether to cache
	public $doStripCode;
	*/

	/**
	 * Construct the UTL instance
	 * @param String $temp  Template name , default is index
	 * @param String $subdir  Template Path relative to APPPATH , default is index
	 * @param String $suffix  Template file suffix name, default is ".shtml"
	 * @param Array $delimiters Delimiter to code, default as array('\{','\}')
	 * @param String $apppath apppath, The Application Path 
	 * @param Boolean $_israw, True when the template is PHP base, False by default when it's generic template
	 * @return Instance of UTL
	 */
	function __construct($temp="index",$subdir="views",$suffix='.shtml',$delimiters=array('{','}'),$apppath = null,$_israw = false) {
		$this->_israw = $_israw;
		$this->_delimiters = $delimiters;
		
		if($apppath == NULL){
			if(!defined('VIEWPATH'))
				define('VIEWPATH',APPPATH);
			$this->compileDirectory = $this->appendSeparator(VIEWPATH.DIRECTORY_SEPARATOR."cache".DIRECTORY_SEPARATOR.$subdir);
			$this->templateDirectory = $this->appendSeparator(VIEWPATH.DIRECTORY_SEPARATOR.$subdir);	
		}else{
			$this->compileDirectory = $this->appendSeparator($apppath.DIRECTORY_SEPARATOR."cache".DIRECTORY_SEPARATOR.$subdir);
			$this->templateDirectory = $this->appendSeparator($apppath.DIRECTORY_SEPARATOR.$subdir);	
		}
		if($suffix != null){
			$this->viewSuffix = $suffix;
		}
		$this->_template = $temp;	
		
		$this->data = new stdClass;
	}

	/**
	 * get UTL String with Data 
	 *
	 * @param String $subject, Original Subject String
	 * @param Array $data, Data array with key=>value pairs
	 * @param Array $delimiters, Delimitors for preg default array('\{','\}')
	 *
	 * @return String with replaced data
	 */

	public static function getString($subject,$data=NULL ,$delimiters=array('{','}')){
		if($data === NULL){
			return $subject;
		}
		else{
			$_searches = array();
			$_replacements = array();
			foreach($data as $_key => $_value){
				$_searches[] = $delimiters[0].$_key.$delimiters[1];
				$_replacements[] = $_value;
			}

			$_str = str_replace($_searches, $_replacements, $subject);
			return $_str;
		}
	}

	/**
	 * Makes sure folders have a trailing slash
	 */
	private function appendSeparator($path) {
		$path = trim($path);
		if(substr($path, strlen($path)-1, 1) != DIRECTORY_SEPARATOR)
			$path .= DIRECTORY_SEPARATOR;
		return $path;
	}

	/**
	 * Assign a template variable.
	 * This can be a single key and value pair, or an associate array of key=>value pairs
	 * @param String $key 
	 * @param Mixed $value
	 */
	public function assign($key, $value = null) {
		if(is_array($key)) {
			foreach($key as $n=>$v)
				$this->data->$n = $v;
		} elseif(is_object($key)) {
			foreach(get_object_vars($key) as $n=>$v)
				$this->data->$n = $v;
		} else {
			$this->data->$key = $value;
		}
	}
	

	/**
	 * Append the data into Scalar
	 *
	 * @param String $key, Property of Data
	 * @param String $value, Value to append
	 *
	 * @return NULL
	 */
	public function append($key, $value = '') {
		if(!property_exists($this->data, $key)) {
			$this->data->$key = '';
		}
		$this->data->$key .= $value;
	}

	/**
	 * Push the data into array
	 *
	 * @param String $key , Property name of data 
	 * @param Mixed $value, data to bush
	 *
	 * @return NULL
	 */
	public function push($key, $value = null) {
		if(!property_exists($this->data, $key)) {
			$this->data->$key = array();
		}
		$data = $this->data->$key;
		$data[] = $value;
		$this->data->$key = $data;
	}

	/**
	 * Resets all previously-set template variables
	 *
	 * @return NULL
	 */
	public function clear() {
		$this->data = new stdClass;
	}
	
	/**
	 * In charge of fetching and rendering the specified template
	 *
	 * @param String $template Template path,serperating muti templates by '|' 
	 * @param Boolean $israw, If the file is PHP base, fetch from constructor if NULL
	 *
	 * @return String The rendered page string
	 */
	public function output($template =null,$israw = NULL) {
		if(!$template)
			$template = $this->_template;
		if($israw === NULL)
			$israw = $this->_israw;
		if(!is_array($template))
			$template = explode('|',$template);
		// go through and prepend template and compile directories with baseDirectory if needed
		$out = '';
		$foundTemplate = false;
		foreach($template as $t) {
			$path = $this->appendSeparator($this->templateDirectory);
				if(file_exists($path . $t . $this->viewSuffix)) {
					$out .= $this->bufferedOutput($path, $t,$israw);
					$foundTemplate = true;
					break; // found the template, so don't check any more directories
				}
		}
		if(!$foundTemplate)
			throw new exception('Template (' . $t.$this->viewSuffix. ') not found in ' . $path);
		return $out;
	}

	public function __set($key,$value){
		$this->assign($key,$value);
	}
		
	public function __get($key){
		return $this->data->$key; 
	}
	
	public function __isset($key){
		return isset($this->data->$key);
	}

	public function __toString(){
		try
		{
			return $this->output();
		}
		catch (Exception $e)
		{
			// Display the exception message
			Pexcel::exception_handler($e);

			return '';
		}
	}

	/**
	 * Fetches the specified template, finding it in the specified path ... but only after trying to compile it first
	 */
	private function bufferedOutput($path, $template,$israw) {
		$this->compile($path, $template,$israw);

		ob_start();
		include($this->compileDirectory . $template . '.php');
		$out = ob_get_clean();
		return $out;
	}

	/**
	 * Compiles the template to PHP code and saves to file ... but only if the template has been updated since the last caching
	 * Uses Regular Expressions to identify template syntax
	 * Passes each match on to the callback for conversion to PHP
	 */
	private function compile($path, $template,$israw) {
		// moved from constructor
		if(!file_exists($this->compileDirectory))
			mkdir($this->compileDirectory,0700,true);

		$templateFile = $path . $template . $this->viewSuffix;
		$compiledFile = $this->compileDirectory . $template . '.php';
		$compileSubDir = dirname($compiledFile);
		if(!file_exists($compileSubDir)){
			mkdir($compileSubDir,0777,true);	
		}

		// don't spend time compiling if nothing has changed
		if(file_exists($compiledFile) && filemtime($compiledFile) >= filemtime($templateFile))
			return;

		$lines = file($templateFile);
		$newLines = array();
		$matches = null;
		foreach($lines as $line)  {
			//no space allowed: anthony.chen
			$pattern = '/'.preg_quote($this->_delimiters[0]).'([^{}\s]+)'.preg_quote($this->_delimiters[1]).'/';
			$num = preg_match_all($pattern, $line, $matches);
			if($num > 0) {
				for($i = 0; $i < $num; $i++) {
					$match = $matches[0][$i];
					$new = $this->transformSyntax($matches[1][$i],$israw);
					$line = str_replace($match, $new, $line);
				}
			}
			$newLines[] = $line;
		}
		$f = fopen($compiledFile, 'w');
		fwrite($f, implode('',$newLines));
		fclose($f);
	}
	

	/**
	 * This is where the generation of PHP code takes place
	 */
	private function transformSyntax($input,$israw) {
		$from = array(
			'/(^|\[|,|\(|\+|$)([a-zA-Z_][a-zA-Z0-9_]*)($|\.|\)|\[|\]|\+)/',
			'/(^|\[|,|\(|\+|$)([a-zA-Z_][a-zA-Z0-9_]*)($|\.|\)|\[|\]|\+)/', // again to catch those bypassed by overlapping start/end characters 
			'/\./',
		);
		$to = array(
			'$1$this->data->$2$3',
			'$1$this->data->$2$3',
			'->'
		);
		
		//$parts = explode(':', $input);
		//The seperator is restricted to : only
		preg_match("%(\w+):([^:].*)%",$input,$parts);
		if(!$parts) $parts[0] = $input;	
		else array_shift($parts);

		if($israw === true) $string = ''; else $string = '<?php ';
		switch($parts[0]) { // check for a template statement
			case 'if':
			case 'switch':
				$string .= $parts[0] . '(' . preg_replace($from, $to, $parts[1]) . ') { ' . ($parts[0] == 'switch' ? 'default: ' : '');
				break;
			case 'foreach':
				$pieces = explode(',', $parts[1]);
				$string .= 'foreach(' . preg_replace($from, $to, $pieces[0]) . ' as ';
				//Disable the transformation here to restrict the foreach 
				$string .=  $pieces[1];
				if(sizeof($pieces) == 3) // prepares the $value portion of foreach($var as $key=>$value)
					$string .= '=>' .$pieces[2];
				$string .= ') { ';
				break;
			case 'set': //Set variable, Or Execute the code
				$pieces = explode(',', $parts[1],2);
				$string .= preg_replace($from, $to, $pieces[0]) . ' = ';
				//Disable the transformation here to restrict the foreach 
				$string .=  preg_replace($from, $to, $pieces[1]);
				break;
			case 'equals': //Test if 2 values equals
				$pieces = explode(',', $parts[1],2);
				$string .= 'if (' . preg_replace($from, $to, $pieces[0]) . ' == ';
				//Disable the transformation here to restrict the foreach 
				$string .=  preg_replace($from, $to, $pieces[1]). ') { ';
				break;
			case 'end':
			case 'endswitch':
				$string .= '}';
				break;
			case 'else':
				$string .= '} else {';
				break;
			case 'case':
				$string .= 'break; case ' . preg_replace($from, $to, $parts[1]) . ':';
				break;
			case 'include':
				$pieces = explode(',', $parts[1]);
				if(count($pieces) == 2){
					if(!$this->pkg_path){
						$string .= 'echo $this->output("' . $pieces[0] . '",'.$pieces[1].');';
					}else{
						$string .= 'echo $this->output("' . str_replace('%PKG_PATH%',$this->pkg_path, $pieces[0]) . '",'.$pieces[1].');';
					}
				}else{
					if(!$this->pkg_path){
						$string .= 'echo $this->output("' . $parts[1] . '");';
					}else{
						$string .= 'echo $this->output("' . str_replace('%PKG_PATH%',$this->pkg_path,$parts[1]) . '");';
					}
				}
				break;
			default:
				$string .= 'echo ' . preg_replace($from, $to, $parts[0]) . ';';
				break;
		}
		if($israw === false) $string .= ' ?>';
		return $string;
	}
}



0
宏哥
宏哥

引用来自“南湖船老大”的答案

引用来自“宏哥”的答案

引用来自“南湖船老大”的答案

引用来自“欣儿”的答案

引用来自“南湖船老大”的答案

/**
     * Takes unknown classes and loads plugin files for them
     * class name format: Smarty_PluginType_PluginName
     * plugin filename format: plugintype.pluginname.php
     *
     * @param  string $plugin_name class plugin name to load
     * @param  bool   $check       check if already loaded
     * @return string |boolean filepath of loaded file or false
     */
    public function loadPlugin($plugin_name, $check = true)
这个函数在具体的执行过程中是怎么用的?比如,知道一个插件的方法会用,然后是怎么找出这个插件方法的文件,并引入

。。。。

插件的命名和存放路径都是有规律的,这个不言自明。这还需要找吗?不需要

几乎所有的烂玩意, 你都如此熟悉

你用什么时间来做真正有意义的事情呢?

让你看看什么叫做 Template:

我厂可是Java和PHP都在用的,PHP的种种又怎么会不知道。至于smarty算不算烂,我个人觉得是除出了原生PHP外的最好选择。就楼上用正则搞得这种练手的东西,就不做评价了。我也写过类似的模板引擎,但最终还是选择了用smarty或者直接PHP代码.单纯的使用正则和语法糖不能解决问题,反而会引入问题。只有像smarty和twig这种基于parse的模板引擎,才能把扩展性和兼容性做到最好。

我也没空测试和细看,就随便问几个问题,这也是我在写PHP的模板引擎过程中先后遇到的问题:

1.任意目录递归include的问题是否实现,也就是所谓的子模板和layout?
2.多层变量/多维数组解析是否实现,比如blog.user.name;
3.在标签里直接调用PHP内置函数和自定义函数是否实现?
4.类似smarty里的module和plugin你又如何解决?没有这个东西的话,模板引擎会比PHP还复杂;
5.报错的处理。如果模板里有语法错误,报错能否精确到模板的精确行,而不是一堆莫名其妙的错误提示?

如果不能很好的解决上面提到的几个问题,那还不如原生PHP。

1: 第 11条

2:  第 2 条

3:  第8 条

5:  第8 条

6: 出错行数和 模板一致,编译后的php是行对应的.

所有被OO F K过的脑残, 都无可救药, 无法理解本来就是很简单的东西.

除非你用两个凡是来拯救

哪怕是一些不大入流的php软件, 都不屑于用smarty 这种 肿胀的跟脓包一样的烂玩意

唯独你们这些 OO F K过的, 不可理喻.

zqq90
zqq90
回复 @南湖船老大 : 素质高低 一下子就看出来了。。一笑而过吧。。技术是技术。。拒绝人身攻击
宏哥
宏哥
回复 @南湖船老大 : 我相信你能写出很多类, 但是你这种屌丝 ,写不出任何有用的东西.
南湖船老大
南湖船老大
你的一些功能虽然能凑合实现,都是做出了一些牺牲的
0
宏哥
宏哥

引用来自“宏哥”的答案

回复 @南湖船老大

0
宏哥
宏哥

引用来自“宏哥”的答案

回复 @南湖船老大

编译后:

返回顶部
顶部