您好,欢迎访问一九零五行业门户网

开发自己的PHP MVC框架

这个教程可以使大家掌握用mvc模式开发php应用的基本概念。此教程分为三个部分,现在这篇是第一部分。
现在市面上有很多流行的框架供大家使用,但是我们也可以自己动手开发一个mvc框架,采用mvc模式可以大大减少我们开发应用的时间,并且能够更好的组织项目源代码,而且其中的某些模块还可在其它项目中使用。现在我要教大家写一个简单的mvc框架。由于这个项目很简单,轻量,所以可能并不是最佳实践,也不具备安全性,还需要大家在实际应用中完善。
所用技术:php,面向对象开发方法。
开始
首先在网站根目录下建立三个文件夹
models views controllers
然后在根目录下新建一个文件:
index.php
现在项目结构应该像这样
§ 网站根目录
  § index.php
  § models/
  § views/
  § controllers/
index.php是整个web应用的入口点,所有的用户请求都会经过它。我们会写一些代码来把用户请求分派到相应的控制器中,这些控制器存放在controllers文件夹里。之后,我们就可以用下面的方式来实现页面跳转:
http://你的域名.com/index.php?page1 http://你的域名.com/index.php?page2 http://你的域名.com/index.php?page3 设置前端控制器index.php 首先在index.php中定义网站根目录和网站域名,以便在整个应用中访问。
定义了网站根目录后,在任何php文件中,都能很方便的引用其它目录的php文件,因为index.php是入口文件,这样就能够在整个应用中访问在它之中定义的这些变量。
设置路由器router.php(转发用户请求到相应控制器) 在controllers目录下新建一个文件,名字为“router.php,这个文件用来处理所有页面请求。想像一下你家里的路由器,它负责把internet路由到家中的每个电脑。router.php文件将会获取传入到index.php的页面请求,然后把请求分派给不同的控制器(controllers)。
route.php中的代码:
这句代码会获取传入到应用中的请求参数。query_string就是”?“后面的所有字符串。
http://你的域名.com/index.php?page1 上面的地址会在代码中得到”page1&action=login“,为了把page1和后面的参数分开,我们需要在route.php中继续加入下列代码:
//解析$request变量,得到用户请求的页面(page1)和其它get变量(&分隔的变量)如一个请求http://你的域名.com/index.php?page1&article=buildawebsite,则被解析为array(page1, article=buildawebsite)   $parsed = explode('&' , $request);      //用户请求的页面,如上面的page1,为$parsed第一个变量,shift之后,数组为array(article=buildawebsite)   $page = array_shift($parsed);      //剩下的为get变量,把它们解析出来   $getvars = array();   foreach ($parsed as $argument)   {       //用=分隔字符串,左边为变量,右边为值       list($variable , $value) = split('=' , $argument);       $getvars[$variable] = $value;   }      //这是测试语句,一会儿会删除   print the page your requested is '$page';   print '
';   $vars = print_r($getvars, true);   print the following get vars were passed to the page:.$vars.登录后复制
登录后复制
;              现在我们需要在index.php中引入route.php
   如果顺利的话,你可以打开浏览器输入:
http://你的域名.com/index.php?news&article=howtobuildaframework 我们会看到如下输出
the page you requested is 'news'       the following get vars were passed to the page:          array       (           [article] => howtobuildaframework       )         
如果没有上述输出,请检查你的服务器配置是否正确,并检查代码是否有错误。 现在来让我们添加一个页面到我们的网站里,这样就可以让router.php来产生一个页面,而不是直接输出上面的信息。
创建一个控制器(controller)
在controllers文件夹里新建一个文件名为“news.php,定义如下的类:
';           $vars = print_r($getvars, true);           print            (               the following get vars were passed to this controller: .               .$vars.登录后复制
登录后复制
);       }   }  
注意我们把route.php中的测试代码复制过来了,并做了一些修改,我们把它放置在main函数里。现在让我们来修改route.php中的代码:
main($getvars);?>  
再次访问http://你的域名.com/index.php?news&article=howtobuildaframework,你将会看到从news_controller打印出来的信息。注意,我们现在用die()来处理错误,我们可以用其它更好的错误处理来规制它,但现在使用die()足够了,试试访问其它页面如http://你的域名.com/index.php?books,你会看到page does not exist!错误。创建一个model(模型)完善news_controller。假设我们有一些新闻片段来供读者阅读,那么就需要news_controller这个控制器去调用一个模型来抓取相关的新闻片段,无论它们是存储在数据库还是文件里。在models文件夹里新建一个文件,“news.php”,代码如下:
现在,我们需要对新闻控制器稍做一些更改,打开controllers里的news.php,把news_controller类的main函数的代码改为如下,这样,我们就会在“news_model”初始化时,看到打印在屏幕上的信息:
public function main(array $getvars)   {       $newsmodel = new news_model;   }   现在刷新页面,你会看到:
fatal error: class 'news_model' not found in /var/www/mvc/controllers/news.php on line xx          等一下,这不是我们想要的结果!我们正试图去加载一个不存在的类。那么原因就是我们并没有引入 /models/news.php文件。为了解决这个问题,让们重新来看一下router.php,然后在它的顶部添加一些代码:
//当类初始化时,自动引入相关文件   function __autoload($classname)   {       //解析文件名,得到文件的存放路径,如news_model表示存放在models文件夹里的news.php(这里是作者的命名约定)       list($filename , $suffix) = split('_' , $classname);          //构成文件路径       $file = server_root . '/models/' . strtolower($filename) . '.php';          //获取文件       if (file_exists($file))       {           //引入文件           include_once($file);               }       else       {           //文件不存在           die(file '$filename' containing class '$classname' not found.);           }   }   这个函数重载了php内置的autoload函数。当我们试图去初始化一个不存在的类时,这个‘魔术方法’允许我们拦截php所执行的动作。通过使用__autoload函数,我们能够告诉php寻找包含此类的文件的位置。假设你遵循了这篇文章中类和文件名的命名约定,那么每当你初始化一个类时,你就不必手动去引入包含此类的文件了! 保存route.php,再刷新一次浏览器,你会看到:
i am the news model   让我们在新闻模型类里定义一些函数来提供文章。现在,我们只简单的定义了一个数组,并保存一些文章,然后提供一个函数,让控制器从中根据标题获取一篇文章。修改models/news.php:
 array           (               'title' => 'new website' ,               'content' => 'welcome to the site! we are glad to have you here.'           )           ,           //2           'mvc' => array           (               'title' => 'php mvc frameworks are awesome!' ,               'content' => 'it really is very easy. take it from us!'           )           ,           //3           'test' => array           (               'title' => 'testing' ,               'content' => 'this is just a measly test article.'           )       );          public function __construct()       {       }          /**       * 根据标题获取文章       *        * @param string $articlename       *        * @return array $article       */       public function get_article($articlename)       {           //从数组中获取文章           $article = $this->articles[$articlename];                  return $article;       }      }?>   现在修改controllers/news.php中的main函数:
public function main(array $getvars)   {       $newsmodel = new news_model;              //获取一篇文章       $article = $newsmodel->get_article('test');              print_r($article);   }   现在我们并没有考虑过滤用户输入的问题,因为我们现在只是为了尽快让大家掌握php mvc的基本内容,所以我们现在不必太关心这些。
如果访问如下网址:
§ http://yourdomain.com/mvc/index.php?news&article=test
你会看到如下输出:
array ( [title] => testing [content] => this is just a measly test article. )   
创建视图(view)
现在我们已经有控制器和模型了,只差一个视图。视图是表现层,它是你的应用中,与用户接触最频繁的部分。之前我提到过,视图是提供与业务逻辑分离的用户接口,有很多方法可以做到这个。你可以使用模板引擎smarty或其它类似的。你也可以写一个自己的模板引擎,但那肯定是相当艰巨的任务。最后,你可以使用原生php视图。
对于目前来说,php视图足够了。这个就像以前php与html代码混合编程一样,但是有一点不同是,我们的业务逻辑已经和视图分离了。看一下如下代码:
welcome to our website!                      news           =$data['title'];?>           =$data['content'];?>
注意,嵌入的php标签利用了php 快捷操作符。这样就能够把我们的内容直接输出到html里面了。在views文件夹里新建一个文件“news.php”,把上述代码拷贝进来。现在我们有了视图文件,但是我们需要一个与视图交互的方法。在models文件夹里新建一个文件“view.php”,添加如下代码:
render = $file;           }               }          /**       * 接受从控制器赋予的变量,并保存在data数组中       *        * @param $variable       * @param $value       */       public function assign($variable , $value)       {           $this->data[$variable] = $value;       }          public function __destruct()       {           //把类中的data数组变为该函数的局部变量,以方便在视图模板中使用           $data = $this->data;                  //渲染视图           include($this->render);       }   }  
现在,最后一件要做的事就是从news_controller里加载视图。修改controllers/news.php:
get_article($getvars['article']);             //创建一个视图,并传入该控制器的template变量             $view = new view_model($this->template);             //把文章数据赋给视图模板             $view->assign('title' , $article['title']);             $view->assign('content' , $article['content']);         }   }   ?>
其它类似信息

推荐信息