PHP核心之MVC设计模式
MVC設(shè)計(jì)模式
MVC概述
MVC介紹
MVC是一個編程思想,是一種設(shè)計(jì)模式
思想:將一個功能分解成3個部分
Model(模型):處理與數(shù)據(jù)有關(guān)的邏輯
View(視圖):顯示頁面
Controller(控制器):處理業(yè)務(wù)邏輯
控制器用來接收請求
以后不能直接請求模型和視圖
MVC演化
顯示商品
# index.php
<?php
//自動加載類
spl_autoload_register(function($class_name){
require "./{$class_name}.class.php";
});
//連接數(shù)據(jù)庫
$param=array(
'user' => 'root',
'pwd' => '',
'dbname' => 'data'
);
$mypdo= MyPDO::getInstance($param);
//獲取商品數(shù)據(jù)
$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>價(jià)格</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";
});
//連接數(shù)據(jù)庫
$param=array(
'user' => 'root',
'pwd' => '',
'dbname' => 'data'
);
$mypdo= MyPDO::getInstance($param);
//獲取商品數(shù)據(jù)
$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>價(jià)格</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>
演化二:分離模型
模型的規(guī)則
一個表對應(yīng)一個模型,表名和模型名必須一致
模型以Model結(jié)尾(不是必須的)
# index.php
<?php
//自動加載類
spl_autoload_register(function($class_name){
require "./{$class_name}.class.php";
});
// 實(shí)例化數(shù)據(jù)模型
$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>價(jià)格</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表的數(shù)據(jù)
public function getList(){
// 連接數(shù)據(jù)庫
$param= array(
'user' => 'root',
'pwd' => '',
'dbname' => 'data'
);
$mypdo= MyPDO::getInstance($param);
// 獲取商品數(shù)據(jù)
return $mypdo->fetchAll('select * from products');
}
}
?>
演化三:分離基礎(chǔ)模型
概念
連接數(shù)據(jù)庫的代碼每個模型都要使用
所有我們需要將連接數(shù)據(jù)庫的代碼封裝到基礎(chǔ)模型類中(Model)
# index.php
<?php
//自動加載類
spl_autoload_register(function($class_name){
require "./{$class_name}.class.php";
});
// 實(shí)例化數(shù)據(jù)模型
$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>價(jià)格</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
// 基礎(chǔ)模型
class Model {
protected $mypdo;
public function __construct(){
$this->initMyPDO();
}
// 連接數(shù)據(jù)庫
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表的數(shù)據(jù)
public function getList(){
// 獲取商品數(shù)據(jù)
return $this->mypdo->fetchAll('select * from products');
}
}
?>
演化四:分離控制器
概念
控制器代碼放在index.php頁面中是不合理的
因?yàn)轫?xiàng)目中的控制器會很多,而index.php只有一個
所以需要將控制器分離開來
控制器的規(guī)則
一個模塊必須對應(yīng)一個控制器
控制器以Controller結(jié)尾(不是必須的)
控制器中的方法以Action結(jié)尾(不是必須的)
目的防止方法名是PHP關(guān)鍵字
請求分發(fā)
每次請求都要從index.php進(jìn)入,所以index.php又叫入口文件
通過在url地址上傳遞參數(shù)來尋址
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); //轉(zhuǎn)成小寫
$controller_name= $c.'Controller'; //拼接控制器類名
$action_name= $a.'Action'; //拼接方法名
//請求分發(fā)
$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>價(jià)格</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
// 基礎(chǔ)模型
class Model {
protected $mypdo;
public function __construct(){
$this->initMyPDO();
}
// 連接數(shù)據(jù)庫
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表的數(shù)據(jù)
public function getList(){
// 獲取商品數(shù)據(jù)
return $this->mypdo->fetchAll('select * from products');
}
}
?>
# ProductsController.class.php
<?php
// 商品模塊
class ProductsController {
// 獲取商品列表
public function listAction(){
// 實(shí)例化數(shù)據(jù)模型
$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); //轉(zhuǎn)成小寫
$controller_name= $c.'Controller'; //拼接控制器類名
$action_name= $a.'Action'; //拼接方法名
//請求分發(fā)
$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>價(jià)格</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(){
// 實(shí)例化數(shù)據(jù)模型
$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表的數(shù)據(jù)
public function getList(){
// 獲取商品數(shù)據(jù)
return $this->mypdo->fetchAll('select * from products');
}
// 刪除products表的數(shù)據(jù)
public function del($proid){
// 刪除商品數(shù)據(jù)
return $this->mypdo->exec("delete from products where proID={$proid}");
}
}
?>
框架目錄
創(chuàng)建目錄結(jié)構(gòu)
Application 應(yīng)用程序
Config 配置文件
Controller 控制器
Admin 后臺控制器
Home 前臺控制器
Model 模型
View 視圖
Admin 后臺視圖
Home 前臺視圖
Framework 框架
Core 核心
Lib 擴(kuò)展
Public 靜態(tài)資源
Traits 復(fù)用代碼
文件分類存放
概念
由于每次都請求入口文件,所以”.“表示入口文件所在的目錄
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 {
...
}
?>
框架類實(shí)現(xiàn)
定義路徑常量
概念
由于文件路徑使用頻率很高,而且路徑比較長
所以將固定不變的路徑定義成路徑常量
知識點(diǎn)
getcwd() 入口文件的絕對路徑
windows下默認(rèn)的目錄分隔符是,Linux下默認(rèn)的目錄分隔符是/
DIRECTORY_SEPARATOR常量根據(jù)不同的操作系統(tǒng)返回不同的目錄分隔符
# 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之前,常量不能保存數(shù)組和對象
# config.php
return array(
//數(shù)據(jù)庫配置
'database'=>array(),
//應(yīng)用程序配置
'app'=>array(
'dp' => 'Admin', //默認(rèn)平臺
'dc' => 'Products', //默認(rèn)控制器
'da' => 'list' //默認(rèn)方法
)
);
# 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); //當(dāng)前請求控制器的目錄地址
define('__VIEW__',VIEW_PATH.$p.DS); //當(dāng)前視圖的目錄地址
}
自動加載類
# 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;
});
}
請求分發(fā)
# 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();
}
}
在入口中調(diào)用run()方法
概述
run()方法調(diào)用后就啟動了框架
# index.php
<?php
require './Framework/Core/Framework.class.php';
Framework::run();
?>
SQL方法封裝
生成insert語句
知識點(diǎn)
array_keys($arr) 返回?cái)?shù)組的鍵
array_values($arr) 返回?cái)?shù)組的值
array_map(fun(), $arr) 將函數(shù)作用到數(shù)組中的每個值上,并返回帶有新值的數(shù)組
$table= 'products'; //表名
//插入的數(shù)據(jù)
$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)";
生成更新語句
知識點(diǎn)
array_search(value, $arr) 在數(shù)組中搜索某個鍵值,并返回對應(yīng)的鍵名
$table='products'; //表名
$data['proname']='鋼筆';
$data['proprice']=120;
$data['proID']='111';
//獲取主鍵
function getPrimaryKey($table) {
//連接數(shù)據(jù)庫
$link=mysqli_connect('localhost','root','root','data');
mysqli_set_charset($link,'utf8');
//查看表結(jié)構(gòu)
$rs=mysqli_query($link,"desc `{$table}`");
//循環(huán)判斷主鍵
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); //返回主鍵在數(shù)組中的下標(biāo)
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語句
知識點(diǎn)
is_array($arr) 判斷變量是否為數(shù)組
function select($table,$cond=array()) {
$sql="select * from `{$table}` where 1";
//拼接條件
if(!empty($cond)){
foreach($cond as $k=>$v){
if(is_array($v)){ //條件的值是數(shù)組類型
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);
獲取表名
知識點(diǎn)
get_class($this) 返回實(shí)例對象的類(包括命名空間)
basename($path) 返回路徑中的文件名部分
substr($str, startNum, endNum) 截取字符串
class Model {
private $table;
public function __construct($table='') {
if($table!='') //直接給基礎(chǔ)模型傳遞表名
$this->table=$table;
else { //實(shí)例化子類模型
$this->table=substr(basename(get_class($this)),0,-5);
}
echo $this->table,'<br>';
}
}
在項(xiàng)目中封裝萬能的增、刪、改、查
概念
由于封裝的方法可以操作所有的表
可以將這些方法封裝在基礎(chǔ)模型中
<?php
namespace Core;
//基礎(chǔ)模型
class Model {
protected $mypdo;
private $table; //表名
private $pk; //主鍵
public function __construct($table=''){
$this->initMyPDO();
$this->initTable($table);
$this->getPrimaryKey();
}
//連接數(shù)據(jù)庫
private function initMyPDO() {
$this->mypdo= MyPDO::getInstance($GLOBALS['config']['database']);
}
//獲取表名
private function initTable($table){
if($table!='') //直接給基礎(chǔ)模型傳遞表名
$this->table=$table;
else { //實(shí)例化子類模型
$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); //返回主鍵在數(shù)組中的下標(biāo)
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);
}
//查詢,返回二維數(shù)組
public function select($cond=array()){
$sql="select * from `{$this->table}` where 1";
if(!empty($cond)){
foreach($cond as $k=>$v){
if(is_array($v)){ //條件的值是數(shù)組類型
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);
}
//查詢,返回一維數(shù)組
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); //轉(zhuǎn)成小寫
define('PLATFROM_NAME', $p); //平臺名常量
define('CONTROLLER_NAME', $c); //控制器名常量
define('ACTION_NAME', $a); //方法名常量
define('__URL__', CONTROLLER_PATH.$p.DS); //當(dāng)前請求控制器的目錄地址
define('__VIEW__',VIEW_PATH.$p.DS); //當(dāng)前視圖的目錄地址
}
//自動加載類
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;
});
}
//請求分發(fā)
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(
//數(shù)據(jù)庫配置
'database'=>array(),
//應(yīng)用程序配置
'app'=>array(
'dp' => 'Admin', //默認(rèn)平臺
'dc' => 'Products', //默認(rèn)控制器
'da' => 'list' //默認(rèn)方法
)
);
?>
基礎(chǔ)模型
# Framework/Core/Model.class.php
<?php
namespace Core;
class Model {
protected $mypdo;
public function __construct(){
$this->initMyPDO();
}
// 連接數(shù)據(jù)庫
private function initMyPDO(){
$this->mypdo= MyPDO::getInstance($GLOBALS['config']['database']);
}
}
?>
PDO數(shù)據(jù)庫
# Framework/Core/MyPDO.class.php
<?php
namespace Core;
class MyPDO{
private $type; //數(shù)據(jù)庫類別
private $host; //主機(jī)地址
private $port; //端口號
private $dbname; //數(shù)據(jù)庫名
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;
}
//初始化參數(shù)
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語句執(zhí)行失敗<br>';
echo '錯誤的SQL語句是:'.$sql,'<br>';
}
echo '錯誤編號:'.$ex->getCode(),'<br>';
echo '錯誤行號:'.$ex->getLine(),'<br>';
echo '錯誤文件:'.$ex->getFile(),'<br>';
echo '錯誤信息:'.$ex->getMessage(),'<br>';
}
//設(shè)置異常模式
private function initException(){
$this->pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
}
//執(zhí)行增、刪、改操作
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;
}
}
//獲取所有數(shù)據(jù) ,返回二維數(shù)組
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);
}
}
//獲取一維數(shù)組
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(){
// 實(shí)例化數(shù)據(jù)模型
$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表的數(shù)據(jù)
public function getList(){
// 獲取商品數(shù)據(jù)
return $this->mypdo->fetchAll('select * from products');
}
// 刪除products表的數(shù)據(jù)
public function del($proid){
// 刪除商品數(shù)據(jù)
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>價(jià)格</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>
復(fù)用跳轉(zhuǎn)
# Traits/Jump.class.php
<?php
//跳轉(zhuǎn)的插件
namespace Traits;
trait Jump{
//封裝成功的跳轉(zhuǎn)
public function success($url,$info='',$time=1){
$this->redirect($url, $info, $time, 'success');
}
//封裝失敗跳轉(zhuǎn)
public function error($url,$info='',$time=3){
$this->redirect($url, $info, $time, 'error');
}
/*
* 作用:跳轉(zhuǎn)的方法
* @param $url string 跳轉(zhuǎn)的地址
* @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>秒以后跳轉(zhuǎn)</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;
}
}
}
總結(jié)
以上是生活随笔為你收集整理的PHP核心之MVC设计模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《精灵宝可梦Let's Go伊
- 下一篇: 倩女幽魂手游89级异人卡级攻略 异人怎么