PHP核心之MVC设计模式
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
Model
ProductsModel.class.php
View
Admin
products_list.html
Home
Framework
Core
Framework.class.php
Model.class.php
MyPDO.class.php
Lib
Public
images
error.fw.png
success.fw.png
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;
}
}
}
總結
以上是生活随笔為你收集整理的PHP核心之MVC设计模式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《精灵宝可梦Let's Go伊
- 下一篇: 倩女幽魂手游89级异人卡级攻略 异人怎么