一、mvc案例相关技术点:
- 1、容器:将类的实例化过程装入,提供绑定
bind()
与实现make()
方法供外部调用 - 2、门面:将注入依赖类的相关方法静态化,并进行统一管理
- 3、外部对象依赖注入
- 4、自动加载技术 -
spl_autoload_register
- 5、数组转变量技术 -
list(...)
- 6、单例模式 - 封装 pdo对象
- 7、数据表与类的绑定 - setFetchMode();
相关文件:
autoload.php
- 自动加载类
class Loader{
public static function load($className)
{
$path = $className.'.php';
if (file_exists($path)){
require $path;
}else{
echo $path . '不存在,请检查~~';
}
}
}
spl_autoload_register(['Loader','load']);
Db.php
- Db类
class Db
{
private static $pdo = null; // pdo实例
private function __construct(...$params)
{
list($dsn, $username, $password) = $params;
try {
self::$pdo = new PDO($dsn, $username, $password);
} catch (Exception $e) {
die('数据库连接失败:'.$e->getMessage());
}
}
//单例模式
public static function getInstance(...$params){
if (is_null(self::$pdo)){
new self(...$params);
}
return self::$pdo;
}
//禁止外部访问克隆方法
private function __clone()
{
// TODO: Implement __clone() method.
}
}
View.php
- 视图类
class View
{
public function fetch($data)
{
$table = '';
$table .= '<table>';
$table .= '<caption>学生信息表</caption>';
$table .= '<tr><th>ID</th><th>名字</th><th>年龄</th><th>课程</th><th>入学时间</th></tr>';
foreach ($data as $item){
$table .= '<tr>';
$table .= "<td>{$item->id}</td>";
$table .= "<td>{$item->name}</td>";
$table .= "<td>{$item->age}</td>";
$table .= "<td>{$item->course}</td>";
$table .= "<td>{$item->create_dt}</td>";
$table .= '</tr>';
}
$table .= '</table>';
return $table;
}
}
echo '<style>
table {border-collapse: collapse; border: 1px solid; width: 500px;height: 150px}
caption {font-size: 1.2rem; margin-bottom: 10px;}
tr:first-of-type { background-color:lightblue;}
td,th {border: 1px solid;padding: 6px}
td:first-of-type {text-align: center}
</style>';
Model.php
- 数据类
class Model
{
private $pdo;
public $id;
private $name;
private $age;
private $course;
private $create_dt;
//属性重载
public function __get($name)
{
return $this->$name;
}
public function __construct()
{
$this->pdo = Db::getInstance('mysql:host=demo.com;dbname=demo','root','root');
$this->create_dt = date('Y-m-d',$this->create_dt);
}
/**
* 返回所有学生数据
* @return array
*/
public function getData(){
$sql = 'select * from `student`';
$stmt = $this->pdo->prepare($sql);
$stmt->setFetchMode(PDO::FETCH_CLASS, Model::class);
$stmt->execute();
$students = $stmt->fetchAll();
return $students;
}
}
Container.php
- 容器类
class Container
{
//类实例的容器
protected $instance = [];
//绑定类实例到容器中
public function bind($alias, Closure $closure){
$this->instance[$alias] = $closure;
}
//将类实例从容器中取出来
public function make($alias, $params = []){
return call_user_func_array($this->instance[$alias],$params);
}
}
Facade.php
- 门面类
class Facade
{
//container实例
protected static $container;
//数据对象
protected static $data = [];
/**
* 实例化方法
* @param $container 将容器注入到本类中
*/
public static function initialize(Container $container)
{
static::$container = $container;
}
//将 Model类的方法静态化,并由本类进行管理调用
public static function getData($alias){
static::$data = self::$container->make($alias)->getData();
}
//将 View类的方法静态化,并由本类进行管理调用
public static function fetch($alias){
return static::$container->make($alias)->fetch(static::$data);
}
}
Controller.php
- 控制器类
// 3、创建控制器
class Controller
{
protected $container;
public function __construct($container)
{
$this->container = $container;
$this->container->bind('model',function (){return new Model();});
$this->container->bind('view',function (){return new View();});
// 调用 Facade里面的初始化方法
Facade::initialize($container);
}
public function index()
{
// 获取数据
Facade::getData('model');
// 渲染模板
return Facade::fetch('view');
}
}
index.php
- 工作类
//在工作类中引入一次即可
<?php
session_start();
require 'autoload.php';
if (!isset($_SESSION['user'])) {
echo '<script>alert("请先登录");location.assign("login.php");</script>';
}
//客户端调用
$container = new Container();
$controller = new Controller($container);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>后台管理界面</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<header>
<h3>后台管理</h3>
<nav>
<a href="#">用户</a>
<a href="dispatch.php?action=logout">退出</a>
</nav>
</header>
<main>
<aside>
<li><a>首页</a></li>
<li><a>学生信息</a></li>
<li><a>用户管理</a></li>
<li><a>系统设置</a></li>
</aside>
<article>
<?php
echo $controller->index();
?>
</article>
</main>
<footer>
<p>2019 - MVC模板案例</p>
</footer>
</body>
</html>
代码效果:
二、路由解析
$uri = $_SERVER['REQUEST_URI'];
$request = explode('/',$uri);
//将pathinfo内容解析到一个数组中保存
$arr = array_slice($request , 3,3);
list($module, $controller, $action) = $arr;
$arr = compact('module','controller','action');
print_r($arr);
//从pathinfo数组中解析出:参数键值对
$values = array_slice($request, 6);
for ($i=0; $i<count($values); $i+=2) {
// 将键值对中的第一个做为键,第二个做为值,该操作仅在第二个值存在的情况下执行
if( isset($values[$i+1])) {
$params[$values[$i]] = $values[$i+1];
}
}
print_r($params);
课程总结:
1、mvc框架底层实现通过 控制器-Controller:控制器中有两个辅助类(Container负责把依赖类的实例注入到控制器中,Facade负责管理获取数据和渲染数据的方法)
获取到模板数据-Model
渲染到页面-View
2、router
通过解析 uri可以获取到用户请求的模板、控制器和方法及参数,程序就会执行与之一一对应的代码并返回相应的页面。
THE END !