题目1:一个简单的mvc模型
1.mvc1/index.php文件
<?php
// *一个简单的mvc模型
// * 模型: Model
// *1.连接数据库
$db = new PDO('mysql:dbname=phpedu1', 'root', 'root');
// *2.$stmt作为预处理对象
$stmt = $db->prepare('SELECT * FROM `staff` LIMIT ?');
// *3.绑定参数
$stmt->bindValue(1, 5, PDO::PARAM_INT);
// *4.执行
$stmt->execute();
// *5.获取全部的关联数据
$staffs = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!-- 视图 View -->
<!DOCTYPE html>
<html lang="zh-CN">
<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>员工列表</title>
</head>
<body>
<h3>员工列表</h3>
<ul>
<?php foreach ($staffs as $staff) : extract($staff) ?>
<li><?=$id?> : <?=$name?>, <?=$sex ? '女' : '男'?> (
<?=$email?> )
</li>
<?php endforeach ?>
</ul>
</body>
</html>
2.浏览器效果图:
题目2:框架中的模型类 Model
1.mvc2/core/Model.php文件:
<?php
// *框架中的模型类 Model
// *遵循psr-4条件
namespace core;
use PDO;
// *为了不让用户直接实例化,把class Model作为抽象类
abstract class Model
{
// *$db:连接对象,在这里把$db作为一个属性
protected $db = null;
// *1.其下的构造方法
// *连接数据库
//* 在实例化时,自动连接
public function __construct($dsn, $username, $password)
{
$this->db = new PDO($dsn, $username, $password);
}
// *2. 其下的select()方法
// *自定义模型: 与某一张数据表相关的类
//* 获取全部数据
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);
}
// *3.其下的getOne()方法
//* 获取某个数据( 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);
}
}
2.浏览器效果图:
题目3:框架中的视图类View
1.mvc2/core/View.php文件:
<?php
//*框架中的视图类View
namespace core;
class View
{
//* 1. 模板变量容器,专门用来存放模板变量,把它作为一个属性
protected array $data = [];
// *2. 其下的assign()方法,即模板赋值
public function assign(string $key, $value)
{
$this->data[$key] = $value;
}
// *3.其下的render()方法,即渲染视图
// *渲染与传参可以同步完成
// *$path:数据显示在页面中的路径,$data为渲染时传参
public function render(string $path, array $data=[])
{
// *如果渲染时传参有参数
if ($data) {
// *参数以每个键为单位遍历
foreach ($data as $key=>$value) {
// *调用其assign()方法,即在参数中分配键与键值
$this->assign($key, $value);
}
}
//* 将模板变量数组展开为独立的变量,以方便传入到模板中使用
extract($this->data);
// *如果当前的页面路径存在则加载,反之程序不执行
file_exists($path) ? include $path : die('模板不存在');
}
}
2.浏览器效果图:
题目4:框架中的控制器类
1.mvc2/core/Controller.php文件:
<?php
// *框架中的控制器类View
namespace core;
// *为了不让用户直接实例化,把class Controller作为抽象类
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;
}
}
2.浏览器效果图:
题目5:注册类的自动加载器方法
1.mvc2/core/autoload.php文件:
<?php
// *注册类的自动加载器方法
spl_autoload_register(function ($class) {
// *表示用'/'替换'\'后面是类名加后缀.php
require str_replace('\\', '/', $class) . '.php';
// require str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
![](https://img.php.cn/upload/image/920/826/897/1671549125615508.jpg)
});
2.浏览器效果图:
题目6:路由器中的QueryString与PATH_INFO这两种方法
1.router.php文件:
<?php
// 路由的本质: 是从url中解析出控制器,控制器方法,以及方法的参数
// 1. controller: 控制器类名
// 2. method: 控制器中的某个方法名
// 3. params: 参数列表,以数组形式
// 以上三种数据在url中的展示方式
// 1. queryString: 查询字符串
// 2. PATH_INFO: 路径信息, 位于查询字符串与当前脚本之间的路径信息
// phpedu.io/one/two/demo1.php?查询字符串,以键值对方式,和&分开
// phpedu.io/one/two/demo1.php?c=hello&m=method&p=aaa
// c=hello&m=method&p=aaa
// phpedu.io/one/two/demo1.php PATH_INFO ?c=hello&m=method&p=aaa
// phpedu.io/one/two/demo1.php/user/index/100/200?c=hello&m=method&p=aaa
// /user/index/100/200 : PATH_INFO
// use JetBrains\PhpStorm\Internal\ReturnTypeContract;()
function p($data)
{
echo is_array($data) ? sprintf('<pre>%s</pre>', print_r($data, true)) : $data.'<br>';
}
// p([1,2,3]);
// p('hello');
p($_SERVER['QUERY_STRING']);
parse_str($_SERVER['QUERY_STRING'],$request);
p($request);
$controller=array_shift($request);
$method=array_shift($request);
$params=array_shift($request);
// *再自定义一个控制器类
class HelloController
{
public function world($name)
{
return 'Hello, ' . $name;
}
}
// *生成控制器类名,并且首字母大写
echo ucfirst($controller).'Controller'.'<br>';
$controller= ucfirst($controller). 'Controller';
echo call_user_func_array([new $controller(), $method], [$params]);
echo '<hr>';
p($_SERVER['PATH_INFO']);
p(explode('/', trim($_SERVER['PATH_INFO'], '/')));
$request = explode('/', trim($_SERVER['PATH_INFO'], '/'));
// * QueryString: 查询字符串
// p($_SERVER['QUERY_STRING']);
// parse_str($_SERVER['QUERY_STRING'], $request);
// p($request);
// // *人为认为
//*c: controller, m: method, name:params
// $controller = array_shift($request);
// $method = array_shift($request);
// $params = array_shift($request);
// *控制器类:测试专用
// class HelloController
// {
// public function world($name)
// {
// return 'Hello, ' . $name;
// }
// }
// *生成控制器类名
// $controller= ucfirst($controller). 'Controller';
// echo call_user_func_array([new $controller(), $method], [$params]);
// echo '<hr>';
// echo call_user_func_array([new $controller(), $method], [$params]);
// echo '<hr>';
// *PATH_INFO: 查询字符串与脚本之间路径信息
// * http://phpLearn.io/13c/router.php/hello/world/admin?c=hello&m=world&name=peter
// * PATH_INFO: /hello/world/admin
// * 推荐使用PATH_INFO
//* 通过 url 重写功能,可以将脚本的扩展名php隐藏
//* http://phpLearn.io/13C/router.php/hello/world/admin
// *http://phpLearn.io/13C/router/hello/world/admin
2.浏览器效果图:
题目7:入口文件
1.mvc3.index.php文件:
<?php
namespace mvc3;
use model\UserModel;
use core\View;
use core\Router;
// *入口文件: 测试
//* 1. 类的自动加载器
require __DIR__ . '/core/autoload.php';
//* 路由解析
// *路由器调用parse()得到控制器,方法等,然后保存到请求变量$request中
$request = Router::parse();
// *请求变量分别把保存的数据转移给控制器,方法,参数变量中
$controller = array_shift($request);
$method = array_shift($request);
$params = array_shift($request);
//* 生成控制器名称(首字母大写)
$controller= 'controller\\'. ucfirst($controller). 'Controller';
// echo $controller;
// die;
// *2. 实例化控制器
$model = new UserModel('mysql:dbname=phpedu1', 'root', 'root');
$view = new View();
$user = new $controller($model, $view);
// *3. 调用控制器中的方法
call_user_func_array([$user, 'get'], $params);
2.浏览器效果图:
题目8:路由器类
1.mvc3/core/Router.php文件:
<?php
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];
}
}