Blogger Information
Blog 35
fans 0
comment 0
visits 44150
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
PHP框架相关技术--依赖注入、路由管理等--2019年10月11日
Victor的博客
Original
1105 people have browsed it

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。





Correction status:qualified

Teacher's comments:并不是所有类都可以用门面封装,但所有类却可以通过依赖注入到其它对象中, 所以依赖注入更直观
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post