🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # 1 简单例子 > Twig的简单应用例子 ~~~ <?php require_once './vendor/autoload.php'; // 字符串渲染 // $loader = new Twig_Loader_Array(array( // 'index' => 'Hello {{ name }}!', // )); // $twig = new Twig_Environment($loader); // echo $twig->render('index', array('name' => 'Fabien')); // 文件渲染 $loader = new Twig_Loader_Filesystem('./template'); $twig = new Twig_Environment($loader, array( 'cache' => './cache', )); $string = $twig->render('index.html', array('name' => 'Fabien')); ?> ~~~ # 2 主要流程 > 简单例子中Twig的主要流程 > 1. 创建模板加载器 Twig_loader > 2. 创建编译环境 Twig_environment > 3. 编译模板 render() # 3 编译流程 >在render()方法包含编译流程 ~~~ ;\Twig\Environment.php public function render($name, array $context = array()) { return $this->loadTemplate($name)->render($context); } ~~~ > 模板编译入口 ~~~ public function loadTemplate($name, $index = null) { $cls = $mainCls = $this->getTemplateClass($name); if (null !== $index) { $cls .= '_'.$index; } if (isset($this->loadedTemplates[$cls])) { return $this->loadedTemplates[$cls]; } if (!class_exists($cls, false)) { $key = $this->cache->generateKey($name, $mainCls); if (!$this->isAutoReload() || $this->isTemplateFresh($name, $this->cache->getTimestamp($key))) { $this->cache->load($key); } if (!class_exists($cls, false)) { $source = $this->getLoader()->getSourceContext($name); $content = $this->compileSource($source); $this->cache->write($key, $content); $this->cache->load($key); if (!class_exists($mainCls, false)) { /* Last line of defense if either $this->bcWriteCacheFile was used, * $this->cache is implemented as a no-op or we have a race condition * where the cache was cleared between the above calls to write to and load from * the cache. */ eval('?>'.$content); } if (!class_exists($cls, false)) { throw new Twig_Error_Runtime(sprintf('Failed to load Twig template "%s", index "%s": cache is corrupted.', $name, $index), -1, $source); } } } // to be removed in 3.0 $this->extensionSet->initRuntime($this); if (isset($this->loading[$cls])) { throw new Twig_Error_Runtime(sprintf('Circular reference detected for Twig template "%s", path: %s.', $name, implode(' -> ', array_merge($this->loading, array($name))))); } $this->loading[$cls] = $name; try { $this->loadedTemplates[$cls] = new $cls($this); } finally { unset($this->loading[$cls]); } return $this->loadedTemplates[$cls]; } ~~~ >加载编译后的模板 ~~~ public function compileSource(Twig_Source $source) { try { return $this->compile($this->parse($this->tokenize($source))); } catch (Twig_Error $e) { $e->setSourceContext($source); throw $e; } catch (Exception $e) { throw new Twig_Error_Syntax(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $source, $e); } } ~~~ >模板编译核心流程 >1.$this->tokenize() >2.$this->parser() >3.$this->compile() ~~~ public function tokenize(Twig_Source $source) { if (null === $this->lexer) { $this->lexer = new Twig_Lexer($this); } return $this->lexer->tokenize($source); } ~~~ > 调用Twig_Lexer分析模板文件生成Twig_TokenStream ~~~ public function parse(Twig_TokenStream $stream) { if (null === $this->parser) { $this->parser = new Twig_Parser($this); } return $this->parser->parse($stream); } ~~~ > 调用Twig_Parser解析Twig_TokenStream ~~~ public function compile(Twig_Node $node) { if (null === $this->compiler) { $this->compiler = new Twig_Compiler($this); } return $this->compiler->compile($node)->getSource(); } ~~~ > 调用Twig_Compiler编译Twig_Node # 4 流程总结 > 1. 创建加载器 Twig_Loader > 2. 创建编译环境 Twig_Environment > 3. 模板文件解析 Twig_Lexer > 4. 模板字符串解析 Twig_Parser > 5. 模板节点编译 Twig_Compiler