一、什么是MVC
MVC模式(Model-View-Controller)是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller)。
MVC模式的目的是实现一种动态的程序设计,使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。除此之外,此模式通过对复杂度的简化,使程序结构更加直观。软件系统通过对自身基本部份分离的同时也赋予了各个基本部分应有的功能。专业人员可以通过自身的专长分组:
(控制器Controller)- 负责转发请求,对请求进行处理。 (视图View) – 界面设计人员进行图形界面设计。 (模型Model) – 程序员编写程序应有的功能(实现算法等等)、数据库专家进行数据管理和数据库设计(可以实现具体的功能)。 模型(Model) “数据模型”(Model)用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。“模型”有对数据直接访问的权力,例如对数据库的访问。“模型”不依赖“视图”和“控制器”,也就是说,模型不关心它会被如何显示或是如何被操作。但是模型中数据的变化一般会通过一种刷新机制被公布。为了实现这种机制,那些用于监视此模型的视图必须事先在此模型上注册,从而,视图可以了解在数据模型上发生的改变。 视图(View) 视图层能够实现数据有目的的显示(理论上,这不是必需的)。在视图中一般没有程序上的逻辑。为了实现视图上的刷新功能,视图需要访问它监视的数据模型(Model),因此应该事先在被它监视的数据那里注册。 控制器(Controller) 控制器起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据模型上的改变。 二、为什么要自己开发MVC框架 网络上有大量优秀的MVC框架可供使用,本教程并不是为了开发一个全面的、终极的MVC框架解决方案,而是将它看作是一个很好的从内部学习PHP的机会,在此过程中,你将学习面向对象编程和设计模式,并学习到开放中的一些注意事项。 更重要的是,你可以完全控制你的框架,并将你的想法融入到你开发的框架中。虽然不一定是做好的,但是你可以按照你的方式去开发功能和模块。 三、开始开发自己的MVC框架 在开始开发前,让我们先来把项目建立好,假设我们建立的项目为hylm,那么接下来的第一步就是把目录结构先设置好。虽然在这个教程中不会使用到上面的所有的目录,但是为了以后程序的可拓展性,在一开始就把程序目录设置好使非常必要的。下面就具体说说每个目录的作用: application – 存放程序代码 config – 存放程序配置或数据库配置 db – 用来存放数据库备份内容 library – 存放框架代码 public – 存放静态文件 scripts – 存放命令行工具 tmp – 存放临时数据 在目录设置好以后,我们接下来就要来顶一下一些代码的规范: MySQL的表名需小写并采用复数形式,如items,cars 模块名(Models)需首字母大写,并采用单数模式,如Item,Car 控制器(Controllers)需首字母大写,采用复数形式并在名称中添加“Controller”,如ItemsController, CarsController 视图(Views)采用复数形式,并在后面添加行为作为文件,如:items/view.php, cars/buy.php 第一步将所有的的请求都重定向到public目录下,解决方案是在todo文件下添加一个.htaccesss文件,文件内容为:
- <IfModule mod_rewrite.c>
- RewriteEngine on
- RewriteRule ^$ public/ [L]
- RewriteRule (.*) public/$1 [L]
- </IfModule>
复制代码在我们把所有的请求都重定向到public目录下以后,我们就需要将所有的数据请求都再重定向到public下的index.php文件,于是就需要在public文件夹下也新建一个.htaccess文件,文件内容为: - <IfModule mod_rewrite.c>
- RewriteEngine On
- #如果文件存在就直接访问目录不进行RewriteRule
- RewriteCond %{REQUEST_FILENAME} !-f
- #如果目录存在就直接访问目录不进行RewriteRule
- RewriteCond %{REQUEST_FILENAME} !-d
- #将所有其他URL重写到 index.php/URL
- RewriteRule ^(.*)$ index.php?url=$1 [PT,L]
- </IfModule>
复制代码这么做的主要原因有:可以使程序有一个单一的入口,将所有除静态程序以外的程序都重定向到index.php上;可以用来生成利于SEO的URL,想要更好的配置URL,后期可能会需要URL路由,这里先不做介绍了。做完上面的操作,就应该知道我们需要做什么了,没错!在public目录下添加index.php文件,文件内容为: - <?php
- define('DS',DIRECTORY_SEPARATOR);
- define('ROOT',dirname(dirname(__FILE__)));
- $url = $_GET['url'];
- require_once(ROOT.DS.'library'.DS.'bootstrap.php');
- <pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word; font-family: "Courier New" !important; font-size: 12px; color: rgb(0, 0, 0); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><span style="margin: 0px; padding: 0px; font-family: "Courier New" !important; font-size: 12px !important; line-height: 1.5 !important; color: rgb(0, 0, 255);">require_once(ROOT.DS.'library'.DS .'shared.php');
- require_once(ROOT.DS.'config'.DS .'config.php');</span><span style="margin: 0px; padding: 0px; font-family: "Courier New" !important; font-size: 12px !important; line-height: 1.5 !important; color: rgb(0, 0, 0);"></span></pre>
复制代码注意上面的PHP代码中,并没有添加PHP结束符号”?>”,这么做的主要原因是:对于只包含PHP代码的文件,结束标志(“?>”)最好不存在,PHP自身并不需要结束符号,不添加结束符号可以很大程度上防止末尾被添加额外的注入内容,让程序更加安全。在index.php中,我们对library文件夹下的config.php发起了请求,那么config.php这个启动文件中到底会包含哪些内容呢? - <?php
- # 设置是否为开发状态
- define('DEVELOPMENT_ENVIRONMENT',true);
- # 设置数据库连接所需数据
- define('DB_HOST','localhost');
- define('DB_NAME','todo');
- define('DB_USER','root');
- define('DB_PASSWORD','root');
复制代码config.php涉及到的内容并不多,不过是一些基础数据的一些设置,再来看看library下的共用文件shared.php应该怎么写 - <?php
- /* 检查是否为开发环境并设置是否记录错误日志 */
- function setReporting(){
- if (DEVELOPMENT_ENVIRONMENT == true) {
- error_reporting(E_ALL);
- ini_set('display_errors','On');
- } else {
- error_reporting(E_ALL);
- ini_set('display_errors','Off');
- ini_set('log_errors','On');
- ini_set('error_log',ROOT.DS. 'tmp' .DS. 'logs' .DS. 'error.log');
- }
- }
- /* 主请求方法,主要目的拆分URL请求 */
- function callHook() {
- global $url;
- $urlArray = array();
- $urlArray = explode("/",$url);
- $controller = $urlArray[0];
- array_shift($urlArray);
- $action = $urlArray[0];
- array_shift($urlArray);
- $queryString = $urlArray;
- $controllerName = $controller;
- $controller = ucwords($controller);
- $model = rtrim($controller, 's');
- $controller .= 'Controller';
- $dispatch = new $controller($model,$controllerName,$action);
- if ((int)method_exists($controller, $action)) {
- call_user_func_array(array($dispatch,$action),$queryString);
- } else {
- /* 生成错误代码 */
- }
- }
复制代码
|