php 一步步实现mvc架构——view篇

2022-10-11 20:27:46 205 0
魁首哥

bigsmoker 51future 技术宅

同学们好,又跟大家见面了,继上次发布得 ” “,已有一个星期了,今天给同学们带了得是”php 一步步实现mvc架构——view篇”。如果对设计模式不了解得同学,请看这篇 ” “。掌握设计模式,有利于理解mvc中各种模式得实现。

好了,言归正传。首先先了解下,什么是view 层。还记得 在 路由篇 中得那张图吗?为了更直观一些,我还是将这张图引入

看见那个view层了吧。对得,就是视图层。这个层就是今天得主角。

一 先说说实现思路,来看个view层代码

index.php

======================================================================

 
{{$test}}

{{$myname}}
{{foreach($memners as $k=>$v)}}
{{$v}}
{{endforeach}}   

这些个奇葩得类似 {{$test}}的变量,就是模板变量,可能有同学说 里面不光是模板变量,还有

{{foreach}}之流,没做。在这个模板里,它们统统都叫 模板变量。

再来看下controller层代码

Test.php

======================================================================

 function mytestAction()
{
    //echo "hello";
    //var_dump(func_get_args());
    //  $this->loadModel('http\models\Test');
    $this->assign("test","mytestAction");
    $this->assign("myname","hhh");
    $this->assign('memners',array('a'=>1,'b'=>'2','c'=>3));
    $this->display('index');
}  

以上代码代码通过display,去调用 templates.php中的display方法来引用模板。那么这个display是什么鬼?哈哈,其实这个display就做两件事。

1 将index.php中的模板变量解析成 原生php语法

解析前的模板

======================================================================

 
{{$test}}

{{$myname}}
{{foreach($memners as $k=>$v)}}
{{$v}}
{{endforeach}}

======================================================================

解析后的模板

======================================================================

  1,
    'b' => '2',
    'c' => 3,
); ?>


$v) {?>

======================================================================

没错,你可以用任何你能想得到的方法去实现。这里的实现思路就是用正则匹配,替换模板变量

具体实现步骤:

1通过template.php 中的display方法读取 模板流

2将模板流中的循环{{foreach($memners as $k=>$v)}}替换成 $v) {?>,{{endforeach}}替换成,{{$test}}替换成

3将controller方法mytestAction中的要赋值给模板的值,通过assign($key,$value)的方法赋值给templates.php中的varArr数组。这个vArr形如:vArr[“test”]=”mytestAction”。

以下是具体操作

给模板赋值

$this->assign(“test”,”mytestAction”);

$this->assign(“myname”,”hhh”);

$this->assign(‘memners’,array(‘a’=>1,’b’=>’2’,’c’=>3));

4将varArr中的值注入 模板流

注意

模板流 指用file_get_content,获取的字符串

二 讲完思路,我们上代码,具体看下如何实现

先看下架构图

======================================================================

======================================================================

上图cache 层就是最终引入的php文件(最终的视图模板)

======================================================================

  1,
    'b' => '2',
    'c' => 3,
); ?>


$v) {?>

======================================================================

再看下http\controller\Test.php

 assign("test","mytestAction");//模板赋值
        $this->assign("myname","hhh");
        $this->assign('memners',array('a'=>1,'b'=>'2','c'=>3));
        $this->display('index');//调用templates/Test/mytest/index.php
    }
    function mytest3Action()
    {
        $this->assign("test","mytest3Action");
        $this->assign("myname","hello");
        $this->assign('memners',array('a'=>1,'b'=>'2','c'=>3));
        $this->display('index');//调用templates/Test/mytest3/index.php
    }
}  

======================================================================

再看下 controller类,调用了Vendor\lib\templates.php的assign和display方法

======================================================================

 templatesObj = (new templates());
    }
    function display($name, ...$arguments)
    {
        $this->templatesObj->display($name, $arguments);
    }
    function assign($k,$v)
    {
        $this->templatesObj->assign($k,$v);
    }
}  

======================================================================

继续查看Vendor\lib\templates.php

======================================================================

 controller=basename(str_replace("\\","/",$GLOBALS['controller']))??'index';
        $this->method=str_replace("Action","",$GLOBALS['method'])??'index';
        $this->suffix='.php';
    }
    function display($tpl,$compileDir='')
    {
        $this->tpl[$this->controller][$this->method] = TPLROOT.DIRECTORY_SEPARATOR.$this->controller.DIRECTORY_SEPARATOR.$this->method.DIRECTORY_SEPARATOR.$tpl.$this->suffix??"";
        $pattern = "#{{(.*?)}}#i";
        $content = file_get_contents($this->tpl[$this->controller][$this->method]);
        $res = $this->replacePattern($pattern,$content);
            $compileDir =COMPILEPATH.DIRECTORY_SEPARATOR.$this->controller.DIRECTORY_SEPARATOR.$this->method.DIRECTORY_SEPARATOR;
        $this->compile($res,$compileDir,$tpl);
        require $this->cacheFile;
    }
    function assign($k,$v)
    {
        $this->vArr[$k] = $v;
    }
    function compile($content,$complieDir,$tplname)
    {
        $this->cacheFile = $complieDir.$tplname.'.php';
        if(is_dir($complieDir))
        {
            return file_put_contents($this->cacheFile,$content);
        } else {
            mkdir($complieDir,0777,true);
            return file_put_contents($this->cacheFile,$content);
        }
    }
    function setPatternFlag($left,$right)
    {}
    function parseVar($pattern,$content)
    {
        preg_match_all($pattern,$content,$matches);
        $replacements = [];
        foreach ($matches[1] as $k=>$v) {
            $matches[0][$k] = '/'.addcslashes($matches[0][$k],'(,$,)').'/';
            if(preg_match("#(foreach.*\((.*?)\))#i",$v))
            {
                $replacements [$k] = "";
            } else if(preg_match("#(endforeach)#i",$v)){
                $replacements [$k] = "";
            }else {
                $replacements [$k] = "";
            }
        }
        $content = preg_replace($matches[0],$replacements,$content);
        $phpVar = '';
        foreach ($this->vArr as $k=>$v)
        {
            if(is_array($v))
            {
                $phpVar .= "";
            } else {
                $phpVar .= "";
            }
        }
        return $phpVar.$content;
    }
    function replacePattern($pattern,$content)
    {
        return $this->parseVar($pattern,$content);
    }
}  

======================================================================

先来看下assign(),很简单,就是将值放入数组,以便将值注入 模板流

======================================================================

 function assign($k,$v)
{
    $this->vArr[$k] = $v;
}  

======================================================================

display 函数的作用是将模板变成 模板流( file_get_contents($this->tpl[$this->controller][$this->method]) ),然后调用 replacePattern方法将模板流中的模板变量替换成 的形式。用file_put_content方法及将其写入cache/Test/mytest/index.php中。再 通过 require cache/Test/mytest/index.php 加载视图

======================================================================

 function display($tpl,$compileDir='')
{
    $this->tpl[$this->controller][$this->method] = TPLROOT.DIRECTORY_SEPARATOR.$this->controller.DIRECTORY_SEPARATOR.$this->method.DIRECTORY_SEPARATOR.$tpl.$this->suffix??"";
    $pattern = "#{{(.*?)}}#i";
    $content = file_get_contents($this->tpl[$this->controller][$this->method]);
    $res = $this->replacePattern($pattern,$content);
        $compileDir =COMPILEPATH.DIRECTORY_SEPARATOR.$this->controller.DIRECTORY_SEPARATOR.$this->method.DIRECTORY_SEPARATOR;
    $this->compile($res,$compileDir,$tpl);
    require $this->cacheFile;//引入模板流生成的php文件

}  

======================================================================

再来看下最重要的replacePattern方法,这个方法的作用就是替换模板变量{{}}为

然后用compile 方法读取replacePattern出来的流,写入cache对应的目录,如cache/Test/mytest/index.php

效果图

 function mytest3Action()
{
    $this->assign("test","mytest3Action");
    $this->assign("myname","hello");
    $this->assign('memners',array('a'=>1,'b'=>'2','c'=>3));
    $this->display('index');
}  

 function mytestAction()
{
    //echo "hello";
    //var_dump(func_get_args());
    //  $this->loadModel('http\models\Test');
    $this->assign("test","mytestAction");
    $this->assign("myname","hhh");
    $this->assign('memners',array('a'=>1,'b'=>'2','c'=>3));
    $this->display('index');
}  

视图层的简单实现今天就讲到这,有兴趣的同学不妨自己试试怎么实现。

接下来要讲得是php 一步步实现mvc架构——model篇。同学们 敬请期待。下期再见

收藏
分享
海报
0 条评论
205
上一篇:PHP反序列化之私有变量与受保护变量的特点 下一篇:对PHP框架一些新的见解,快速开发那点事

本站已关闭游客评论,请登录或者注册后再评论吧~

忘记密码?

图形验证码