1. MVC模式实现数据库查询
- config.php
<?php
// 配置文件
return [
'type' => $type ?? 'mysql',
'host' => $host ?? 'php.edu',
'dbname' => $dbname ?? 'first',
'username' => $username ?? 'root',
'password' => $password ?? 'root',
'port' => $port ?? 3306,
'charset' => $charset ?? 'utf8',
];
- connect.php
<?php
// 数据库连接
namespace mvc_test;
use PDO;
trait tConnect
{
private $config;
public function db()
{
$this->config = require "config.php";
extract($this->config);
$dsn = sprintf('%s:host=%s;dbname=%s;charset=%s;port=%s',$type,$host,$dbname,$charset,$port);
try {
$db = new PDO($dsn,$username,$password);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_ASSOC);
} catch (Throwable $e) {
exit($e->getMessage());
} catch (PDOException $e) {
exit($e->getMessage());
}
return $db;
}
}
- Model.php
<?php
// 模型
namespace mvc_test;
// 连接数据库
require "connect.php";
// 查询类
class Model
{
use tConnect;
public function getData ()
{
// PDO对象
$pdo = $this->db();
return $pdo->query("SELECT * FROM `student` LIMIT 10")->fetchAll();
}
}
- View.php
<?php
namespace mvc_test;
// 视图,展示数据
class View
{
public function fetch ($data)
{
$table = '<table>';
$table .= '<caption><h2>用户信息表</h2><caption>';
$table .= '<tr>';
$table .= '<th>id</th><th>用户名</th><th>性别</th><th>年龄</th><th>电话</th>';
$table .= '</tr>';
foreach ($data as $user)
{
$table .= '<tr>';
$table .= '<td>'.$user['id'].'</td>';
$table .= '<td>'.$user['username'].'</td>';
$table .= '<td>'.$user['sex'].'</td>';
$table .= '<td>'.$user['age'].'</td>';
$table .= '<td>'.$user['tel'].'</td>';
$table .= '</tr>';
}
$table .= '</table>';
return $table;
}
}
echo "
<style>
table{border-collapse: collapse;width: 500px;text-align: center;margin: auto;}
td,th{border:1px solid black;padding: 10px;}
tr:first-of-type{background-color: coral;}
</style>
";
- trait.php
<?php
namespace mvc_test;
// iFacade初始化接口
interface iFacade
{
public static function initialize ($container) ;
}
// 使用trait实现接口
trait tFacade
{
protected static $container = null;
public static function initialize ($container)
{
static::$container = $container;
}
}
// 静态接管类成员的访问
trait tMember
{
public static function getData ()
{
return static::$container->make('model')->getData();
}
public static function fetch ($data)
{
return static::$container->make('view')->fetch($data);
}
// 获取数据并渲染
public static function res ()
{
return static::fetch(static::getData());
}
}
// 服务容器接管外部对象
trait tContainer
{
protected $instances = [];
public function bind ($keyName,\Closure $process)
{
$this->instances[$keyName] = $process;
}
public function make ($keyName,$params=[])
{
return call_user_func_array($this->instances[$keyName],[]);
}
}
- controller.php
<?php
namespace mvc_test;
require 'Model.php';
require 'View.php';
require 'trait.php';
// 服务容器
class Container
{
use tContainer;
}
// 将外部对象添加进服务容器
$container = new Container();
$container->bind('model',function(){
return new Model();
});
$container->bind('view',function(){
return new View();
});
// Facade接管服务容器,真正实现接口
abstract class Facade implements iFacade
{
use tFacade;
}
// 接管类成员的访问
class Member extends Facade
{
use tMember;
}
// 控制器类
class Controller
{
// Facade初始化
public function __construct ($container)
{
Facade::initialize($container);
}
// 获取并渲染数据
public function index ()
{
return Member::res();
}
}
// 客户端调用
$controller = new Controller($container);
echo $controller->index();
2. 总结
如果在一个类中实例化另一个类,会造成依赖性过强,也就是耦合度过高,为解决这一问题,使用依赖注入的方式来解耦,但是当依赖注入的外部对象很多时,便可以使用服务容器将外部对象封装起来,进行统一管理,在此基础之上,使用Facade门面技术,接管服务容器中外部对象成员的访问,进而,以后在控制器中调用时就可以统一使用Facade类来调用,不需要担心该使用其他类来调用,因为那些类实例放入服务容器以后,类成员的访问已经被Facade接管了