框架搭建
回顾
- MVC 是一种编程思想,通过 MVC 思想来组织项目中的代码
- MVC 由 M(模型),V(视图),C(控制器)组成
- 模型用来操作数据
- 视图用来显示数据的
- 控制器用来接收请求,并根据需求调用模型和视图
- 通过 c 和 a 参数确定路由,c 参数表示控制器,a 参数表示方法
框架搭建
问题
在上一讲 MVC 中,所有的文件都存放在站点下,不便于管理,我们需要将所有的文件分类存放。
创建框架目录
所有的代码分成两部分,一个部分代码是与具体的业务没有直接关系,用来支撑项目的运行,这部分称为框架代码(Framework),另一部分与具体项目相关,称为项目代码(Application)。
将上一讲的文件放到对应的目录中
将所有的类文件添加上命名空间
通过文件的地址做命名空间
创建 Framework.class.php 文件
在 Core 文件夹下创建 Framework.class.php 页面
定义路径常量
思路:将所有文件放到对应目录后,我们就围绕如何加载类去写代码。
思路:由于加载类需要路径,首先我们定义路径才常量
获取文件的绝对路径
获取目录分隔符
代码如下:
namespace Core;
class Framework{
// 定义路径常量
private static function initConst(){
define(‘DS’, DIRECTORY_SEPARATOR); // 定义目录分隔符
define(‘ROOT_PATH’, getcwd().DS); // 定义根目录路径
// 定义一级目录
define(‘APP_PATH’, ROOT_PATH.’Application’.DS); // 定义 Application 目录的路径
define(‘FRAMEWROK_PATH’, ROOT_PATH.’Framework’.DS);
// 定义二级目录
define(‘CONFIG_PATH’, APP_PATH.’Config’.DS);
define(‘CONTROLLER_PATH’, APP_PATH.’Controller’.DS);
define(‘MODEL_PATH’, APP_PATH.’Model’.DS);
define(‘VIEW_PATH’, APP_PATH.’View’.DS);
define(‘CORE_PATH’, FRAMEWROK_PATH.’Core’.DS);
define(‘LIB_PATH’, FRAMEWROK_PATH.’Lib’.DS);
}
}
加载配置文件
- 在 config 文件夹创建 config.php 页面
- 代码如下
<?php
return array(
// 数据库配置
‘database’ =>array(
‘dbname’ => ‘data’,
‘user’ => ‘root’,
‘pwd’ => ‘root’
),
// 应用程序配置
‘app’ => array(
‘default_platform’ => ‘Admin’,
‘default_controller’ => ‘Products’,
‘default_action’ => ‘list’
)
);
- 在 Framework 类中加载配置文件
private static function initConfig(){
$GLOBALS[‘config’]=require CONFIG_PATH.’config.php’;
}
确定路由
通过传递参数的方法确定路由
p: 平台
c:控制器
a:方法
在 URL 地址中访问
代码如下:
private static function initRoutes(){
$p=isset($_REQUEST[‘p’])?$_REQUEST[‘p’]:$GLOBALS[‘config’][‘app’][‘default_platform’];
$c=isset($_REQUEST[‘c’])?$_REQUEST[‘c’]:$GLOBALS[‘config’][‘app’][‘default_controller’];
$a=isset($_REQUEST[‘a’])?$_REQUEST[‘a’]:$GLOBALS[‘config’][‘app’][‘default_action’];
$p=ucfirst(strtolower($p)); // 首字母大写
$c=ucfirst(strtolower($c)); // 首字母大写
$a=strtolower($a); // 全部小写
define(‘PLATFORM_NAME’, $p); // 定义平台名称常量
define(‘CONTROLLER_NAME’, $c); // 定义控制器名称常量
define(‘ACTION_NAME’, $a); // 定义方法名称常量
define(‘__URL__’, CONTROLLER_PATH.$p.DS); // 当前请求的控制器的路径
define(‘__VIEW__’, VIEW_PATH.$p.DS); // 当前请求视图的路径
}
自动加载类
/*
* 加载类的方法
* @param $class_name string 需要加载的类
*/
private static function loadClass($class_name) {
$namespace= dirname($class_name); // 获取命名空间
$class_name= basename($class_name); // 类名
if(in_array($namespace,array(‘Core’,’Lib’)))
$path=FRAMEWROK_PATH.$namespace.DS.$class_name.’.class.php’;
elseif($namespace==’Model’)
$path=MODEL_PATH.$class_name.’.class.php’;
else
$path=__URL__.$class_name.’.class.php’;
// 如果文件存在就加载
if(isset($path) && file_exists($path))
require $path;
}
注册加载类
加载类的方法写到类中不会自动执行,需要将加载类的方法注册到__autoload() 栈中
private static function initRegisterLoadClass(){
spl_autoload_register(‘self::loadClass’);
}
请求分发
private static function initDispatch(){
、$controller_name=’\Controller\\’.PLATFORM_NAME.’\\’.CONTROLLER_NAME.’Controller’; // 拼接控制器类名
$action_name=ACTION_NAME.’Action’; // 拼接方法名
// 请求分发
$controller=new $controller_name();
$controller->$action_name();
}
封装 run() 方法
public static function run(){
self::initConst();
self::initConfig();
self::initRoutes();
self::initRegisterLoadClass();
self::initDispatch();
}
在 index.php 页面执行 run() 方法
执行 run() 方法就会启动框架
注意:现在的 index.php 页面只起接受请求的作用,接受请求后就会启动框架,index.php 称为 “入口文件”
由于在每次请求的都是入口文件,所以在框架中 “.” 表示入门文件所在的目录。
项目中需要更改代码的地方
测试,成功
总结:框架搭建的步骤
- 创建框架文件夹
- 将项目文件放到对应的文件夹中
- 在原来的类文件上添加命名空间
- 定义了路径常量
- 确定路由
- 加载类的方法
- 注册自动加载类
- 请求分发
- 引入配置文件
- 调试
完善删除功能
删除记录后,显示一个消息页面,n 秒以后跳转到指定的地址上。
所有控制器都会用到跳转功能,所以将跳转的方法写到基础控制器中
步骤
- 在 Core 文件夹中创建 Controller.class.php
<?php
/*
* 基础控制器
*/
namespace Core;
abstract class Controller{
// 封装 jump 方法, 正确跳转
protected function success($url,$info=”,$time=1){
$this->jump($url, $info, $time, true);
}
// 封装 jump() 方法,错误跳转
protected function error($url,$info=”,$time=3){
$this->jump($url, $info, $time, false);
}
/*
* 跳转的方法
* @param $url string 跳转的 URL 地址
* @param $info string 显示的信息
* @param $time int 页面停留时间
* @param $success bool 显示正确或错误的图标
*/
private function jump($url,$info=”,$time=3,$success=true){
if($info==”)
header (“location:{$url}”);
else{
$img=’true.fw.png’;
$class=’success’;
if(!$success){
$img=’error.fw.png’;
$class=’error’;
}
echo <<<str
<!doctype html>
<html>
<head>
<meta charset=”utf-8″>
<meta http-equiv=”refresh” content=”{$time};url={$url}”>
<title> 无标题文档 </title>
<style type=”text/css”>
body{
text-align:center;
padding-top:100px;
font-size:24px;
}
.success{
color:#090;
}
.error{
color:#F00;
}
</style>
</head>
<body>
<img src=”/Public/images/{$img}”>
<h2 class=”{$class}”>{$info}</h2>
{$time} 秒以后跳转
</body>
</html>
str;
}
}
}
- 所有的控制器都继承基础控制器
- 在控制器中调用 success() 和 error()