10月11日:
1. 写一个依赖注入的案例, 内容自定义
2. 写一个mvc应用的案例, 内容自定义
3. 写一个简单的路由, 理解路由的原理与目标
用户使用浏览器访问php构建的web应用时,都是通过url来获得指定页面的内容。而对应用的所有请求都会定向到应用入口文件(一般是单一入口),系统会从URL参数中解析当前请求的模块、控制器、操作方法以及参数,就可以执行到相应的代码。
结合MVC的设计模式,使用php路由机制,完全可以搭建一个url驱动运行的应用系统,这个系统可以是单一串联结构的MVC,也可以构成几个MVC结构并联的结构。
MVC的工作流程如下:
1. 浏览者->发出指令,后台调用控制器处理
2. 控制器->按指令选取一个合适的模型 (动作集)
3. 模型->按照控制器指令选取相应的数据 (功能集)
4. 控制器->按指令选取相应的视图
5. 视图->把第三步取到的数据按用户想要的样子显示出来 (显示集)
实例说明:
【1】编写一个Router.php来解析url。以系统默认的URL模式(PATHINFO模式)来解析内容,例如:http://serverName/index.php/Home/Index/index系统会访问默认模块(Home)下面的默认控制器(Index)的默认操作(index);
【2】编写一个自动加载文件AutoLoad.php,实现所有类的动态懒加载;
【3】编写一个入口文件index.php,在此按照url解析的模块、控制器和方法去执行。依赖注入和服务容器需要在这个文件中添加代码;
【4】编写一个控制器文件controller.php,url中的请求会通过这里派发到model去实现功能,返回来的数据再发送view去显示;这里主要是逻辑处理的操作;
【5】编写model.php,这里主要实现业务的功能,比如数据库操作、方法库等与数据资源相关的操作;
【6】编写view.php,这里主要功能是把获得的数据资源展示给用户,实际项目中更多是与html/js相关的内容。
代码实现:
实例 -- Router.php <?php class Router { public static $module; public static $controller = 'controller'; public static $action = 'index'; public static $params = []; public static function getRoute($curentFile) { $req = explode('/', $_SERVER['REQUEST_URI']); $file = explode(DIRECTORY_SEPARATOR, $curentFile); $mcap = array_slice($req, (array_search(end($file), $req) + 1)); if (count($mcap) < 3) { return; } $route = array_slice($mcap, 0, 3); list(self::$module, self::$controller, self::$action) = $route; //如果使用剩余参数传参,则为索引数组; self::$params = array_slice($mcap, 3); } } ?> 运行实例 » 点击 "运行实例" 按钮查看在线实例
实例 -- 入口文件1 -- 这里使用依赖注入实现 <?php include 'Autoloader.php'; Router::getRoute(__FILE__); $model = new Model(); $view = new View(); $controller = new Router::$controller($model, $view); if (is_null(Router::$module)) { $controller->index(); } else { $action = Router::$action; if (method_exists($controller, Router::$action)) { $controller->$action(...Router::$params); } else { die("未找到页面,请检查url..."); } } ?> 运行实例 » 点击 "运行实例" 按钮查看在线实例
实例 --- 这里使用“服务容器” 和 “静态代理” <?php include 'Autoloader.php'; Router::getRoute(__FILE__); //服务容器 class Container { protected $instance = []; //保存到关联数组; public function bind($alias, Closure $process) { $this->instance[$alias] = $process; } //从数组中取出类的实例化过程; public function make($alias, $params = []) { return call_user_func_array($this->instance[$alias], []); } } $contanier = new Container(); $contanier->bind('model', function () { return new Model(); }); $contanier->bind('view', function () { return new View(); }); class Facade { protected static $contanier = null; protected static $data = []; public static function initialize(Container $contanier) { static::$contanier = $contanier; } public static function getData(){ static::$data = static::$contanier->make('model')->getData(); } public static function blogData(){ static::$data = static::$contanier->make('model')->blogData(); public static function showIdex(){ return static::$contanier->make('view')->showIdex(static::$data); } public static function showBlog(){ return static::$contanier->make('view')->showBlog(static::$data); } } $controller = new Router::$controller(); if (is_null(Router::$module)) { $controller->index($contanier); } else { $action = Router::$action; if (method_exists($controller, Router::$action)) { $controller->$action($contanier, ...Router::$params); } else { die("未找到页面,请检查url..."); } } ?> 运行实例 » 点击 "运行实例" 按钮查看在线实例
实例 --- 控制器 代码,“静态代理代码已注释” <?php // require 'Model.php'; // require 'View.php'; //控制器 class Controller_s { //静态代理需要依赖注入的方法拿到容器 // public function __construct($container) { // Face::initialize($container); // } //默认action: 请求index; public function index(Container $contanier) { // Face::getData(); // Face::showIdex(); $data = $contanier->make('model')->getData(); $contanier->make('view')->showIdex($data); } //请求blog的action public function blog(Container $contanier) { // Face::blogData(); // Face::showBlog(); $data = $contanier->make('model')->blogData(); $contanier->make('view')->showBlog($data); } //自定义方法,传参数 public function add($contanier, $name = 'Victor', $age = '30', $salary = 20000) { echo __METHOD__ . ': 姓名: ' . $name . ', 年龄: ' . $age . ', 工资: ' . $salary; } } // class Face extends Facade { // //-- // } ?> 运行实例 » 点击 "运行实例" 按钮查看在线实例
实例 -- Model代码 <?php class Model { public function getData() { return 'Model中取到的index数据'; } public function blogData() { return 'Model中取到的blog数据'; } public function getInfo($name, $age, $salary) { return __METHOD__ . ': 姓名: ' . $name . ', 年龄: ' . $age . ', 工资: ' . $salary; // return 'Model中取到的index数据'; } } ?> 运行实例 » 点击 "运行实例" 按钮查看在线实例
实例 --- View代码 <?php class View { public function showIdex($data) { echo '在View中显示: ' . $data; } public function showBlog($data) { echo '在View中显示: ' . $data; } public function showUserInfo($data) { echo '在View中显示用户信息: ' . $data; } } ?> 运行实例 » 点击 "运行实例" 按钮查看在线实例
总结:
1、学习了php路由机制、依赖注入、服务容器和门面类(静态代理),基本了解使用情况和原理;
2、这个“静态代理” 确实 应该叫 “门面类”,绕来绕去,就是为了控制器中的代码变得简单又简单,说白了就是为框架使用者方便,体验好,但实际上后面多了撑门面的类,还得把modle和view中的方法重构一次,很多的代码,其实远不如依赖注入直观简便。作为初学者,实在不知这样做编写效率和运行效率该怎么比较。
3、感觉可以把modle和view中的方法分别做成Trait插件,设为protected,然后让门面类全部引用过来,通过__callStatic()魔术方法应该可以访问到modle和view。