PHP MVC框架初探
前言
下面准备审一下Yii、laravel、tp,但这些框架都是基于MVC模式的,所以先简单了解下MVC模式。
MVC是什么
MVC(Model-View-Controller)是软件工程的一种软件架构模式。
在MVC模式设计下,软件系统被分来三个模块:模型(Model)、视图(VIew)、控制器(Controller)。
Model(模型):是应用程序中用于处理应用程序数据逻辑的部分,通常负责与数据库直接进行 curd 的交互。
View(视图):是应用程序处理数据显示的部分,通过将处理好的数据进行渲染。
Controller(控制器):是应用程序中处理用户交互的部分,通常用于处理数据逻辑的分发,并相应的反送给视图和控制器。
简而言之View就是我们所看到的界面,Model就是View所显示界面的后端数据,而Controller就相当于是View和Model之间的桥梁
为什么使用MVC框架
在PHP中使用MVC框架,可以实现了分层、分类开发,实现了web的分离,使前端代码与后端分离,某一层的调整,不会对另一层的代码和逻辑造成影响,使用MVC开发框架更加方便程序的扩展,使开发的代码整体更加清晰
MVC框架
目录结构
- app目录:应用目录(多模块)
- 单模块:即一个主界面,其中包含
Model
、View
、Controller
- 多模块:有多个主界面,并都包含
Model
、View
、Controller
- 单模块:即一个主界面,其中包含
- config目录: 配置文件目录
- Sentiment目录:核心文件目录
- public目录: WEB目录(对外访问目录)
url访问控制器
先在app目录下写个控制器,这时通过public下的index.php直接访问控制器是访问不到的
现在就是需要对入口文件index.php进行配置,先获取下边三个路径,方便对mvc路径进行构造
<?php
define('APP_PATH',dirname(__DIR__));$script_name=$_SERVER['SCRIPT_NAME']; // /public/index.php
$request_url=$_SERVER['REQUEST_URI']; // /public/index.php/index/home/index?id=123&titile=456
$query_string=$_SERVER['QUERY_STRING']; // id=123&titile=456
?>
之后就是需要取出mvc中需要的部分,并通过$action调用对应的index方法
<?php
define('APP_PATH',dirname(__DIR__));$script_name = $_SERVER['SCRIPT_NAME']; // /public/index.php
$request_url = $_SERVER['REQUEST_URI']; // /public/index.php/index/home/index?id=123&titile=456
$query_string = $_SERVER['QUERY_STRING']; // id=123&titile=456// 需要 index/home/index
$url = str_replace($script_name,'',$request_url); // /index/home/index?id=123&titile=456
$url = str_replace($query_string,'',$url); // /index/home/index?
$url = ltrim($url,'/'); // index/home/index?
$url = rtrim($url,'?'); // index/home/index
$url = explode('/',$url);$model = $url[0];
$controller = $url[1];
$action = $url[2];$path = APP_PATH.'/app/'.$model.'/controller/'.$controller.'.php';
require_once $path;
$new = new $controller;
$new ->$action();
?>
结果:
之后可以优化一下mvc的赋值模式(if/else 避免因用户传参问题导致无法访问对应的index方法),但这种方式若想调用不同的方法 每次都需要修改else中的值,因此可以通过config配置文件 进行修改
<?php
define('APP_PATH',dirname(__DIR__));$script_name = $_SERVER['SCRIPT_NAME']; // /public/index.php
$request_url = $_SERVER['REQUEST_URI']; // /public/index.php/index/home/index?id=123&titile=456
$query_string = $_SERVER['QUERY_STRING']; // id=123&titile=456// 需要 index/home/index
$url = str_replace($script_name,'',$request_url); // /index/home/index?id=123&titile=456
$url = str_replace($query_string,'',$url); // /index/home/index?
$url = ltrim($url,'/'); // index/home/index?
$url = rtrim($url,'?'); // index/home/index
$url = explode('/',$url);if(count($url) >= 3){$model = $url[0];$controller = $url[1];$action = $url[2];
} else {$model = 'index';$controller = 'home';$action = 'index';
}$path = APP_PATH.'/app/'.$model.'/controller/'.$controller.'.php';
require_once $path;
$new = new $controller;
$new ->$action();
?>
/config/app.php
<?phpreturn['default_model'=>'index','default_controller'=>'Home','default_action'=>'index'
];
之后将else部分替换成
else {$config=require_once APP_PATH.'/config/app.php';$model = $config['default_model'];$controller = $config['default_controller'];$action = $config['default_action'];
}
此时访问/public/index.php/
,即可默认调用/app/index/Home/的index方法
但其实不需要很多入口文件,所以这里就把原本的index.php
入口文件构建到核心文件Sentiment中,除此之外如果count >=3时,若访问不存在的控制器例如/index/index/index,他还是会报错,所以通过下边的三个if语句,再次进行优化
/Sentient/Sentiment.php
<?php
class Sentiment
{public static function init(){$script_name = $_SERVER['SCRIPT_NAME']; // /public/index.php$request_url = $_SERVER['REQUEST_URI']; // /public/index.php/index/home/index?id=123&titile=456$query_string = $_SERVER['QUERY_STRING']; // id=123&titile=456// 需要 index/home/index$url = str_replace($script_name,'',$request_url); // /index/home/index?id=123&titile=456$url = str_replace($query_string,'',$url); // /index/home/index?$url = ltrim($url,'/'); // index/home/index?$url = rtrim($url,'?'); // index/home/index$url = explode('/',$url);if(count($url) >= 3){$model = $url[0];$controller = $url[1];$action = $url[2];} else {$config=require_once APP_PATH.'/config/app.php';$model = $config['default_model'];$controller = $config['default_controller'];$action = $config['default_action'];}//判断应用模块if(!is_dir(APP_PATH.'/app/'.$model)){exit("应用模块<".$model.">不存在!");}$path = APP_PATH.'/app/'.$model.'/controller/'.$controller.'.php';//判断控制器if(!file_exists($path)){exit("控制器<".$controller.">不存在!");}require_once $path;$new = new $controller;//判断方法if(!method_exists($new,$action)){exit("方法< ".$action ." >不存在");}return ['new'=> $new,'action'=>$action];}
}
/Sentiment/App.php
<?php
define('APP_PATH',dirname(__DIR__));
require_once APP_PATH.'/Sentiment/Sentiment.php';$init = Sentiment::init();
$new =$init['new'];
$action=$init['action'];
$new->$action();
/public/index.php
<?php
define('APP_PATH',dirname(__DIR__));
require_once APP_PATH.'/Sentiment/App.php';
?>
此时就可以通过index.php,访问到核心文件的入口了,访问不存在的应用模块、控制器、方法时会返回提示信息,如下图访问方法ccc时,则会输出提示信息
访问视图层、页面跳转、函数助手
访问视图
在/app/index/view/
下建一个home文件,再在其中建一个index.php
<?php
echo "this is view";
?>
此时只需要修改Home.php的index方法,便可直接访问到视图层
<?php
class Home
{public function index(){require_once APP_PATH.'/app/index/view/home/index.php';}
}
这里可以做一下优化,把require_once的内容写到核心文件Sentiment中
/Sentiment/Sentiment.php
<?php
class Sentiment
{public static function init(){$script_name = $_SERVER['SCRIPT_NAME']; // /public/index.php$request_url = $_SERVER['REQUEST_URI']; // /public/index.php/index/home/index?id=123&titile=456$query_string = $_SERVER['QUERY_STRING']; // id=123&titile=456// 需要 index/home/index$url = str_replace($script_name,'',$request_url); // /index/home/index?id=123&titile=456$url = str_replace($query_string,'',$url); // /index/home/index?$url = ltrim($url,'/'); // index/home/index?$url = rtrim($url,'?'); // index/home/index$url = explode('/',$url);if(count($url) >= 3){$model = $url[0];$controller = $url[1];$action = $url[2];} else {$config=require_once APP_PATH.'/config/app.php';$model = $config['default_model'];$controller = $config['default_controller'];$action = $config['default_action'];}define('MODULE',$model); //view的module路径//判断应用模块if(!is_dir(APP_PATH.'/app/'.$model)){exit("应用模块<".$model.">不存在!");}$path = APP_PATH.'/app/'.$model.'/controller/'.$controller.'.php';//判断控制器if(!file_exists($path)){exit("控制器<".$controller.">不存在!");}require_once $path;$new = new $controller;//判断方法if(!method_exists($new,$action)){exit("方法< ".$action ." >不存在");}return ['new'=> $new,'action'=>$action];}public static function view($path,$data){$path= APP_PATH.'/app/'.MODULE.'/view/'.$path.'.php';require_once $path;}
}
较之前多出的部分
define('MODULE',$model); //view的module路径public static function view($path,$data){$path= APP_PATH.'/app/'.MODULE.'/view/'.$path.'.php';require_once $path;}
/app/index/controller/Home.php
直接调用Sentiment的view方法,并传参path,和data
<?phpclass Home
{public function index(){Sentiment::view('home/index','456');}
}
/app/index/view/home/index.php
两种调用$data值得方法选一个即可
<?= $data ?>
<? echo $data;?>
此时在访问就是我们传入的456值
页面跳转
先创建个跳转文件/Sentiment/Load.php
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>Document</title>
</head>
<body><h1><?=$msg?></h1><h3>页面自动跳转,等待 <b id="msg">3</b>秒,<a href="javascript:li()">跳转</a></h3><script>var msg = document.getElementById("msg");var i = 3;setInterval(function(){i--;msg.innerHTML = i;if(i<=0){window.location.href= "../<?= $path?>";}},1000);function li(){window.location.href = "../<?= $path ?>";}</script>
</body></html>
/Sentiment/Sentiment.php,创建load方法
public static function load($path,$msg){$url=APP_PATH.'/Sentiment/Load.php';require_once $url;
}
/app/index/controller/Home.php,通过abc方法跳转到index方法调用view
<?phpclass Home
{public function index(){Sentiment::view('home/index','456');}public function abc(){Sentiment::load('home/index',"Sentiment");}
}
结果
三秒后自动跳转index
函数助手
Sentiment/Common.php,将之前写的view、load函数写到其中
<?php
function dump($data){echo "<pre>";print_r($data);echo "</pre>";
}function view($path,$data){Sentiment::view($path,$data);
}function load($path,$msg){Sentiment::load($path,$msg);
}
在/Sentiment/App.php,进行文件包含
require_once APP_PATH.'/Sentiment/Common.php';
这时/app/index/controller/Home.php
,就不需要通过Sentiment::view()这种方式调用了,而是直接view();即可
除此外dump方法便于输出数组,当index方法中,是数组时调用dump
<?phpclass Home
{public function index(){$data=['Sentiment'=>1,'Tana'=>2];dump($data);}public function abc(){load('home/index',"Sentiment");}
}
结果
其实整个运行的流程就是:/public/index.php
—>/Sentiment/App.php
(在Sentiment.php获取控制器和方法值)—>/app/index/controller/Home.php(由于App.php包含了Common.php,所以就不用通过::调用方法)
PHP MVC框架初探相关推荐
- mvc的宿舍管理系统源码 基于jsp_[源码和文档分享]基于JSP的MVC框架实现的图书推荐系统展示平台网站...
推荐系统是目前互联网中最常见的一种智能产品形式.由于网络中信息量的快速增长以及图书出版行业出版量的攀升,人们需要一种办法,来解决信息过载的问题.此外,用户访问网络是为了获取信息,但并不是所有的访问都有 ...
- php mvc实例下载,php实现简单的MVC框架实例
本文实例讲述了php实现简单的MVC框架.分享给大家供大家参考.具体如下: 在开始之前需要知道的知识 1.php基础知识 2.单一入口, 不知道的可以看看这里 具备以上两点, 那我们就可以开始啦. 哈 ...
- Scott的ASP.net MVC框架系列文章之四:处理表单数据(2)
前几周我发表了一系列文章介绍我们正在研究的ASP.NET MVC框架.ASP.NET MVC框架为你提供了一种新的开发Web应用程序的途径,这种途径可以让应用程序变得更加层次清晰,而且更加有利于对代码 ...
- Spring MVC框架有哪些优点
Spring MVC是Spring提供的一个实现了Web MVC设计模式的轻量级Web框架.它与Struts2框架一样,都属于MVC框架,但其使用和性能等方面比Struts2更加优异. Spring ...
- koa-grace:一个基于koa的node多应用MVC框架
春节期间没回家留在北京写了一个基于koa的node MVC框架:koa-grace ,大家有兴趣可以star & fork下,谢谢支持啦!! 项目地址: https://github.com/ ...
- Java Web学习总结(30)——Service层在MVC框架中的意义和职责
mvc框架由model,view,controller组成,执行流程一般是:在controller访问model获取数据,通过view渲染页面. mvc模式是web开发中的基础模式,采用的是分层设计, ...
- Spring MVC 框架搭建及详解
现在主流的Web MVC框架除了Struts这个主力 外,其次就是Spring MVC了,因此这也是作为一名程序员需要掌握的主流框架,框架选择多了,应对多变的需求和业务时,可实行的方案自然就多了.不过 ...
- Java MVC框架性能比较 jsp、struts1、struts2、springmvc3 (转帖)
为什么80%的码农都做不了架构师?>>> Java MVC框架性能比较 jsp.struts1.struts2.springmvc3 现在各种MVC框架很多,各框架的优缺点网络 ...
- Asp.Net MVC 自定义的MVC框架(非EF操作数据库)
一些废话:在北京辞职回家不知不觉中已经半年多了,这半年中有过很多的彷徨,困惑,还有些小小难受.半年时间算是我人生以来遇到过的最困苦的时候.理想的工作跟我擦肩而过,驾照也没有考过,年后这一改革...,毕 ...
最新文章
- 2019.2.7 区块链论文翻译
- 4028: [HEOI2015]公约数数列
- TS基础2(泛型、枚举、元组)-学习笔记
- git 2.30.1最新版本的使用
- java递增_java-8 – 如何按组递增
- 力扣40. 组合总和 II(JavaScript)
- python代码转换为pytorch_python基础教程Pytorch之Tensor和Numpy之间的转换的实现方法...
- [转]Java集合类: Set、List、Map、Queue使用场景梳理
- JavaScript的Date类的函数特殊处理导致的问题
- Sharepoint 2010 对话框框架
- Atitit 算法原理与导论 目录 1. Attilax总结的有用算法 按用途分类	1 1.1. 排序算法 字符串匹配(String Matching)	1 1.2. 加密算法 编码算法 序列
- 系统分析师论文评分标准
- AD域管理员账号下发
- 服务器cache文件夹里的东西可以删除吗,MSOCache文件夹可以删除吗?如何清理C盘空间?...
- 无线信道仿真 matlab,基于Matlab的无线信道仿真.doc
- 请教苹果虚拟机自动配置序列号ID脚本
- vue日历排班组件_vue之手把手教你写日历组件
- 沟通失败是怎样造成的
- 1-4 python爬取笔趣阁小说(附带完整代码)
- 红米 k30 pro 刷入欧版和小米钱包/商店
热门文章
- lnmp一键部署脚本
- 从零学习Fluter(八):Flutter的四种运行模式--Debug、Release、Profile和test以及命名规范...
- ESP32自动更新气象站
- 搭建私有云:owncloud(用Docker构建owncloud私有云盘)
- mybatis的JavaType和ofType区别
- [uni-app]聊天App实例
- 白盒测试(单元测试JUnit使用断言assertThat中startsWith、endsWith方法)
- Windows中查看8080端口的占用情况并关闭相关进程
- linux grep 和 find 命令
- Liunx学习笔记 - 07 - 02 正则表达式与文件格式化处理