Php: compile a simple template engine-PHP source code

Source: Internet
Author: User
Tags php foreach php web development reflector
Php writes a simple template engine. the mvc design mode is widely used in php web development. the data transmitted by the controller to the view layer can be parsed only through the template engine. Implement a simple template engine that only contains the if and foreach tags and parses the $ foo variable.
Compile the template class and compiler compilation class. The code is as follows:

 '. Php ', // file suffix 'templatedir' => '.. /views/', // The folder in which the template is located 'compiledir' => '.. /runtime/cache/views/', // The Directory stored after compilation 'suffixcompile' => '. php ', // after compilation, the file suffix 'iscachehtml' => false, // whether to re-compile the file into a static html file 'isortphp' => true, // whether php syntax 'cachetime' => 0, // cache time, in seconds]; private $ _ file; // private $ _ valueMap = []; // key-value pair private $ _ compiler; // compiler public function _ construct ($ compiler, $ config = []) {$ this-> _ com Piler = $ compiler; $ this-> _ config = array_merge ($ this-> _ config, $ config );} /*** [assign storage controller assigned key value] * @ param [type] $ values [key-value pair set] * @ return [type] [description] */public function assign ($ values) {if (is_array ($ values) {$ this-> _ valueMap = $ values;} else {throw new \ Exception ('The value assigned to the view by the controller must be an array! ');} Return $ this ;} /*** [show display View] * @ param [type] $ file [files with compilation cache] * @ return [type] [description] */public function show ($ file) {$ this-> _ file = $ file; if (! Is_file ($ this-> path () {throw new \ Exception ('Template file'. $ file. 'does not exist! ');} $ CompileFile = $ this-> _ config ['compiledir']. md5 ($ file ). $ this-> _ config ['suffixcompile ']; $ cacheFile = $ this-> _ config ['compiledir']. md5 ($ file ). '.html '; // after compilation, the file does not exist or the cache time expires. re-compile and regenerate the html static cache if (! Is_file ($ compileFile) | $ this-> isRecompile ($ compileFile) {$ this-> _ compiler-> compile ($ this-> path (), $ compileFile, $ this-> _ valueMap); $ this-> _ config ['iscachehtml '] = true; if ($ this-> isSupportPhp ()) {extract ($ this-> _ valueMap, EXTR_OVERWRITE); // import the variable from the array to the current symbol table} if ($ this-> isReCacheHtml ()) {ob_start (); ob_clean (); include ($ compileFile); file_put_contents ($ cacheFile, ob_get_contents (); ob_end_flush () ;}else {readfile ($ cacheFile );}} /*** [isRecompile determines whether to re-compile based on the cache time] * @ param [type] $ compileFile [compiled file] * @ return boolean [description] */private function isRecompile ($ compileFile) {return time ()-filemtime ($ compileFile)> $ this-> _ config ['cachetime'];} /*** [does isReCacheHtml need to re-cache static html files?] * @ return boolean [description] */private function isReCacheHtml () {return $ this-> _ config ['iscachehtml '];}/*** [does isSupportPhp support php syntax?] * @ return boolean [description] */private function issuppphp php () {return $ this-> _ config ['isortphp'];} /*** [path: obtain the template file path] * @ return [type] [description] */private function path () {return $ this-> _ config ['templatedir']. $ this-> _ file. $ this-> _ config ['suffix '];}
 _ ValueMap ['\ 1'];?> ",'
 ','
 ','
 ',"
 _ ValueMap ['\ 1'] as \ $ k =>\$ v) {?> ",'
 ','
 ']; /*** [Compile the template file with compile] * @ param [type] $ source [template file] * @ param [type] $ destFile [compiled file] * @ param [type] $ values [key-value pair] * @ return [type] [description] */public function compile ($ source, $ destFile, $ values) {$ this-> _ content = file_get_contents ($ source); $ this-> _ valueMap = $ values; if (strpos ($ this-> _ content, '{$ ')! = False) {$ this-> _ content = preg_replace ($ this-> _ patten, $ this-> _ translation, $ this-> _ content );} file_put_contents ($ destFile, $ this-> _ content );}}

Our controller can call the assign method in the template to assign values. The show method is used to compile the template.

 S [$ k] = $ c;} public function _ get ($ k) {return $ this-> build ($ this-> s [$ k]);} /*** Autowiring (Automatic Resolution) ** @ param string $ className * @ return object * @ throws Exception */public function build ($ className) {// if it is a Closure function (closures) if ($ className instanceof \ Closure) {// execute the Closure function return $ className ($ this);} if (isset (self :: $ instances [$ className]) {return self: $ instances [$ linoleic SsName];}/** @ var ReflectionClass $ reflector */$ reflector = new \ ReflectionClass ($ className); // check whether the class can be instantiated, exclude abstract classes abstract and object interface if (! $ Reflector-> isInstantiable () {throw new \ Exception ($ reflector. ': This class cannot be instantiated! ');}/** @ Var ReflectionMethod $ constructor obtains the class constructor */$ constructor = $ reflector-> getConstructor (); // if no constructor exists, directly instantiate and return if (is_null ($ constructor) {return new $ className;} // Get the constructor parameter, return the parameter list through the ReflectionParameter array $ parameters = $ constructor-> getParameters (); // recursively parse the parameters of the constructor $ dependencies = $ this-> getDependencies ($ parameters ); // create a new instance of the class. the parameters are passed to the class constructor. $ Obj = $ reflector-> newInstanceArgs ($ dependencies); self: $ instances [$ className] = $ obj; return $ obj ;} /*** @ param array $ parameters * @ return array * @ throws Exception */public function getDependencies ($ parameters) {$ dependencies = []; /** @ var ReflectionParameter $ parameter */foreach ($ parameters as $ parameter) {/** @ var ReflectionClass $ dependency */$ dependency = $ parameter-> getClass (); if (is_null ($ dependency) {// is a variable. if there is a default value, set the default value $ dependencies [] = $ this-> resolveNonClass ($ parameter );} else {// is a class that recursively parses $ dependencies [] = $ this-> build ($ dependency-> name) ;}} return $ dependencies ;} /*** @ param ReflectionParameter $ parameter * @ return mixed * @ throws Exception */public function resolveNonClass ($ parameter) {// if there is a default value, return the default value if ($ parameter-> isdefavalueavailable () {return $ parameter-> getDefaultValue ();} throw new \ Exception ('I have no idea what to do here. ');}}

To access the attributes of an object in key-value pairs, you must implement the four methods of the ArrayAccess interface,
The Object base class code is as follows:

public function offsetExists($offset)     {        return array_key_exists($offset, get_object_vars($this));    }    public function offsetUnset($key)     {        if (array_key_exists($key, get_object_vars($this)) ) {            unset($this->{$key});        }    }    public function offsetSet($offset, $value)     {        $this->{$offset} = $value;    }    public function offsetGet($var)     {        return $this->$var;    }

In a Controller, you can call the render method of the parent Controller.

$this->render('test\index', ['name' => 'tom', 'age' => 20, 'friends' => ['jack', 'rose']], ['cacheTime' => 10]);

Compile the View template file 'test \ Index ':

    
     Document   

Display template file view

{$ Name}

{$ Age}

{If $ age> 18}

Adult

{Else if $ age <10}

Xiao Mao child

{/If} {foreach $ friends}

{^ V}

{/Foreach}

So far, a simple template compilation engine is ready.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.