咚门:时来有空,整理一下公司一直在用的 MVC 框架:
0. 目录:
---- controllers
--- router.php(路由)
--- users.php(以其中一个具体的 controller 为例)
--- ...
---- models
--- view.php(视图类)
--- users.php(以其中一个具体的 model 为例)
--- ...
---- views
--- users(以其中一个具体的 view 为例)
-- index.php
-- add.php
-- edit.php
-- ...
--- ...
---- index.php
1. 入口文件: /index.php
<?php
/*
* index.php是整个web应用的入口点,所有的用户请求都会经过它。
* 我们会写一些代码来把用户请求分派到相应的控制器中,这些控制器存放在controllers文件夹里
* 首先在index.php中定义网站根目录和网站域名,以便在整个应用中访问。
* 定义了网站根目录后,在任何php文件中,都能很方便的引用其它目录的php文件,因为index.php是入口文件,
* 这样就能够在整个应用中访问在它之中定义的这些变量。
* 在controllers目录下新建一个文件,名字为“router.php",这个文件用来处理所有页面请求。
* 想像一下你家里的路由器,它负责把internet路由到家中的每个电脑。
* router.php文件将会获取传入到index.php的页面请求,然后把请求分派给不同的控制器(controllers)。
* 创建一个Model(模型)完善News_Controller。
* 假设我们有一些新闻片段来供读者阅读,那么就需要News_Controller这个控制器去调用一个模型来抓取相关的新闻片段,无论它们是存储在数据库还是文件里。
* 在models文件夹里新建一个文件,“news.php”
* 现在我们已经有控制器和模型了,只差一个视图。可以使用原生php视图。在views文件夹里新建一个文件“news.php”
* 现在我们有了视图文件,但是我们需要一个与视图交互的方法。在models文件夹里新建一个文件“view.php”
* 访问URL http://域名或IP.com/index.php?news&a=index news为控制器参数 a=index 为控制器的方法参数
* 控制器页面可以不用再执行session_start();,数据模型页面和视图页面需要启动 session_start();
*/
session_start();
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-cache, must-revalidate");
header("Pramga: no-cache");
ini_set('session.gc_maxlifetime',7200); //设置时间
set_time_limit(0);
//网站根目录
define("SITE_ROOT", _DIR_);
//网站域名
define('DOMAIN_NAME', 'http://www.ukin.cc');
//版本常量(此方案不好,导致浏览器每天都要重新下载一次所有资源)
define("VERSION_TIMESTAMP", date("Ymd"));
//引入PDO文件(哎,虽然这里引入了这个文件,但大家各自为政,在每个model里面自己又再次引入此文件)
require_once(SITE_ROOT . '/db/' . 'pdo_mysql.php');
//引入路由控制文件router.php
require_once(SITE_ROOT . '/controllers/' . 'router.php');
?>
2. 路由文件: /controllers/router.php
<?php
/*
* 咚门:__autoload — 尝试加载未定义的类。通过定义这个函数来启用 类的自动加载 。
*
* 这个函数重载了PHP内置的autoload函数。当我们试图去初始化一个不存在的类时,这个‘魔术方法’允许我们拦截php所执行的动作。
* 通过使用__autoload函数,我们能够告诉php寻找包含此类的文件的位置。
* 假设你遵循了这篇文章中 类和文件名的命名约定 ,那么每当你初始化一个类时,你就不必手动去引入包含此类的文件了!
*/
//当类初始化时,自动引入相关文件(引入数据模型文件)
function __autoload($className)
{
//解析文件名,得到文件的存放路径,如News_Model表示存放在models文件夹里的news.php(这里是作者的命名约定)
list($filename, $suffix) = explode('_', $className);
//构成 model 文件的路径
$file = SITE_ROOT . '/models/' . strtolower($filename) . '.php';
//获取文件
if (file_exists($file)) {
//引入 model 文件
include_once($file);
} else {
//文件不存在
die("model 文件【$filename】不存在!");
}
}
// 获取请求参数(即 URL 参数),例如:http://localhost/index.php?login&a=index
$request = $_SERVER['QUERY_STRING'];
// 解析请求页面和其它GET变量
$parsed = explode('&', $request);
// 取得控制器名称:login (array_shift — 将 $parsed 的第一个单元移出并作为结果返回;将 $parsed 的长度减一并将所有其它单元向前移动一位,所有的数字键名将改为从零开始计数,键名将不变。)
$page = array_shift($parsed);
// 取得:a=index
$fun_action_a = array_shift($parsed);
// 取得操作方法名称:index
$fun_action = str_replace("a=", "", $fun_action_a);
/**
* 此文件会把所有的传入参数分派到相应的控制器中
*/
//检测是否已登录,如果未登录则把控制器和方法重置为登录页面
require_once(SITE_ROOT . '/public/' . 'check_session.php');
//$target = SITE_ROOT . '/controllers/' . $page . '.php';
//echo $fun_action;
if ($page == "") {
$page = "login";
$fun_action = "login";
}
//echo $fun_action;
// 拼接控制器文件的路径
$target = SITE_ROOT . '/controllers/' . $page . '.php';
if (file_exists($target)) {
// 引入相应的控制器文件
include_once($target);
// 拼接控制器类名。修改page变量,以符合命名规范(如$page="news",我们的约定是首字母大写,控制器的话就在后面加上“<strong>_Controller”</strong>,即News_Controller)
$class = ucfirst($page) . '_Controller';
// 初始化对应的控制器类
if (class_exists($class)) {
$controller = new $class;
} else {
die("控制器类名【$controller】不存在!");
}
} else {
//不能在controllers找到此文件
die("controller 文件【$page】不存在!");
}
//初始化控制器后,根据控制器方法参数决定调用的函数(默认调用 index() 函数)
switch ($fun_action) {
case "index":
$controller->index();
break;
case "index2":
$controller->index2();
break;
case "index3":
$controller->index3();
break;
case "add":
$controller->add();
break;
case "add2":
$controller->add2();
break;
case "add3":
$controller->add3();
break;
case "add4":
$controller->add4();
break;
case "add5":
$controller->add5();
break;
case "add6":
$controller->add6();
break;
case "add7":
$controller->add7();
break;
case "add8":
$controller->add8();
break;
case "add9":
$controller->add9();
break;
case "edit":
$controller->edit();
break;
case "detail":
$controller->detail();
break;
case "download":
$controller->download();
break;
case "login":
$controller->login();
break;
case "change_password":
$controller->change_password();
break;
case "reset_password":
$controller->reset_password();
break;
default:
$controller->index();
break;
}
?>
3. controller 之一: /controllers/users.php
<?php
/*
* 控制器处理页面提交的请求,初始化数据模型,从数据模型获取查询的数据
* 初始化视图交互方法,调用视图模板
* 将数据传送到视图模板,在视图页面中显示
*/
class Users_Controller {
// $template变量会保存与此控制器相关的"view(视图)"的文件名,不包括.php后缀
public $template = 'users';
public function index() {
//初始化数据模型
$usersModel = new Users_Model;
//从数据模块获取数据
$rs_value = $usersModel->index();
//初始化视图交互方法,并传入该控制器的template变量
$view = new View_Model($this->template,"index");
//把文章数据赋给视图模板
$view->assign('rs_value' , $rs_value);
}
public function add() {
//初始化数据模型
$usersModel = new Users_Model;
//从数据模块获取数据
$rs_value = $usersModel->add();
//初始化视图交互方法,并传入该控制器的template变量
$view = new View_Model($this->template,"add");
//把文章数据赋给视图模板
$view->assign('rs_value' , $rs_value);
}
}
?>
4. model 之一: /models/users.php
<?php
class Users_Model {
public function index() {
// Code
return $rs_value;
}
}
5. /models/view.php
<?php
/**
* 在我们的MVC框架中,处理视图的功能
* 接收控制器传送过来的控制器参数和对应的方法参数,组成视图文件路径
* 接收控制器赋予的变量,保存在data数组中,传送到视图页面文件中显示
*/
class View_Model
{
// 保存赋给视图模板的变量
private $data = array();
public $fun_action;
// 保存视图渲染状态
private $render = FALSE;
// 加载一个视图模板 $fun_action
public function __construct($template, $fun_action) {
// 拼接视图文件的路径。$template为控制器传递过来的参数,作为对应视图目录;$fun_action为控制器方法参数,对应该方法的视图
$file = SITE_ROOT . '/views/' . strtolower($template) . '/' .$fun_action. '.php';
if (file_exists($file)) {
/**
* 当模型对象销毁时才能渲染视图
* 如果现在就渲染视图,那么我们就不能给视图模板赋予变量
* 所以此处先保存要渲染的视图文件路径
*/
$this->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);
}
}
?>
- 以其中一个具体的 view 为例: /views/users/index.php
// 就不写具体代码了,
// 但注意,在 /model/view.php 中把 model 中返回的变量 $rs_value 赋值给了data[$variable],
// 所以要在 /views/users/index.php 中调用 model 返回的变量,需要用这样的格式:$data['rs_value']['某个具体的变量对应的键名']
- 其他(与 MVC 无关): /db/pdo_mysql.php
<?php
$dbms='mysql'; // 数据库类型 Oracle 用ODI,对于开发者来说,使用不同的数据库,只要改这个,不用记住那么多的函数了(mssql)
$host='192.168.1.1'; // 数据库主机
$dbname='test'; // 使用的数据库
$user='test'; // 数据库用户名
$pwd='test'; // 数据库密码
$dsn = "$dbms:host=$host;dbname=$dbname";
$dbh="";
Try {
$dbh = new PDO($dsn, $user, $pass); //初始化一个PDO对象,就是创建了数据库连接对象$dbh
$dbh->exec('SET names utf8');
} Catch(PDOException $e) {
// echo 'Error!: ',$e->getMessage(),"\n";
}
?>
网友评论