我正在编写一个模板引擎,我试图在我的模板引擎中添加一个@extends
函数来处理一个文件并在运行时在我的页面中运行它:
<?php BakerApp::extends('filename.php',get_defined_vars()); ?>
上面的代码将替换为@extends('filename')
和以下代码:
public function extends($BAKER_FILE_NAME,$vars){
$BAKER_FILE_NAME.=baker::$extension;
extract($vars);
eval('?> '.baker::compile(file_get_contents($BAKER_FILE_NAME),0));
}
到目前为止,我的代码工作正常,但是当我在扩展文件中使用@extends
时,我的代码输出如下:
Root Page RootPage>subPage RootPage>subPage RootPage>subPage RootPage>subPage RootPage>subPage RootPage>subPage RootPage>subPage RootPage>subPage RootPage>subPage RootPage>...............
虽然这应该如下:
Root Page
RootPage>subPage
rootPage>Subpage>thispage
我的页面是以下代码:
file:page.php
Root Page
@extends('app')
file:app.php
RootPage>subPage
@extends('ext')
file:ext.php
rootPage>Subpage>thispage
我的模板引擎如下:
file:baker2.class.php
<?php
function e($e){
return htmlentities($e);
}
function mprint($array){
echo "<br><pre>";
print_r($array);
echo "<br></pre>";
}
function teletype($char){
mprint(preg_replace('~([\S\s])~', ' $1', $char));exit;
}
function write_in_file($address,$content){
$FileHandle=fopen($address, 'w');
fwrite($FileHandle, $content);
fclose($FileHandle);
}
class baker
{
public static $data;
public static $tmp;
public static $Current=[];
public static $ta;
public static $edit=true;
public static $extension='.baker.php';
public static $baked_extension='.baked.php';
public static $root_of_theme=__DIR__.'/';
public static $root_of_baked_theme=__DIR__.'/';
public static $minify=false;
public static $b='<?php ';
public static $e=' ?>';
public static $patterns=[];
public static $func;
public static $shortcuts;
public static $Functions;
public static $PshortCuts;
public static $blocks;
public static $shorttags;
public static $baked_file_address='';
function addPart($pattern,$replace){
self::$patterns[$pattern]=$replace;
}
function addFunc(){
$args=func_get_args();
foreach ($args as $value) {
self::$func[]=$value;
}
}
function addFunction($FunctionName,$FunctionRe){
if(is_array($FunctionName)){
foreach ($FunctionName as $name) {
self::$Functions[$name]=$FunctionRe;
}
}else{
self::$Functions[$FunctionName]=$FunctionRe;
}
}
function addShortCut($shortCutName,$ShortCutRe){
if(is_array($shortCutName)){
foreach ($shortCutName as $name) {
self::$shortcuts[$name]=$ShortCutRe;
}
}else{
self::$shortcuts[$shortCutName]=$ShortCutRe;
}
}
function addShortTag($shortTagName,$ShortTagRe){
if(is_array($shortTagName)){
foreach ($shortTagName as $name) {
self::$shorttags[$name]=$ShortTagRe;
}
}else{
self::$shorttags[$shortTagName]=$ShortTagRe;
}
}
function addBlock($blockName,$blockFunc){
if(is_array($blockName)){
foreach ($blockName as $name) {
self::$blocks[$name]=$blockFunc;
}
}else{
self::$blocks[$blockName]=$blockFunc;
}
}
function ReplaceKeyToValue($string,$array){
foreach ($array as $key => $value) {
$string=str_replace($key, $value, $string);
}
return $string;
}
function baker($vals=[])
{
baker::addFunc(
// function(){
// $extend='~(@extends\((?:\'|")(.+)(?:\'|")\))~';
// for(;;){
// if(preg_match($extend, baker::$tmp, $matches)){
// baker::$tmp = str_replace($matches[0],file_get_contents(baker::$root_of_theme.$matches[2]),baker::$tmp);
// }else{
// break;
// }
// }
// }
//,function(){
// $getsection='~@(?:GetSection|yield)\((?:\'|")(.+)(?:\'|")\)~';
// for(;;){
// if(preg_match($getsection, baker::$tmp, $matches)){
// baker::$tmp = str_replace($matches[0],baker::$data[$matches[1]],baker::$tmp);
// }else{
// break;
// }
// }
// }
);
self::$data=$vals;
}
function assign($assign,$val=false)
{
if($val){
self::$data[$assign]=$val;
}else{
}
}
function minify($file){
// echo "<pre>".preg_replace('~([a-zA-Z0-9_\<\>\[\]\?])~', ' $1', $file)."</pre>";exit;
$minifyPattern=[
'~[ ]+~'=>'',
'~[ ]+~'=>' ',
'~[
]~'=>'',
'~\?\>[ ]+~'=>'?>&-SPACE_$#',
'~[ ]+<\?php~'=>'&-SPACE_$#<?php',
'~[ ]*\:[ ]*~'=>':',
'~[ ]*\=[ ]*~'=>'=',
'~[ ]*\{[ ]*~'=>'{',
'~[ ]*\}[ ]*~'=>'}',
'~[ ]*\[[ ]*~'=>'[',
'~[ ]*\][ ]*~'=>']',
'~[ ]*\'[ ]*~'=>'\'',
'~[ ]*\"[ ]*~'=>'"',
'~[ ]*<[ ]*~' =>'<',
'~[ ]*>[ ]*~' =>'>',
'~<\!\-\-([a-zA-Z0-9_ \-\<\>\\\(\)/"\'\.=&#ضصثقفغعهخحجچپشسیبلاتنمکگظطزرذدئوءأإؤژيةَُِّۀآـ«»:,؛،ريالًٌٍ\+])\-\->~'=>'',
'~<\?php\}\?>~'=>'<?php } ?>',
'~<\?php\}~' =>'<?php }',
'~&-SPACE_\$#~'=>' ',
];
$ptr=[];
$ptrRe=[];
foreach ($minifyPattern as $key => $value) {
$ptr[]=$key;
$ptrRe[]=$value;
}
$file=preg_replace($ptr, $ptrRe, $file);
return $file;
}
function loop($template_source)
{
$b='<?php ';
$e=' ?>';
// preg_match($replace_before_exe, $tmp,$matches);
if(self::$func){
foreach (self::$func as $key => $value) {
$value();
}
}
/**
*
* @functions e.g @funcName
*
*/
$pt='~@(\w+)\s*(?:\((.*?)\)(?:\{(.*?)})?\s*(?=$|\n|;))?~';
preg_match_all($pt,$template_source,$matchFunction);
$i=0;
foreach ($matchFunction[1] as $FuncName) {
$FuncCode = $matchFunction[0][$i];
$FuncArgs = $matchFunction[2][$i];
$FuncOutSideArg = $matchFunction[3][$i];
$ArgsArray=[];
for (;;) {
/*
past match
'~\s*((?:\w+\s*\([\s\S]*?\))|(?:"[\s\S]*?")|\'[\s\S]*?\'|[^,]*\[[\s\S]*?]|(?:true|false|null))\s*(?=(?:,|\)|$))~s'
new
'~\s*((?:\w+\s*\([\s\S]*?\))|(?:"[\s\S]*?")|\'[\s\S]*?\'|[^,]*\[[\s\S]*?]|(?:true|false|null)|(?:.+?))\s*(?=(?:,|$))~'
new
'~\s*,?\s*((?:(?:\'.*?\')|(?:\".*?\")|array\(.*?\))|(?:\[.*?\])|(?:.+?))\s*(?=(?:,|$))~s'
*/
if(preg_match('~\s*,?\s*((?:(?:\'.*?\')|(?:\".*?\")|array\(.*?\))|(?:\[.*?\])|(?:.+?))\s*(?=(?:,|$))~s',$FuncArgs,$args)){
$FuncArgs=str_replace($args[0],'',$FuncArgs);
$ArgsArray[]=$args[1];
}else{
break;
}
}
if(isset(self::$Functions[$FuncName])){
$template_source=str_replace($FuncCode,self::$Functions[$FuncName]($ArgsArray,$FuncOutSideArg),$template_source);
}
$i++;
}
// if(isset(self::$Functions[])){
//
// }
// $template_source=str_replace($matchFunction[0],'',$template_source);
// mprint($matchFunction);
// break;
#Blocks#
$pt='~{\s*(\w+)(?:\((.*?)\))?(?:\s|\~)(.*?)end\1}~s';
preg_match_all($pt, $template_source,$match);
$i=0;
foreach ($match[1] as $blockName) {
//mprint($match[2][$i]);
$args=[];
if(preg_match_all('~\s*,?\s*((?:(?:\'.*?\')|(?:\".*?\")|array\(.*?\))|(?:\[.*?\])|(?:.+?))\s*(?=(?:,|$))~s', $match[2][$i],$argsMatch)){
$args=$argsMatch[1];
}
$blockContent=$match[3][$i];
$block=$match[0][$i];
$i++;
if(isset(self::$blocks[$blockName])){
$blockRe=self::$blocks[$blockName]($blockContent,$args);
$template_source=str_replace($block,$blockRe,$template_source);
}
}
#short cuts#
for (;;) {
if(preg_match('`^\s*\[\s*(\w+)(?:\s+(\w+=.*?|\~.*?))?\s*(=?~]|])\s*$`sm', $template_source,$ShortCutVal)){
$shortCutKeyValArray=[];
if(preg_match('~\s*(?:\~(")|\w+=)?(.*)\1\s*~s', $ShortCutVal[2],$oneArg)){
$shortCutKeyValArray['_']=$oneArg[2];
}
if($ShortCutVal[3]=='~]'){
$pt= '`^\s*\[\s*'.$ShortCutVal[1].'(?:\s+(?:\w+=.*?|\~.*?))?(?:\s*'.$ShortCutVal[3].')\s*(.*?)\[/\s*'.$ShortCutVal[1].'\s*]\s*$`sm';
preg_match($pt, $template_source,$x);
$ShortCutVal[0]=$x[0];
$shortCutKeyValArray['block_contents']=$x[1];
}
$shortCutName=strtolower($ShortCutVal[1]);
$shortCutKeyValString=$ShortCutVal[2];
$arg2=$shortCutKeyValString;
for (;;) {
if(!preg_match('~(\w+)\s*=\s*"(.*?)"\s*(?=$|\w+\s*=)~s', $shortCutKeyValString,$ValOfaAttr)){
break;
}
$shortCutKeyValString=str_replace($ValOfaAttr[0], '', $shortCutKeyValString);
//mprint($ValOfaAttr);
$shortCutKeyValArray[$ValOfaAttr[1]]=$ValOfaAttr[2];
}
$template_source= str_replace($ShortCutVal[0], self::$shortcuts[$shortCutName]($shortCutKeyValArray,$arg2), $template_source);
}else{
break;
}
}
# #@shorttag #
$pattern='~#@(\w+)(?:\{(\*|\+)([\w ]+)})?~';
preg_match_all($pattern, $template_source, $match);
$i=0;
foreach ($match[1] as $shortTagName) {
$shortTagBody=$match[0][$i];
if(isset(self::$shorttags[$shortTagName])){
$replace=self::$shorttags[$shortTagName]();
switch ($match[2][$i]) {
case '+':
$replace.=$match[3][$i];
break;
case '*':
$replace=str_repeat($replace, $match[3][$i]);
break;
}
$template_source=str_replace($shortTagBody, $replace, $template_source);
}
$i++;
}
/* patterns */
self::$tmp=$template_source;
$ptr=[];$ptrRe=[];
foreach (self::$patterns as $key => $value) {
if(preg_match_all($key,$template_source,$ptrMatch)){
$value($ptrMatch);
}
}
$template_source=self::$tmp;
//$template_source= preg_replace($ptr,$ptrRe, $template_source);
if(self::$minify){
$template_source=self::minify($template_source);
}
return $template_source;
}
function run($template_source){
extract(self::$data);
eval(' ?> '.$template_source);
}
function compile($template_source,$cache=1){
self::$data+=$GLOBALS;
// $file_address=self::$root_of_theme.$name.self::$extension;
$baked_file_address= self::$baked_file_address;
//$template_source=file_get_contents($file_address);
$template_source=self::loop($template_source);
if($cache){
$FileName = $baked_file_address;
$FileHandle = fopen($FileName, 'w') or die("can't open file");
fclose($FileHandle);
file_put_contents($FileName, $template_source);
}
return $template_source;
}
function view($name){
if(!is_dir(self::$root_of_baked_theme)){
mkdir(self::$root_of_baked_theme);
}
$file_address=self::$root_of_theme.$name.self::$extension;
$baked_file_address= self::$root_of_baked_theme.$name.self::$baked_extension;
self::$baked_file_address=$baked_file_address;
if(self::$edit || !file_exists($baked_file_address)){
$template_source=self::compile(file_get_contents($file_address));
}else{
$template_source=file_get_contents($baked_file_address);
}
self::run($template_source);
}
function getsourse(){
}
}
/**
* baker Compiler
*/
class BakerCompiler
{
public static $template_source='';
public function BakerCompiler($resource='')
{
self::$template_source=$resource;
return $this;
}
public function getSource($resource){
self::$template_source=$resource;
return $this;
}
public function compile($resource){
}
}
class BakerApp
{
public static $current_section=[];
public static $last_section='';
public static $sections=[];
public function startSection($name){
self::$current_section=array_reverse(self::$current_section);
self::$current_section[]=$name;
self::$current_section=array_reverse(self::$current_section);
ob_start();
}
public function stopSection(){
$section_content=ob_get_clean();
self::$last_section=self::$current_section[0];
self::$sections[self::$current_section[0]]=$section_content;
array_shift(self::$current_section);
//mprint(self::$current_section);
}
public function yield($name){
return self::$sections[$name];
}
public function extends($BAKER_FILE_NAME,$vars){
$BAKER_FILE_NAME.=baker::$extension;
extract($vars);
eval('?> '.baker::compile(file_get_contents($BAKER_FILE_NAME),0));
}
}
?>
,用法是:
include 'baker2.class.php';
new baker();
baker::addFunction(['extends','extend'],function($args){
return '<?php BakerApp::extends('.$args[0].',get_defined_vars()); ?>';
});
baker::$extension='.php';
baker::view('page');
我当前的代码中出现了什么问题?我该如何解决?