MVC设计模式
MVC概述
- MVC介绍
- MVC是一个编程思想,是一种设计模式
- 思想:将一个功能分解成3个部分
- Model(模型):处理与数据有关的逻辑
- View(视图):显示页面
- Controller(控制器):处理业务逻辑
- 控制器用来接收请求
- 以后不能直接请求模型和视图
MVC演化
显示商品
# index.php
<?php
//自动加载类
spl_autoload_register(function($class_name){
require "./{$class_name}.class.php";
});
//连接数据库
$param=array(
'user' => 'root',
'pwd' => '',
'dbname' => 'data'
);
$mypdo= MyPDO::getInstance($param);
//获取商品数据
$list=$mypdo->fetchAll('select * from products');
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>显示商品</title>
</head>
<body>
<table border='1' width='980' bordercolor='#000'>
<tr>
<th>编号</th> <th>名称</th> <th>价格</th> <th>删除</th>
</tr>
<?php foreach($list as $rows):?>
<tr>
<td><?=$rows['proID']?></td>
<td><?=$rows['proname']?></td>
<td><?=$rows['proprice']?></td>
<td><a href="">删除</a></td>
</tr>
<?php endforeach;?>
</table>
</body>
</html>
演化一:分离视图
# index.php
<?php
//自动加载类
spl_autoload_register(function($class_name){
require "./{$class_name}.class.php";
});
//连接数据库
$param=array(
'user' => 'root',
'pwd' => '',
'dbname' => 'data'
);
$mypdo= MyPDO::getInstance($param);
//获取商品数据
$list=$mypdo->fetchAll('select * from products');
require './products_list.html';
?>
# products_list.html
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<title>显示商品</title>
</head>
<body>
<table border='1' width='980' bordercolor='#000'>
<tr>
<th>编号</th> <th>名称</th> <th>价格</th> <th>删除</th>
</tr>
<?php foreach($list as $rows):?>
<tr>
<td><?=$rows['proID']?></td>
<td><?=$rows['proname']?></td>
<td><?=$rows['proprice']?></td>
<td><a href="">删除</a></td>
</tr>
<?php endforeach;?>
</table>
</body>
</html>
演化二:分离模型
- 模型的规则
- 一个表对应一个模型,表名和模型名必须一致
- 模型以Model结尾(不是必须的)
# index.php
<?php
//自动加载类
spl_autoload_register(function($class_name){
require "./{$class_name}.class.php";
});
// 实例化数据模型
$model= new ProductsModel();
$list= $model->getList();
// 加载视图
require './products_list.html';
?>
# products_list.html
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<title>显示商品</title>
</head>
<body>
<table border='1' width='980' bordercolor='#000'>
<tr>
<th>编号</th> <th>名称</th> <th>价格</th> <th>删除</th>
</tr>
<?php foreach($list as $rows):?>
<tr>
<td><?=$rows['proID']?></td>
<td><?=$rows['proname']?></td>
<td><?=$rows['proprice']?></td>
<td><a href="">删除</a></td>
</tr>
<?php endforeach;?>
</table>
</body>
</html>
# ProductsModel.class.php
<?php
//products模型用来操作products表
class ProductsModel {
// 获取products表的数据
public function getList(){
// 连接数据库
$param= array(
'user' => 'root',
'pwd' => '',
'dbname' => 'data'
);
$mypdo= MyPDO::getInstance($param);
// 获取商品数据
return $mypdo->fetchAll('select * from products');
}
}
?>
演化三:分离基础模型
- 概念
- 连接数据库的代码每个模型都要使用
- 所有我们需要将连接数据库的代码封装到基础模型类中(Model)
# index.php
<?php
//自动加载类
spl_autoload_register(function($class_name){
require "./{$class_name}.class.php";
});
// 实例化数据模型
$model= new ProductsModel();
$list= $model->getList();
// 加载视图
require './products_list.html';
?>
# products_list.html
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<title>显示商品</title>
</head>
<body>
<table border='1' width='980' bordercolor='#000'>
<tr>
<th>编号</th> <th>名称</th> <th>价格</th> <th>删除</th>
</tr>
<?php foreach($list as $rows):?>
<tr>
<td><?=$rows['proID']?></td>
<td><?=$rows['proname']?></td>
<td><?=$rows['proprice']?></td>
<td><a href="">删除</a></td>
</tr>
<?php endforeach;?>
</table>
</body>
</html>
# Model.class.php
<?php
// 基础模型
class Model {
protected $mypdo;
public function __construct(){
$this->initMyPDO();
}
// 连接数据库
private function initMyPDO(){
$param= array(
'user' => 'root',
'pwd' => '',
'dbname' => 'data'
);
$this->mypdo= MyPDO::getInstance($param);
}
}
?>
# ProductsModel.class.php
<?php
//products模型用来操作products表
class ProductsModel extends Model{
// 获取products表的数据
public function getList(){
// 获取商品数据
return $this->mypdo->fetchAll('select * from products');
}
}
?>
演化四:分离控制器
-
概念
- 控制器代码放在index.php页面中是不合理的
- 因为项目中的控制器会很多,而index.php只有一个
- 所以需要将控制器分离开来
-
控制器的规则
- 一个模块必须对应一个控制器
- 控制器以Controller结尾(不是必须的)
- 控制器中的方法以Action结尾(不是必须的)
- 目的防止方法名是PHP关键字
-
请求分发
- 每次请求都要从index.php进入,所以index.php又叫入口文件
- 通过在url地址上传递参数来寻址
c
控制器a
方法
# index.php
<?php
//自动加载类
spl_autoload_register(function($class_name){
require "./{$class_name}.class.php";
});
//确定路由
$c= $_GET['c']??'Products'; //控制器
$a= $_GET['a']??'list'; //方法
$c= ucfirst(strtolower($c)); //首字母大写
$a= strtolower($a); //转成小写
$controller_name= $c.'Controller'; //拼接控制器类名
$action_name= $a.'Action'; //拼接方法名
//请求分发
$obj= new $controller_name();
$obj->$action_name();
?>
# products_list.html
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<title>显示商品</title>
</head>
<body>
<table border='1' width='980' bordercolor='#000'>
<tr>
<th>编号</th> <th>名称</th> <th>价格</th> <th>删除</th>
</tr>
<?php foreach($list as $rows):?>
<tr>
<td><?=$rows['proID']?></td>
<td><?=$rows['proname']?></td>
<td><?=$rows['proprice']?></td>
<td><a href="">删除</a></td>
</tr>
<?php endforeach;?>
</table>
</body>
</html>
# Model.class.php
<?php
// 基础模型
class Model {
protected $mypdo;
public function __construct(){
$this->initMyPDO();
}
// 连接数据库
private function initMyPDO(){
$param= array(
'user' => 'root',
'pwd' => '',
'dbname' => 'data'
);
$this->mypdo= MyPDO::getInstance($param);
}
}
?>
# ProductsModel.class.php
<?php
//products模型用来操作products表
class ProductsModel extends Model{
// 获取products表的数据
public function getList(){
// 获取商品数据
return $this->mypdo->fetchAll('select * from products');
}
}
?>
# ProductsController.class.php
<?php
// 商品模块
class ProductsController {
// 获取商品列表
public function listAction(){
// 实例化数据模型
$model= new ProductsModel();
$list= $model->getList();
// 加载视图
require './products_list.html';
}
}
?>
删除商品
# index.php
<?php
//自动加载类
spl_autoload_register(function($class_name){
require "./{$class_name}.class.php";
});
//确定路由
$c= $_GET['c']??'Products'; //控制器
$a= $_GET['a']??'list'; //方法
$c= ucfirst(strtolower($c)); //首字母大写
$a= strtolower($a); //转成小写
$controller_name= $c.'Controller'; //拼接控制器类名
$action_name= $a.'Action'; //拼接方法名
//请求分发
$obj= new $controller_name();
$obj->$action_name();
?>
# products_list.html
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<title>显示商品</title>
</head>
<body>
<table border='1' width='980' bordercolor='#000'>
<tr>
<th>编号</th>
<th>名称</th>
<th>价格</th>
<th>删除</th>
</tr>
<?php foreach($list as $rows):?>
<tr>
<td><?=$rows['proID']?></td>
<td><?=$rows['proname']?></td>
<td><?=$rows['proprice']?></td>
<td><a href="index.php?c=Products&a=del&proid=<?=$rows['proID']?>" onclick="return confirm('确定要删除吗')">删除</a></td>
</tr>
<?php endforeach;?>
</table>
</body>
</html>
# ProductsController.class.php
<?php
// 商品模块
class ProductsController {
// 获取商品列表
public function listAction(){
// 实例化数据模型
$model= new ProductsModel();
$list= $model->getList();
// 加载视图
require './products_list.html';
}
public function delAction(){
$id= (int)$_GET['proid'];
$model= new ProductsModel();
if($model->del($id)){
header('location:index.php?c=Products&a=list');
}else{
echo '删除失败!';
exit;
}
}
}
?>
# ProductsModel.class.php
<?php
//products模型用来操作products表
class ProductsModel extends Model{
// 获取products表的数据
public function getList(){
// 获取商品数据
return $this->mypdo->fetchAll('select * from products');
}
// 删除products表的数据
public function del($proid){
// 删除商品数据
return $this->mypdo->exec("delete from products where proID={$proid}");
}
}
?>
框架目录
创建目录结构
-
Application 应用程序
- Config 配置文件
- Controller 控制器
- Admin 后台控制器
- Home 前台控制器
- Model 模型
- View 视图
- Admin 后台视图
- Home 前台视图
-
Framework 框架
- Core 核心
- Lib 扩展
-
Public 静态资源
-
Traits 复用代码
文件分类存放
-
概念
- 由于每次都请求入口文件,所以”.“表示入口文件所在的目录
-
Application
- Config
- config.php
- Controller
- Admin
- ProductsController.class.php
- Home
- Admin
- Model
- ProductsModel.class.php
- View
- Admin
- products_list.html
- Home
- Admin
- Config
-
Framework
- Core
- Framework.class.php
- Model.class.php
- MyPDO.class.php
- Lib
- Core
-
Public
- images
- error.fw.png
- success.fw.png
- images
-
Traits
- Jump.class.php
-
index.php
添加命名空间
- 概念
- 通过文件目录地址做命名空间
- 这样获取了命名空间就能知道文件存放的地址
# Model.class.php
<?php
namespace Core;
class Model {
...
}
?>
# MyPDO.class.php
<?php
namespace Core;
class MyPDO {
...
}
?>
# ProductsModel.class.php
<?php
namespace Model;
class ProductsModel extends Model {
...
}
?>
# ProductsController.class.php
<?php
namespace ControllerAdmin;
class ProductsController {
...
}
?>
框架类实现
定义路径常量
-
概念
- 由于文件路径使用频率很高,而且路径比较长
- 所以将固定不变的路径定义成路径常量
-
知识点
getcwd()
入口文件的绝对路径- windows下默认的目录分隔符是
,Linux下默认的目录分隔符是
/
- DIRECTORY_SEPARATOR常量根据不同的操作系统返回不同的目录分隔符
# Framework.class.php
private static function initConst(){
define('DS', DIRECTORY_SEPARATOR); //定义目录分隔符
define('ROOT_PATH', getcwd().DS); //入口文件所在的目录
define('APP_PATH', ROOT_PATH.'Application'.DS); //application目录
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('FRAMEWORK_PATH', ROOT_PATH.'Framework'.DS);
define('CORE_PATH', FRAMEWORK_PATH.'Core'.DS);
define('LIB_PATH', FRAMEWORK_PATH.'Lib'.DS);
define('TRAITS_PATH', ROOT_PATH.'Traits'.DS);
}
引入配置文件
- 概述
- 在PHP7.0之前,常量不能保存数组和对象
# config.php
return array(
//数据库配置
'database'=>array(),
//应用程序配置
'app'=>array(
'dp' => 'Admin', //默认平台
'dc' => 'Products', //默认控制器
'da' => 'list' //默认方法
)
);
# Framework.class.php
private static function initConfig(){
$GLOBALS['config']= require CONFIG_PATH.'config.php';
}
确定路由
- 概述
p
平台[platform]c
控制器[controller]a
方法[action]
# Framework.class.php
private static function initRoutes(){
$p= $_GET['p']??$GLOBALS['config']['app']['dp'];
$c= $_GET['c']??$GLOBALS['config']['app']['dc'];
$a= $_GET['a']??$GLOBALS['config']['app']['da'];
$p= ucfirst(strtolower($p));
$c= ucfirst(strtolower($c));
$a= strtolower($a);
define('PLATFROM_NAME', $p); //平台名常量
define('CONTROLLER_NAME', $c); //控制器名常量
define('ACTION_NAME', $a); //方法名常量
define('__URL__', CONTROLLER_PATH.$p.DS); //当前请求控制器的目录地址
define('__VIEW__',VIEW_PATH.$p.DS); //当前视图的目录地址
}
自动加载类
# Framework.class.php
private static function initAutoLoad(){
spl_autoload_register(function($class_name){
$namespace= dirname($class_name); //命名空间
$class_name= basename($class_name); //类名
if(in_array($namespace, array('Core','Lib'))) //命名空间在Core和Lib下
$path= FRAMEWORK_PATH.$namespace.DS.$class_name.'.class.php';
elseif($namespace=='Model') //文件在Model下
$path=MODEL_PATH.$class_name.'.class.php';
elseif($namespace=='Traits') //文件在Traits下
$path=TRAITS_PATH.$class_name.'.class.php';
else //控制器
$path=CONTROLLER_PATH.PLATFROM_NAME.DS.$class_name.'.class.php';
if(file_exists($path) && is_file($path))
require $path;
});
}
请求分发
# Framework.class.php
private static function initDispatch(){
$controller_name='Controller\'.PLATFROM_NAME.'\'.CONTROLLER_NAME.'Controller'; //拼接控制器类名
$action_name=ACTION_NAME.'Action'; //拼接方法名
$obj=new $controller_name();
$obj->$action_name();
}
封装run()方法
# Framework.class.php
class Framework{
//启动框架
public static function run(){
self::initConst();
self::initConfig();
self::initRoutes();
self::initAutoLoad();
self::initDispatch();
}
}
在入口中调用run()方法
- 概述
- run()方法调用后就启动了框架
# index.php
<?php
require './Framework/Core/Framework.class.php';
Framework::run();
?>
SQL方法封装
生成insert语句
- 知识点
array_keys($arr)
返回数组的键array_values($arr)
返回数组的值array_map(fun(), $arr)
将函数作用到数组中的每个值上,并返回带有新值的数组
$table= 'products'; //表名
//插入的数据
$data['proid']='007';
$data['proname']='钢笔';
$data['proprice']=120;
//第一步:拼接字段名
$keys=array_keys($data); //获取所有的字段名
$keys=array_map(function($key){ //在所有的字段名上添加反引号
return "`{$key}`";
},$keys);
$keys=implode(',',$keys); //字段名用逗号连接起来
//第二步:拼接值
$values=array_values($data); //获取所有的值
$values=array_map(function($value){ //所有的值上添加单引号
return "'{$value}'";
},$values);
$values=implode(',',$values); //值通过逗号连接起来
//第三步:拼接SQL语句
echo $sql="insert into `{$table}` ($keys) values ($values)";
生成更新语句
- 知识点
array_search(value, $arr)
在数组中搜索某个键值,并返回对应的键名
$table='products'; //表名
$data['proname']='钢笔';
$data['proprice']=120;
$data['proID']='111';
//获取主键
function getPrimaryKey($table) {
//连接数据库
$link=mysqli_connect('localhost','root','root','data');
mysqli_set_charset($link,'utf8');
//查看表结构
$rs=mysqli_query($link,"desc `{$table}`");
//循环判断主键
while($rows=mysqli_fetch_assoc($rs)){
if($rows['Key']=='PRI')
return $rows['Field'];
}
}
//第一步:获取非主键
$keys=array_keys($data); //获取所有键
$pk=getPrimaryKey($table); //获取主键
$index=array_search($pk,$keys); //返回主键在数组中的下标
unset($keys[$index]); //删除主键
//第二步:拼接`键`='值'的形式
$keys=array_map(function($key) use ($data){
return "`{$key}`='{$data[$key]}'";
},$keys);
$keys=implode(',',$keys);
//第三步:拼接SQL语句
echo $sql="update `{$table}` set $keys where $pk='{$data[$pk]}'";
生成select语句
- 知识点
is_array($arr)
判断变量是否为数组
function select($table,$cond=array()) {
$sql="select * from `{$table}` where 1";
//拼接条件
if(!empty($cond)){
foreach($cond as $k=>$v){
if(is_array($v)){ //条件的值是数组类型
switch($v[0]){ //$v[0]保存的是符号,$v[1]是值
case 'eq': //等于 equal
$op='=';
break;
case 'gt': //大于 greater than
$op='>';
break;
case 'lt':
$op='<';
break;
case 'gte':
case 'egt':
$op='>=';
break;
case 'lte':
case 'elt':
$op='<=';
break;
case 'neq':
$op='<>';
break;
}
$sql.=" and `$k` $op '$v[1]'";
}else{
$sql.=" and `$k`='$v'";
}
}
}
return $sql;
}
//测试
$table='products'; //表名
$cond=array(
'proname' => '钢笔',
'proprice' => array('eq','12'),
'aa' => array('gt',10),
'bb' => array('lt',20),
);
echo select($table),'<br>';
echo select($table,$cond);
获取表名
- 知识点
get_class($this)
返回实例对象的类(包括命名空间)basename($path)
返回路径中的文件名部分substr($str, startNum, endNum)
截取字符串
class Model {
private $table;
public function __construct($table='') {
if($table!='') //直接给基础模型传递表名
$this->table=$table;
else { //实例化子类模型
$this->table=substr(basename(get_class($this)),0,-5);
}
echo $this->table,'<br>';
}
}
在项目中封装万能的增、删、改、查
- 概念
- 由于封装的方法可以操作所有的表
- 可以将这些方法封装在基础模型中
<?php
namespace Core;
//基础模型
class Model {
protected $mypdo;
private $table; //表名
private $pk; //主键
public function __construct($table=''){
$this->initMyPDO();
$this->initTable($table);
$this->getPrimaryKey();
}
//连接数据库
private function initMyPDO() {
$this->mypdo= MyPDO::getInstance($GLOBALS['config']['database']);
}
//获取表名
private function initTable($table){
if($table!='') //直接给基础模型传递表名
$this->table=$table;
else { //实例化子类模型
$this->table=substr(basename(get_class($this)),0,-5);
}
}
//获取主键
private function getPrimaryKey() {
$rs=$this->mypdo->fetchAll("desc `{$this->table}`");
foreach($rs as $rows){
if($rows['Key']=='PRI'){
$this->pk=$rows['Field'];
break;
}
}
}
//万能的插入
public function insert($data){
$keys=array_keys($data); //获取所有的字段名
$keys=array_map(function($key){ //在所有的字段名上添加反引号
return "`{$key}`";
},$keys);
$keys=implode(',',$keys); //字段名用逗号连接起来
$values=array_values($data); //获取所有的值
$values=array_map(function($value){ //所有的值上添加单引号
return "'{$value}'";
},$values);
$values=implode(',',$values); //值通过逗号连接起来
$sql="insert into `{$this->table}` ($keys) values ($values)";
return $this->mypdo->exec($sql);
}
//万能的更新
public function update($data){
$keys=array_keys($data); //获取所有键
$index=array_search($this->pk,$keys); //返回主键在数组中的下标
unset($keys[$index]); //删除主键
$keys=array_map(function($key) use ($data){
return "`{$key}`='{$data[$key]}'";
},$keys);
$keys=implode(',',$keys);
$sql="update `{$this->table}` set $keys where $this->pk='{$data[$this->pk]}'";
return $this->mypdo->exec($sql);
}
//删除
public function delete($id){
$sql="delete from `{$this->table}` where `{$this->pk}`='$id'";
return $this->mypdo->exec($sql);
}
//查询,返回二维数组
public function select($cond=array()){
$sql="select * from `{$this->table}` where 1";
if(!empty($cond)){
foreach($cond as $k=>$v){
if(is_array($v)){ //条件的值是数组类型
switch($v[0]){ //$v[0]保存的是符号,$v[1]是值
case 'eq': //等于 equal
$op='=';
break;
case 'gt': //大于 greater than
$op='>';
break;
case 'lt':
$op='<';
break;
case 'gte':
case 'egt':
$op='>=';
break;
case 'lte':
case 'elt':
$op='<=';
break;
case 'neq':
$op='<>';
break;
}
$sql.=" and `$k` $op '$v[1]'";
}else{
$sql.=" and `$k`='$v'";
}
}
}
return $this->mypdo->fetchAll($sql);
}
//查询,返回一维数组
public function find($id){
$sql="select * from `{$this->table}` where `{$this->pk}`='$id'";
return $this->mypdo->fetchRow($sql);
}
}
?>
MVC框架代码
入口文件
# index.php
<?php
require './Framework/Core/Framework.class.php';
Framework::run();
?>
框架文件
# Framework/Core/Framework.class.php
<?php
class Framework{
//启动框架
public static function run(){
self::initConst();
self::initConfig();
self::initRoutes();
self::initAutoLoad();
self::initDispatch();
}
//定义路径常量
private static function initConst(){
define('DS', DIRECTORY_SEPARATOR); //定义目录分隔符
define('ROOT_PATH', getcwd().DS); //入口文件所在的目录
define('APP_PATH', ROOT_PATH.'Application'.DS); //application目录
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('FRAMEWORK_PATH', ROOT_PATH.'Framework'.DS);
define('CORE_PATH', FRAMEWORK_PATH.'Core'.DS);
define('LIB_PATH', FRAMEWORK_PATH.'Lib'.DS);
define('TRAITS_PATH', ROOT_PATH.'Traits'.DS);
}
//引入配置文件
private static function initConfig(){
$GLOBALS['config']=require CONFIG_PATH.'config.php';
}
//确定路由
private static function initRoutes(){
$p=$_GET['p']??$GLOBALS['config']['app']['dp'];
$c=$_GET['c']??$GLOBALS['config']['app']['dc'];
$a=$_GET['a']??$GLOBALS['config']['app']['da'];
$p=ucfirst(strtolower($p));
$c=ucfirst(strtolower($c)); //首字母大写
$a=strtolower($a); //转成小写
define('PLATFROM_NAME', $p); //平台名常量
define('CONTROLLER_NAME', $c); //控制器名常量
define('ACTION_NAME', $a); //方法名常量
define('__URL__', CONTROLLER_PATH.$p.DS); //当前请求控制器的目录地址
define('__VIEW__',VIEW_PATH.$p.DS); //当前视图的目录地址
}
//自动加载类
private static function initAutoLoad(){
spl_autoload_register(function($class_name){
$namespace= dirname($class_name); //命名空间
$class_name= basename($class_name); //类名
if(in_array($namespace, array('Core','Lib'))) //命名空间在Core和Lib下
$path= FRAMEWORK_PATH.$namespace.DS.$class_name.'.class.php';
elseif($namespace=='Model') //文件在Model下
$path=MODEL_PATH.$class_name.'.class.php';
elseif($namespace=='Traits') //文件在Traits下
$path=TRAITS_PATH.$class_name.'.class.php';
else //控制器
$path=CONTROLLER_PATH.PLATFROM_NAME.DS.$class_name.'.class.php';
if(file_exists($path) && is_file($path))
require $path;
});
}
//请求分发
private static function initDispatch(){
$controller_name='Controller\'.PLATFROM_NAME.'\'.CONTROLLER_NAME.'Controller'; //拼接控制器类名
$action_name=ACTION_NAME.'Action'; //拼接方法名
$obj=new $controller_name();
$obj->$action_name();
}
}
配置文件
# Application/Config/config.php
<?php
return array(
//数据库配置
'database'=>array(),
//应用程序配置
'app'=>array(
'dp' => 'Admin', //默认平台
'dc' => 'Products', //默认控制器
'da' => 'list' //默认方法
)
);
?>
基础模型
# Framework/Core/Model.class.php
<?php
namespace Core;
class Model {
protected $mypdo;
public function __construct(){
$this->initMyPDO();
}
// 连接数据库
private function initMyPDO(){
$this->mypdo= MyPDO::getInstance($GLOBALS['config']['database']);
}
}
?>
PDO数据库
# Framework/Core/MyPDO.class.php
<?php
namespace Core;
class MyPDO{
private $type; //数据库类别
private $host; //主机地址
private $port; //端口号
private $dbname; //数据库名
private $charset; //字符集
private $user; //用户名
private $pwd; //密码
private $pdo; //保存PDO对象
private static $instance;
private function __construct($param) {
$this->initParam($param);
$this->initPDO();
$this->initException();
}
private function __clone() {
}
public static function getInstance($param=array()){
if(!self::$instance instanceof self)
self::$instance=new self($param);
return self::$instance;
}
//初始化参数
private function initParam($param){
$this->type=$param['type']??'mysql';
$this->host=$param['host']??'127.0.0.1';
$this->port=$param['port']??'3306';
$this->dbname=$param['dbname']??'data';
$this->charset=$param['charset']??'utf8';
$this->user=$param['user']??'root';
$this->pwd=$param['pwd']??'';
}
//初始化PDO
private function initPDO(){
try{
$dsn="{$this->type}:host={$this->host};port={$this->port};dbname={$this->dbname};charset={$this->charset}";
$this->pdo=new PDO($dsn, $this->user, $this->pwd);
} catch (PDOException $ex) {
$this->showException($ex);
exit;
}
}
//显示异常
private function showException($ex,$sql=''){
if($sql!=''){
echo 'SQL语句执行失败<br>';
echo '错误的SQL语句是:'.$sql,'<br>';
}
echo '错误编号:'.$ex->getCode(),'<br>';
echo '错误行号:'.$ex->getLine(),'<br>';
echo '错误文件:'.$ex->getFile(),'<br>';
echo '错误信息:'.$ex->getMessage(),'<br>';
}
//设置异常模式
private function initException(){
$this->pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}
//执行增、删、改操作
public function exec($sql){
try{
return $this->pdo->exec($sql);
} catch (PDOException $ex) {
$this->showException($ex, $sql);
exit;
}
}
//获取自动增长的编号
public function lastInsertId(){
return $this->pdo->lastInsertId();
}
//判断匹配的类型
private function fetchType($type){
switch ($type){
case 'num':
return PDO::FETCH_NUM;
case 'both':
return PDO::FETCH_BOTH;
case 'obj':
return PDO::FETCH_OBJ;
default:
return PDO::FETCH_ASSOC;
}
}
//获取所有数据 ,返回二维数组
public function fetchAll($sql,$type='assoc'){
try{
$stmt=$this->pdo->query($sql); //获取PDOStatement对象
$type= $this->fetchType($type); //获取匹配方法
return $stmt->fetchAll($type);
} catch (Exception $ex) {
$this->showException($ex, $sql);
}
}
//获取一维数组
public function fetchRow($sql,$type='assoc'){
try{
$stmt=$this->pdo->query($sql); //获取PDOStatement对象
$type= $this->fetchType($type); //获取匹配方法
return $stmt->fetch($type);
} catch (Exception $ex) {
$this->showException($ex, $sql);
exit;
}
}
//返回一行一列
public function fetchColumn($sql){
try{
$stmt=$this->pdo->query($sql);
return $stmt->fetchColumn();
} catch (Exception $ex) {
$this->showException($ex, $sql);
exit;
}
}
}
?>
控制器
# Application/Controller/Admin/ProductsController.class.php
<?php
namespace ControllerAdmin;
// 商品模块
class ProductsController {
use TraitsJump;
// 获取商品列表
public function listAction(){
// 实例化数据模型
$model= new ModelProductsModel();
$list= $model->getList();
// 加载视图
require __VIEW__.'products_list.html';
}
public function delAction(){
$id= (int)$_GET['proid'];
$model= new ModelProductsModel();
if($model->del($id)){
$this->success('index.php?p=Admin&c=Products&a=list', '删除成功');
}else{
$this->error('index.php?p=admin&c=Products&a=list', '删除失败');
}
}
}
?>
方法模型
# Application/Model/ProductsModel.class.php
<?php
namespace Model;
//products模型用来操作products表
class ProductsModel extends CoreModel{
// 获取products表的数据
public function getList(){
// 获取商品数据
return $this->mypdo->fetchAll('select * from products');
}
// 删除products表的数据
public function del($proid){
// 删除商品数据
return $this->mypdo->exec("delete from products where proID={$proid}");
}
}
?>
视图
# Application/View/Admin/products_list.html
<!Doctype html>
<html>
<head>
<meta charset="utf-8">
<title>显示商品</title>
</head>
<body>
<table border='1' width='980' bordercolor='#000'>
<tr>
<th>编号</th>
<th>名称</th>
<th>价格</th>
<th>删除</th>
</tr>
<?php foreach($list as $rows):?>
<tr>
<td><?=$rows['proID']?></td>
<td><?=$rows['proname']?></td>
<td><?=$rows['proprice']?></td>
<td><a href="index.php?p=Admin&c=Products&a=del&proid=<?=$rows['proID']?>" onclick="return confirm('确定要删除吗')">删除</a></td>
</tr>
<?php endforeach;?>
</table>
</body>
</html>
复用跳转
# Traits/Jump.class.php
<?php
//跳转的插件
namespace Traits;
trait Jump{
//封装成功的跳转
public function success($url,$info='',$time=1){
$this->redirect($url, $info, $time, 'success');
}
//封装失败跳转
public function error($url,$info='',$time=3){
$this->redirect($url, $info, $time, 'error');
}
/*
* 作用:跳转的方法
* @param $url string 跳转的地址
* @param $info string 显示信息
* @param $time int 停留时间
* @param $flag string 显示模式 success|error
*/
private function redirect($url,$info,$time,$flag){
if($info=='')
header ("location:{$url}");
else{
echo <<<str
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--
<meta http-equiv="refresh" content="3;http://www.php.com"/>
-->
<title>Document</title>
<style>
body{
text-align: center;
font-family: '微软雅黑';
font-size: 18px;
}
#success,#error{
font-size: 36px;
margin: 10px auto;
}
#success{
color: #090;
}
#error{
color: #F00;
}
</style>
</head>
<body>
<img src="./Public/images/{$flag}.fw.png">
<div id='{$flag}'>{$info}</div>
<div><span id='t'>{$time}</span>秒以后跳转</div>
</body>
</html>
<script>
window.onload=function(){
var t={$time};
setInterval(function(){
document.getElementById('t').innerHTML=--t;
if(t==0)
location.href='index.php';
},1000)
}
</script>
str;
exit;
}
}
}