Correcting teacher:天蓬老师
Correction status:qualified
Teacher's comments:理解了容器的概念, 写一个服务容器就简单了, 但是实际的服务容器, 比这个复杂多了,有对象, 有数组, 有闭包, 有函数, 有类, 有请求数据,甚至代码片断, 反射结果 等, 但思想是不变的
Model.php
<?php
namespace home;
require 'Db.php';
class Model extends Db
{
}
Db.php
<?php
namespace home;
//数据库操作类
class Db{
public static $link = null;//保存pdo连接
public static $sql = null;//保存语句
//使用构造函数连接数据库
public function __construct($dsn,$username,$password){
try{
self::$link = new \PDO($dsn,$username,$password);
if(empty(self::$link)){
echo '数据库连接失败';
}
}catch(\Exception $e){
echo $e->getMessage();
}
}
//新增数据
public static function add(string $table,array $data){
$val = array_values($data);
$keys = array_map(function($item){
return $item = '`'.$item.'`=?';
},array_keys($data));
$fields = implode(",",$keys);
//预处理sql语句,使用占位符
$sql = "insert {$table} set {$fields}";
$stmt = self::$link->prepare($sql);
//执行查询语句
$stmt->execute($val);
if($stmt->rowCount()===1){
return self::$link->lastInsertId();//获取新增的主键ID
}else{
return $stmt->errorInfo();
}
}
//查询数据
public static function find(string $sql){
//预处理sql语句
$stmt = self::$link->prepare($sql);
//执行查询语句
$stmt->execute();
return $stmt->fetchAll(\PDO::FETCH_ASSOC);
}
//更新数据
public static function update(string $table,string $where,array $data)
{
$val = array_values($data);
$keys = array_map(function($item){
return $item = '`'.$item.'`=?';
},array_keys($data));
$fields = implode(",",$keys);
//预处理sql语句,使用占位符
self::$sql = "update `{$table}` SET {$fields} {$where}";
$stmt = self::$link->prepare(self::$sql);
//执行查询语句
$stmt->execute($val);
if($stmt->rowCount()){
return $stmt->rowCount();//返回受影响的记录数
}else{
return $stmt->errorInfo();
}
}
//删除数据
public static function delete($table,$where)
{
$sql = "DELETE FROM `{$table}` {$where}";
self::$sql=$sql;
$stmt = self::$link->prepare($sql);
$stmt->execute();
if($stmt->rowCount()){
return $stmt->rowCount();//返回受影响的记录数
}else{
return $stmt->errorInfo();
}
}
}
<?php
namespace home;
class View
{
public function fetch($data){
include 'goods.php';
}
}
goods.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>商品信息维护</title>
<style>
body {
display: flex;
flex-flow: column nowrap;
align-items: center;
}
form {
display: flex;
flex-flow: row wrap;
}
form>section {
margin: 10px;
display: flex;
flex-flow: row nowrap;
}
table {
margin-top: 30px;
width: 1000px;
font-family: verdana, arial, sans-serif;
font-size: 11px;
color: #333333;
border-width: 1px;
border-color: #666666;
border-collapse: collapse;
}
table>thead {
background-color: #80ff80;
}
table th {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
}
table td {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #ffffff;
text-align: center;
}
tfoot>tr,
tfoot>tr>td {
width: initial;
}
</style>
</head>
<body>
<hr>
<hr>
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" class="queryterms" method="POST">
<section>
<label for="goodsname">商品名称:</label>
<input type="text" name="goodsname" id="goodsname"
value="<?php if(isset($_SESSION['goodsname'])) echo $_SESSION['goodsname']?>">
</section>
<section>
<label for="goodsmodel">商品型号:</label>
<input type="text" name="goodsmodel" id="goodsmodel"
value="<?php if(isset($_SESSION['goodsmodel'])) echo $_SESSION['goodsmodel']?>">
</section>
<section>
<button>查询</button>
</section>
</form>
<div>
<table>
<thead>
<tr>
<th>ID</th>
<th>名称</th>
<th>型号</th>
<th>价格</th>
<th>数量</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<?php foreach($data as $val):?>
<tr>
<td><?php echo $val['id'] ?></td>
<td><?php echo $val['name']?></td>
<td><?php echo $val['model']?></td>
<td><?php echo $val['price']?></td>
<td><?php echo $val['number']?></td>
<td><?php echo $val['status']?></td>
<td><a href="handle.php?act=edit&id=<?php echo $val['id'] ?>">编辑</a>
<a href="handle.php?act=delete&id=<?php echo $val['id'] ?>">删除</a></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr>
<td colspan="7"><?php if(isset($page))echo $page; ?></td>
</tr>
</tfoot>
</table>
</div>
</body>
</html>
<?php
namespace home;
require 'Model.php';
require 'View.php';
//.直接在方法内实例化外部类使用
class Controller
{
public function index($dsn,$username,$password){
$data = (new Model($dsn,$username,$password))::find('select * from goods limit 2');
return (new View)->fetch($data);
}
}
$ctrl = new Controller;
$ctrl->index($dsn,$username,$password);
至此,就完成了一个最简单的mvc框架,Model类负责处理数据、view输出展示数据,controller类负责接收处理请求和返回数据
效果图:
<?php
namespace home;
require 'Db.php';
class Model extends Db
{
public function __construct(){
if(file_exists('config.php')){
include 'config.php';
}
try{
self::$link = new \PDO($dsn,$username,$password);
if(empty(self::$link)){
echo '数据库连接失败';
}
}catch(\Exception $e){
echo $e->getMessage();
}
}
}
// 在参数中传入外部类的实例
class Controller
{
public function index(Model $model,view $view){
$data = $model::find('select * from goods limit 2,3');
return $view->fetch($data);
}
}
$ctrl = new Controller;
$ctrl->index(new Model,new View);
效果图:
通过参数传递类实例的方式,成功把模型和视图类的实例创建放到了客户端,代码涉及改造量也大大降低。但是依赖的类很多时,要一个个的创建类的实例,也比较麻烦
服务容器:
<?php
namespace home;
//服务容器类
class Container
{
public $binds = [];
//绑定服务到容器
public function bind($alias,\Closure $process){
$this->binds[$alias] = $process;
}
//使用
public function make($alias,array $param=[]){
return call_user_func_array($this->binds[$alias],$param);
}
}
容器依赖:
class Controller3
{
public function index(Container $container){
//从容器中取得model和view类的对象实例
$data = $container->make('Model')::find('select * from goods limit 6,5');
return $container->make('View')->fetch($data);
}
}
$container = new Container;
//注册服务,绑定类到容器中
$container->bind('Model',function(){return new Model();});
$container->bind('View',function(){return new View;});
$container->bind('controller',function(){return new Controller3;});
//使用服务
$container->make('controller')->index($container);
效果图:
服务容器就像一个全局变量,把所有服务类放到容器中,使用时根据注册的名字即可直接获得实例