学习笔记之mvc架构模式分析与设计
程序员文章站
2022-04-01 23:03:24
...
为了未来学习成熟稳定的框架,我先找到了一个MVC微框架进行入门学习,掌握一定的理论体系,有利于加深对大框架的理解,加快吸收的速度,避免思维僵化。
一、MVC工作流程初步认识
- 浏览者 --> 调用控制器,对他发出指令
- 控制器 --> 按指令选取一个合适的模型
- 模型 --> 按控制器指令取相应数据
- 控制器 --> 按指令选取相应视图
- 视图 --> 把第三步取到的数据按用户想要的样子显示出来
(一)示例:
test.php
require_once 'testController.class.php';
require_once 'testModel.class.php';
require_once 'testView.class.php';
//第一步:浏览者 --> 调用控制器,对他发出指令
$testController = new testController();
$testController -> show();
testController.class.php
class testController{
function show(){
// 第二步:控制器 --> 按指令选取一个合适的模型
$testModel = new testModel();
$data = $testModel->get();
// 第四步:控制器 --> 按指令选取相应视图
$testView = new testView();
$testView->display($data);
}
}
testModel.class.php
class testModel{
// 第三步:模型 --> 按控制器指令取相应数据
function get(){
return "MVC工作流程初步认识";
}
}
testView.class.php
class testView{
// 第五步:视图 --> 把第三步取到的数据按用户想要的样子显示出来
function display($data){
echo $data;
}
}
运行结果:
二、简易调用实例化及入口文件
function.php
function C($name, $method){
require_once '/libs/Controller/'.$name.'Controller.class.php';
$controller = $name.'Controller';
$obj = new $controller();
$obj -> $method();
}
//模型的方法不带有自己的参数,所以不引入method会灵活一些。控制器引入method是因为它是不允许有自己的参数的。
function M($name){
require_once('/libs/Model/'.$name.'Model.class.php');
$model = $name.'Model';
$obj = new $model();
return $obj;
}
function V($name){
require_once('/libs/View/'.$name.'View.class.php');
$view = $name.'View';
$obj = new $view();
return $obj;
}
//对非法字符进行转义
function daddslashes($str){
return (!get_magic_quotes_gpc())?addslashes($str):$str;
}
testController.class.php
class testController{
function show(){
// 第二步:控制器 --> 按指令选取一个合适的模型
$testModel = M('test');
$data = $testModel -> get();
// 第四步:控制器 --> 按指令选取相应视图
$testView = V('test');
$testView -> display($data);
}
}
入口程序:在网上经常被称为单一入口机制,单一入口指在一个web应用程序中,所有的请求都是指向一个脚本文件。
index.php
//1. 统一入口文件为首的url形式:index.php?controler=控制器名&method=方法名
require_once 'function.php';
//2. 在入口文件里使用安全的方式就收传递来的控制器名和方法名
//设置允许访问的控制器名与方法名
$controllerAllow = array('test','index');
$methodAllow = array('test','index','show');
//使用daddslashes对_GET传递进来的参数进行非法参数过滤,用in_array判断传入的控制器与方法名是否允许进入。
$controller=in_array($_GET['controller'],$controllerAllow)?daddslashes($_GET['controller']):'index';
$method=in_array($_GET['method'],$methodAllow)?daddslashes($_GET['method']):'index';
C($controller, $method);
三、第三方类调用
function.php
//第三方类调用函数
function ORG($path, $name, $params=array()){
// path 是路径,name是第三方类名,params 是该类初始化的时候需要指定、赋值的属性集合,格式为 array(属性名=>属性值, 属性名2=>属性值2……)
require_once('libs/ORG/'.$path.$name.'.class.php');
$obj = new $name();
if(!empty($params)){
foreach($params as $key=>$value){
$obj->$key = $value;
}
}
return $obj;
}
index.php
//smarty实例化
$view = ORG('Smarty/', 'Smarty', $viewconfig);
config.php
//对smarty属性进行初始化
$viewconfig = array('left_delimiter' => '{', 'right_delimiter' => '}', 'template_dir' => 'tpl', 'compile_dir' => 'template_c', 'cache_dir' => 'cache');
testController.class.php
class testController{
function show(){
global $view;
// 第二步:控制器 --> 按指令选取一个合适的模型
// $testModel = new testModel();
$testModel = M('test');
$data = $testModel -> get();
// 第四步:控制器 --> 按指令选取相应视图
// $testView = new testView();
// $testView = V('test');
// $testView -> display($data);
$view->assign('username', "用户名");
$view->display('test.tpl');
}
}
目录
四、微框架的建立
研发的原则:
- 业务逻辑全进model层
- 大事化小,分而治之
- 相似功能合二为一
(一)简单工厂模式
用工厂方法代替new操作的一种模式。可以统一管理对象的实例化,便于扩展维护。
DB工厂类 DB.class.php
class DB {//类名在php里面是一个全局变量,DB::$db或DB::方法()直接调用
public static $db;//用于保存实例化对象
public static function init($dbtype, $config) {
self::$db = new $dbtype;
self::$db->connect($config);
}
public static function query($sql){
return self::$db->query($sql);
}
public static function findAll($sql){
$query = self::$db->query($sql);
return self::$db->findAll($query);
}
public static function findOne($sql){
$query = self::$db->query($sql);
return self::$db->findOne($query);
}
public static function findResult($sql, $row = 0, $filed = 0){
$query = self::$db->query($sql);
return self::$db->findResult($query, $row, $filed);
}
public static function insert($table,$arr){
return self::$db->insert($table,$arr);
}
public static function update($table, $arr, $where){
return self::$db->update($table, $arr, $where);
}
public static function del($table,$where){
return self::$db->del($table,$where);
}
}
视图引擎工厂类:VIEW.class.php
class VIEW {
public static $view;
public static function init($viewtype,$config){
self::$view = new $viewtype;
// 对试图引擎类进行初始化
/*$smarty = new Smarty();//实例化smarty
$smarty->left_delimiter=$config["left_delimiter"];//左定界符
$smarty->right_delimiter=$config["right_delimiter"];//右定界符
$smarty->template_dir=$config["template_dir"];//html模板的地址
$smarty->compile_dir=$config["compile_dir"];//模板编译生成的文件
$smarty->cache_dir=$config["cache_dir"];//缓存*/
foreach($config as $key=>$value){
self::$view -> $key = $value;
}
}
public static function assign($data){
foreach($data as $key=>$value){
self::$view->assign($key, $value);
}
}
public static function display($template){
self::$view->display($template);
}
}
(二)操作Mysql类
<?php
class mysql{
/**
* 报错函数
*
* @param string $error
*/
function err($error){
die("对不起,您的操作有误,错误原因为:".$error);//die有两种作用 输出 和 终止 相当于 echo 和 exit 的组合
}
/**
* 连接数据库
*
* @param string $dbhost 主机名
* @param string $dbuser 用户名
* @param string $dbpsw 密码
* @param string $dbname 数据库名
* @param string $dbcharset 字符集/编码
* @return bool 连接成功或不成功
**/
function connect($config){
extract($config);
if(!($con = mysql_connect($dbhost,$dbuser,$dbpsw))){//mysql_connect连接数据库函数
$this->err(mysql_error());
}
if(!mysql_select_db($dbname,$con)){//mysql_select_db选择库的函数
$this->err(mysql_error());
}
mysql_query("set names ".$dbcharset);//使用mysql_query 设置编码 格式:mysql_query("set names utf8")
}
/**
* 执行sql语句
*
* @param string $sql
* @return bool 返回执行成功、资源或执行失败
*/
function query($sql){
if(!($query = mysql_query($sql))){//使用mysql_query函数执行sql语句
$this->err($sql."<br />".mysql_error());//mysql_error 报错
}else{
return $query;
}
}
/**
*列表
*
*@param source $query sql语句通过mysql_query 执行出来的资源
*@return array 返回列表数组
**/
function findAll($query){
while($rs=mysql_fetch_array($query, MYSQL_ASSOC)){//mysql_fetch_array函数把资源转换为数组,一次转换出一行出来
$list[]=$rs;
}
return isset($list)?$list:"";
}
/**
*单条
*
*@param source $query sql语句通过mysql_query执行出的来的资源
*return array 返回单条信息数组
**/
function findOne($query){
$rs = mysql_fetch_array($query, MYSQL_ASSOC);
return $rs;
}
/**
*指定行的指定字段的值
*
*@param source $query sql语句通过mysql_query执行出的来的资源
*return array 返回指定行的指定字段的值
**/
function findResult($query, $row = 0, $filed = 0){
$rs = mysql_result($query, $row, $filed);
return $rs;
}
/**
* 添加函数
*
* @param string $table 表名
* @param array $arr 添加数组(包含字段和值的一维数组)
*
*/
function insert($table,$arr){
//$sql = "insert into 表名(多个字段) values(多个值)";
foreach($arr as $key=>$value){//foreach循环数组
$value = mysql_real_escape_string($value);
$keyArr[] = "`".$key."`";//把$arr数组当中的键名保存到$keyArr数组当中
$valueArr[] = "'".$value."'";//把$arr数组当中的键值保存到$valueArr当中,因为值多为字符串,而sql语句里面insert当中如果值是字符串的话要加单引号,所以这个地方要加上单引号
}
$keys = implode(",",$keyArr);//implode函数是把数组组合成字符串 implode(分隔符,数组)
$values = implode(",",$valueArr);
$sql = "insert into ".$table."(".$keys.") values(".$values.")";//sql的插入语句 格式:insert into 表(多个字段)values(多个值)
$this->query($sql);//调用类自身的query(执行)方法执行这条sql语句 注:$this指代自身
return mysql_insert_id();
}
/**
*修改函数
*
*@param string $table 表名
*@param array $arr 修改数组(包含字段和值的一维数组)
*@param string $where 条件
**/
function update($table,$arr,$where){
//update 表名 set 字段=字段值 where ……
foreach($arr as $key=>$value){
$value = mysql_real_escape_string($value);
$keyAndvalueArr[] = "`".$key."`='".$value."'";
}
$keyAndvalues = implode(",",$keyAndvalueArr);
$sql = "update ".$table." set ".$keyAndvalues." where ".$where;//修改操作 格式 update 表名 set 字段=值 where 条件
$this->query($sql);
}
/**
*删除函数
*
*@param string $table 表名
*@param string $where 条件
**/
function del($table,$where){
$sql = "delete from ".$table." where ".$where;//删除sql语句 格式:delete from 表名 where 条件
$this->query($sql);
}
}
(三)微型框架编写
1.框架组织结构
(1) 函数库
(2) 类库
a. 视图引擎库
b. DB引擎库
c. 核心库
(3) require文件清单
(4) 启动引擎程序(完成一系列初始化并调用控制器)
2.文件清单:include.list.php
//罗列清单程序
$paths = array(
'function/function.php',
'libs/core/DB.class.php',
'libs/core/VIEW.class.php',
'libs/db/mysql.class.php',
'libs/view/Smarty/Smarty.class.php'
);
3.引擎程序:PC.php
//启动引擎程序
//引入清单文件
$currentdir = dirname(__FILE__);//获取当前文件所在地址
include_once($currentdir.'/include.list.php');
foreach($paths as $path){
include_once($currentdir.'/'.$path);
}
class PC{
public static $controller;
public static $method;
private static $config;
private static function init_db(){
DB::init('mysql', self::$config['dbconfig']);
}
private static function init_view(){
VIEW::init('Smarty', self::$config['viewconfig']);
}
private static function init_controller(){
self::$controller = isset($_GET['controller'])?daddslashes($_GET['controller']):'index';
}
private static function init_method(){
self::$method = isset($_GET['method'])?daddslashes($_GET['method']):'index';
}
public static function run($config){
// 1. 完成一系列初始化
self::$config = $config;
self::init_db();
self::init_view();
self::init_controller();
self::init_method();
// 2. 调用控制器
C(self::$controller, self::$method);
}
}
(四)入口文件与配置文件改进
1. 入口文件:
(1) 调用配置文件
(2) 调用微型框架
(3) 启动框架引擎
2. 配置文件:
(1) 数据库配置信息
(2) 视图引擎配置信息
admin.php
/*
入口文件
*/
header("Content-type: text/html; charset=utf-8");
//(1)调用配置文件
require_once('config.php');
//(2)调用微型框架
require_once('framework/pc.php');
//(3)启动框架引擎
PC::run($config);
config.php
/*
配置文件
*/
$config = array(
//视图引擎配置信息:对smarty属性进行初始化
'viewconfig' => array(
'left_delimiter' => '{', 'right_delimiter' => '}', 'template_dir' => 'tpl', 'compile_dir' => 'data/template_c'),
//数据库配置信息:对mysql属性进行初始化
'dbconfig' => array(
'dbhost' => 'localhost', 'dbuser'=>'root', 'dbpsw' => '0330' , 'dbname' => 'newsreport', 'dbcharset' => 'utf8')
);
五、MVC微型框架的实际运用
教程模板略。
自己用所学的知识做了个前台小网站:企业管理虚拟实景实验设计大赛网站