MVC工作原理
1. m: model,模型, 数据库操作
2. v: view, 视图, html 页面
3. c: controller,控制器, mv 数据交互
index.php(入口文件)
namespace mvc3;
use model\UserModel;
use core\View;
use core\Router;
// 入口文件: 测试
// 1. 类的自动加载器
require __DIR__ . '/core/autoload.php';
// 路由解析
$request = Router::parse();
$controller = array_shift($request);
$method = array_shift($request);
$params = array_shift($request);
// 生成控制器名称
$controller= 'controller\\'. ucfirst($controller). 'Controller';
// 2. 实例化控制器
$model = new UserModel('mysql:dbname=phpedu', 'root', 'root');
$view = new View();
$user = new $controller($model, $view);
// 3. 调用控制器中的方法
call_user_func_array([$user, 'get'], $params);
model: 模型, 数据库操作
// 模型类 Model
// psr-4
namespace core;
use PDO;
abstract class Model
{
protected $db = null;
// 1. 连接数据库
// 在实例化时,自动连接
public function __construct($dsn, $username, $password)
{
$this->db = new PDO($dsn, $username, $password);
}
// 2. 内置一些基本的底层操作,供用户的自定义模型用
// 自定义模型: 与某一张数据表相关的类
// 2.1 获取全部数据
public function select($num)
{
$sql = 'SELECT * FROM `staff` LIMIT ?;';
$stmt = $this->db->prepare($sql);
$stmt->bindParam(1, $num, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// 2.2 获取某个数据( id )
public function getOne($id)
{
$sql = 'SELECT * FROM `user` WHERE `id` = ? ;';
$stmt = $this->db->prepare($sql);
$stmt->bindParam(1, $id, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetch(PDO::FETCH_ASSOC);
}
}
view, 视图, html 页面
<?php
// 视图类View
namespace core;
class View
{
// 1. 模板变量容器
protected array $data = [];
// 2. 模板赋值
public function assign(string $key, $value)
{
$this->data[$key] = $value;
}
// 3. 渲染视图
// 渲染与传参可以同步完成
public function render(string $path, array $data=[])
{
if ($data) {
foreach ($data as $key=>$value) {
$this->assign($key, $value);
}
}
// 将模板变量数组展开为独立的变量,以方便传入到模板中使用
extract($this->data);
// 渲染/加载模板文件
file_exists($path) ? include $path : die('模板不存在');
}
}
Controller.php 控制器类
// 控制器类View
namespace core;
abstract class Controller
{
// 1. 模型对象
protected Model $model;
// 2. 视图对象
protected View $view;
// 3. 实例化,初始化上面的模型,视图对象
public function __construct(Model $model, View $view)
{
$this->model = $model;
$this->view = $view;
}
}
autoload 自动加载
// 注册类的自动加载器方法
spl_autoload_register(function ($class) {
require str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
});
Router 路由类
namespace core;
// 路由器类
class Router
{
public static function parse(): array
{
// 默认控制器,实际项目,应该来自配置文件,而不是在写死
$controller = 'Index';
$action = 'index';
// 参数列表
$params = [];
// 判断是否存在pathinfo
if (array_key_exists('PATH_INFO', $_SERVER) && $_SERVER['PATH_INFO'] !== '/') {
// 为什么要判断 $_SERVER['PATH_INFO'] !== '/' ?
// 因为: admin.php/ 时,$_SERVER['PATH_INFO'] = '/', 导致解析控制器失败
$pathinfo = array_filter(explode('/', $_SERVER['PATH_INFO']));
// dump($pathinfo);
// 考虑到index.php/ 情况, 这时pathinfo为空数组
if (count($pathinfo) >= 2) {
$controller = array_shift($pathinfo);
$action = array_shift($pathinfo);
$params = $pathinfo;
} else {
$controller = array_shift($pathinfo);
}
}
// 查看控制器,方法,参数
// dump($controller, $action, $params);
// 将这些数据返回出去
return [$controller, $action, $params];
}
}