一相简单的MVC框架范例,MVC框架模式实现原理分析

您可能感兴趣的文章:

  • 20个2014年最优秀的PHP框架回顾
  • php实现最简单的MVC框架实例教程
  • Yii
    快速,安全,专业的PHP框架
  • PHP开发框架Laravel数据库操作方法总结
  • PHP框架Swoole定时器Timer特性分析
  • 2014年最新推荐的10款 PHP
    开发框架
  • 国产PHP开发框架myqee新手快速入门教程
  • PHP开发框架kohana3
    自定义路由设置示例
  • 高性能PHP框架Symfony2经典入门教程
  • ThinkPHP框架实现session跨域问题的解决方法
  • 常用PHP框架功能对照表

    //ob_end_flush();      //
这个是直接输出缓冲区的内容了,不用再次缓存起来。
    ob_start();            //开始新的缓冲区,给后面的程序用
    return $content;       //
返回文本,此处也可以字节echo出来,并结束代码。
}

Controller加载机制

复制代码 代码如下:

文件路径/system/core/URI.php

第五个$content = ob_get_contents
()很重要,是为了将缓冲区的内容取出来,但不清除它。

你可以匹配特定类型的HTTP请求和路径,渲染视图或做更多事情。如果你合并Dispatch和其他框架,那你就可以拥有一个相当强大并且轻量级的程序!

复制代码 代码如下:

PHP的mvc框架很多,像Yii,CodeIgniter,ThinkPHP等现在流行的框架,利用MVC模式进行web页面的开发,我们可以非常方便的编写web程序。他们的工作原理大家应该也比较感兴趣,下面我说说一个mvc框架长什么样。

//包含库
include ‘dispatch.php’;
// 定义你的路由
get(‘/greet’, function () {
//渲染视图
render(‘greet-form’);
});
//post处理
post(‘/greet’, function () {
$name = from($_POST, ‘name’);
// render a view while passing some locals
render(‘greet-show’, array(‘name’ => $name));
});
// serve your site
dispatch();

我们来看看Codeigniter框架是如何加载到controller并且调用action的。

文件路径/system/core/URI.php

Dispatch是一个PHP小框架。它并没有给你完整的MVC设置,但你可以定义URL规则和方法,以便更好组织应用程序。这对API、简单的站点或原型来说是完美的。

//controller中action的方法
public function index(){
    // … 许多的业务逻辑代码
    $data = array(‘name’=>’abc’, ‘age’=>12, …. );
    return $this->render(‘view/path/file.html’,$data);
}

//大约在250行
include(APPPATH.’controllers/’.$RTR->fetch_directory().$RTR->fetch_class().’.php’);
 
$class  = $RTR->fetch_class();
$method = $RTR->fetch_method();
 
//大约在308行
$CI = new $class();
 
//大约在359行
call_user_func_array(array(&$CI, $method),
array_slice($URI->rsegments, 2));
就这样,通过这个就调用到了我们的controller及其方法了,接下来就是编写自己的业务逻辑代码了。

在互联网我们都是通过url提供服务,因此不同的url有不同的服务。用户访问不同的页面也就获得了不同的服务。那么我们的服务是如何通过url来区分不同的服务呢。

我们来看看Codeigniter框架是如何加载到controller并且调用action的。

//大约在359行
call_user_func_array(array(&$CI, $method),
array_slice($URI->rsegments, 2));

第三个ob_start()是开启一块新的缓冲区,为了是将视图的内容放到缓冲区。当然了,缓冲区有一定的大小,如果内容超出了缓冲区的设定值,那么会自动的发送给server。

就这样,通过这个就调用到了我们的controller及其方法了,接下来就是编写自己的业务逻辑代码了。

// 看看是否是从命令行运行的
if (php_sapi_name() == ‘cli’ or defined(‘STDIN’)){
    $this->_set_uri_string($this->_parse_cli_args());
    return;
}
 
// 首先尝试 REQUEST_URI 这个适应大部分的情况
if ($uri = $this->_detect_uri()){
    $this->_set_uri_string($uri);
    return;
}
 
// 看看PATH_INFO变量是否存在?nginx需要配置
// Note: some servers seem to have trouble with getenv() so we’ll test
it two ways
$path = (isset($_SERVER[‘PATH_INFO’])) ? $_SERVER[‘PATH_INFO’] :
@getenv(‘PATH_INFO’);
if (trim($path, ‘/’) != ” && $path != “/”.SELF){
    $this->_set_uri_string($path);
    return;
}
 
// 没有PATH_INFO,看看 QUERY_STRING?
$path =  (isset($_SERVER[‘QUERY_STRING’])) ?
$_SERVER[‘QUERY_STRING’] : @getenv(‘QUERY_STRING’);
if (trim($path, ‘/’) != ”){
    $this->_set_uri_string($path);
    return;
}
 
//尝试去从 $_GET 获取信息
if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), ‘/’) !=
”){
    $this->_set_uri_string(key($_GET));
    return;
}
 
// 尽力了,放弃了路由
$this->uri_string = ”;
return;
通过上面的尝试,接下来就是如何利用路由机制加载正确的controller了。

接着在视图文件view/path/file.html里写上一下代码。

至此,我们看到一个简单的PHP的MVC框架。如果你有兴趣可以自己开发一个MVC框架,或者更深入点的HMVC。

Controller加载机制

视图view的显示

通过上面的尝试,接下来就是如何利用路由机制加载正确的controller了。

<div>
姓名 : <?=$name ?>
年龄 : <?php echo $age; ?>
</div>

$class  = $RTR->fetch_class();
$method = $RTR->fetch_method();

我们的web程序就要通过url寻找到不同的文件,进行不同的业务逻辑处理。我们的路由机制就是根据url,寻找到对应的controller,和action,然后由action进行具体的业务逻辑处理。

第三个ob_start()是开启一块新的缓冲区,为了是将视图的内容放到缓冲区。当然了,缓冲区有一定的大小,如果内容超出了缓冲区的设定值,那么会自动的发送给server。

第四个require
file,这个就是第一个参数,根据自己的规则去加载视图的文件。其中文件里可以夹杂php、html的代码。你在这个render()函数声明的任何局部变量或者这里能访问到的任何全局变量,都可以在require的file文件中访问到。

我们从这个函数也可以看到程序有点类似程序中断保护现场的感觉。只不过中断保护现场会先保存数据,然后在返回的时候恢复回来。这里只有关闭上一个缓冲区,开启一个新的缓冲区,关闭这个缓冲哦过去,开启另外一个缓冲区。

看看第一个extract($var)。这个函数从数组中将变量导入到当前的符号表。刚刚就将$data数组里面的name、age抽取出来,这样就可以在视图view中使用$name
$age。更详细的请参考

复制代码 代码如下:

一个简单的controller

在/system/core/Codeigniter.php中有如下的代码。Codeigniter在这之前会根据$_SERVER[‘PATH_INFO]里面的值来进行赋值(这个都是靠自己的设定的,默认的话CI他会有许多的if分支进行判断)。

protected function render($template, array $var = array() )
{
    extract($var);   // 抽取数组中的变量
    ob_end_clean (); //关闭顶层的输出缓冲区内容
    ob_start ();     // 开始一个新的缓冲区
    require TEMPLATE_ROOT . $template . ‘.html’;  //加载视图view
    $content = ob_get_contents ();             // 获得缓冲区的内容
    ob_end_clean ();           // 关闭缓冲区
 
    //ob_end_flush();      //
这个是直接输出缓冲区的内容了,不用再次缓存起来。
    ob_start();            //开始新的缓冲区,给后面的程序用
    return $content;       //
返回文本,此处也可以字节echo出来,并结束代码。
}
在这短短的几行代码中,全都是精华,就是这些非常重要的,全是php的内置函数,接下来我们来具体分析分析。

他们的工作原理大家应该也比较感兴趣,下面我说说一个mvc框架长什么样。

//定义一个controller
class UserControler extends Controller{
     //定义一个action方法,注意一定是public的
     public function index(){
          // do business code
     }
}
具体的对应规则不同的框架映射不同。以下是CodeIgniter框架的URL路由,它会尽力的尝试各种的可能,来分析URL的情况。

// 尽力了,放弃了路由
$this->uri_string = ”;
return;

我们从这个函数也可以看到程序有点类似程序中断保护现场的感觉。只不过中断保护现场会先保存数据,然后在返回的时候恢复回来。这里只有关闭上一个缓冲区,开启一个新的缓冲区,关闭这个缓冲哦过去,开启另外一个缓冲区。

第四个require
file,这个就是第一个参数,根据自己的规则去加载视图的文件。其中文件里可以夹杂php、html的代码。你在这个render()函数声明的任何局部变量或者这里能访问到的任何全局变量,都可以在require的file文件中访问到。

第七个ob_start()是重新开启一个缓冲区,为了是下面的程序需要使用缓冲区。有写框架可能不用对$content的内容进行操作了,那么直接ob_end_flush()将缓冲区的内容输出出来就行了。

// 看看是否是从命令行运行的
if (php_sapi_name() == ‘cli’ or defined(‘STDIN’)){
    $this->_set_uri_string($this->_parse_cli_args());
    return;
}

当我们的业务逻辑代码写完后,就需要页面的展示了。很多常见的MVC框架在页面的调用是这么写的。

在这短短的几行代码中,全都是精华,就是这些非常重要的,全是php的内置函数,接下来我们来具体分析分析。

路由机制

复制代码 代码如下:

在互联网我们都是通过url提供服务,因此不同的url有不同的服务。用户访问不同的页面也就获得了不同的服务。那么我们的服务是如何通过url来区分不同的服务呢。

// 首先尝试 REQUEST_URI 这个适应大部分的情况
if ($uri = $this->_detect_uri()){
    $this->_set_uri_string($uri);
    return;
}

在/system/core/Codeigniter.php中有如下的代码。Codeigniter在这之前会根据$_SERVER[‘PATH_INFO]里面的值来进行赋值(这个都是靠自己的设定的,默认的话CI他会有许多的if分支进行判断)。

//大约在308行
$CI = new $class();

//controller中action的方法
public function index(){
    // … 许多的业务逻辑代码
    $data = array(‘name’=>’abc’, ‘age’=>12, …. );
    return $this->render(‘view/path/file.html
www.111cn.net’,$data);
}

//定义一个controller
class UserControler extends Controller{
     //定义一个action方法,注意一定是public的
     public function index(){
          // do business code
     }
}

这个是一个很简单的展示视图的过程。如果直接使用这个不方便对视图view进行模块化,因此一些框架都不会这么直接用的。

//尝试去从 $_GET 获取信息
if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), ‘/’) !=
”){
    $this->_set_uri_string(key($_GET));
    return;
}

接着在视图文件view/path/file.html里写上一下代码。

protected function render($template, array $var = array() )
{
    extract($var);   // 抽取数组中的变量
    ob_end_clean (); //关闭顶层的输出缓冲区内容
    ob_start ();     // 开始一个新的缓冲区
    require TEMPLATE_ROOT . $template . ‘.html’;  //加载视图view
    $content = ob_get_contents ();             // 获得缓冲区的内容
    ob_end_clean ();           // 关闭缓冲区

这段如何将数据渲染到视图中,这段代码以前我一直很好奇,现在我明白了,我们来看看是如何实现的。

当我们的业务逻辑代码写完后,就需要页面的展示了。很多常见的MVC框架在页面的调用是这么写的。

第二个ob_end_clean()的作用是关闭顶层的缓冲区,为了是之前的程序不小心echo出的一些文字给清楚了,为了下一行的重新开辟一块缓冲区。

//大约在250行
include(APPPATH.’controllers/’.$RTR->fetch_directory().$RTR->fetch_class().’.php’);

第五个$content = ob_get_contents
()很重要,是为了将缓冲区的内容取出来,但不清除它。

// 没有PATH_INFO,看看 QUERY_STRING?
$path =  (isset($_SERVER[‘QUERY_STRING’])) ?
$_SERVER[‘QUERY_STRING’] : @getenv(‘QUERY_STRING’);
if (trim($path, ‘/’) != ”){
    $this->_set_uri_string($path);
    return;
}

一个简单的controller

复制代码 代码如下:

我们的web程序就要通过url寻找到不同的文件,进行不同的业务逻辑处理。我们的路由机制就是根据url,寻找到对应的controller,和action,然后由action进行具体的业务逻辑处理。

您可能感兴趣的文章:

  • php打造属于自己的MVC框架
  • php实现最简单的MVC框架实例教程
  • php实现简单的MVC框架实例
  • PHP MVC框架路由学习笔记
  • 搭建自己的PHP MVC框架详解
  • PHP
    MVC框架skymvc支持多文件上传
  • Thinkphp模板中使用自定义函数的方法
  • ThinkPHP模板输出display用法分析
  • thinkphp模板继承实例简述
  • PHP仿tp实现mvc框架基本设计思路与实现方法分析

// 看看PATH_INFO变量是否存在?nginx需要配置
// Note: some servers seem to have trouble with getenv() so we’ll test
it two ways
$path = (isset($_SERVER[‘PATH_INFO’])) ? $_SERVER[‘PATH_INFO’] :
@getenv(‘PATH_INFO’);
if (trim($path, ‘/’) != ” && $path != “/”.SELF){
    $this->_set_uri_string($path);
    return;
}

这个是一个很简单的展示视图的过程。如果直接使用这个不方便对视图view进行模块化,因此一些框架都不会这么直接用的。

至此,我们看到一个简单的PHP的MVC框架。如果你有兴趣可以自己开发一个MVC框架,或者更深入点的HMVC。

第二个ob_end_clean()的作用是关闭顶层的缓冲区,为了是之前的程序不小心echo出的一些文字给清楚了,为了下一行的重新开辟一块缓冲区。

具体的对应规则不同的框架映射不同。以下是CodeIgniter框架的URL路由,它会尽力的尝试各种的可能,来分析URL的情况。

第七个ob_start()是重新开启一个缓冲区,为了是下面的程序需要使用缓冲区。有写框架可能不用对$content的内容进行操作了,那么直接ob_end_flush()将缓冲区的内容输出出来就行了。

复制代码 代码如下:

复制代码 代码如下:

这段如何将数据渲染到视图中,这段代码以前我一直很好奇,现在我明白了,我们来看看是如何实现的。

看看第一个extract($var)。这个函数从数组中将变量导入到当前的符号表。刚刚就将$data数组里面的name、age抽取出来,这样就可以在视图view中使用$name
$age。更详细的请参考

<div>
姓名 : <?=$name ?>
年龄 : <?php echo $age; ?>
</div>

视图view的显示

路由机制