博客列表 >PHP框架相关技术--依赖注入、路由管理等--2019年10月11日

PHP框架相关技术--依赖注入、路由管理等--2019年10月11日

Victor的博客
Victor的博客原创
2019年10月18日 19:33:451104浏览

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。





声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议