博客列表 >0217 MVC服务容器门面与路由思路

0217 MVC服务容器门面与路由思路

Admin
Admin原创
2020年02月24日 22:39:23717浏览

MVC服务容器门面与路由思路

相对完整的MVC框架流程

  • MVC框架流程大致上是这样子的
  • Model > View > Controller
  • Model > View > Container > Controller
  • Model > View > Container > Facade > Controller
    首先我们来写一个Model > View > Controller
    Model模型(用来获取数据)

    1. namespace chapter6;
    2. //模型
    3. class Model
    4. {
    5. public function getData($dbname='blog',$sqlserver='mysql')
    6. {
    7. return (new \PDO("{$sqlserver}:".'host=localhost;dbname='."{$dbname}",'root','root'))->query('SELECT `title` FROM `art`')->fetchAll(\PDO::FETCH_ASSOC);
    8. }
    9. }

    View视图

    1. namespace chapter6;
    2. //视图
    3. class View
    4. {
    5. public function fetch($mdata)
    6. {
    7. $data = '';
    8. $data .= '<ul>';
    9. foreach ($mdata as $v) {
    10. $data .= '<li>' . $v['title'] . '</li>';
    11. }
    12. $data .= '</ul>';
    13. return $data;
    14. }
    15. }
    16. echo "<style>
    17. *{
    18. margin: 0;
    19. padding: 0;
    20. }
    21. li{
    22. list-style: none;
    23. }
    24. ul{
    25. max-width: 150px;
    26. box-shadow: 0 0 5px rgba(0,0,0,0.6);
    27. }
    28. </style>";

    控制器

    1. namespace chapter6;
    2. require 'Model.php';
    3. require 'View.php';
    4. //简单的MVC思路
    5. class Controller
    6. {
    7. protected $model;
    8. protected $view;
    9. public function __construct(model $model, view $view)
    10. {
    11. $this->model = $model;
    12. $this->view = $view;
    13. }
    14. public function index()
    15. {
    16. $data = $this->model->getData();
    17. return $this->view->fetch($data);
    18. }
    19. }
    20. //实例化
    21. $model = new Model;
    22. $view = new View;
    23. //注入对象利用构造方法减少耦合
    24. $controller = new Controller($model,$view);
    25. echo $controller->index();

    运行截图:
    接下来我们来加入服务容器
    PS:啥是服务容器,服务容器是干啥的?服务容器你可以理解为一个容器池,里面有你所需要使用的对象,当你需要的时候从容器里面获取对象来进行使用

    1. namespace chapter6;
    2. //导入模型
    3. require 'Model.php';
    4. //导入视图
    5. require 'View.php';
    6. //简单的MVC思路+
    7. //使用服务容器
    8. class Container
    9. {
    10. //对象容器
    11. protected $instances = [];
    12. //写入对象
    13. public function bind($alias, \Closure $process)
    14. {
    15. $this->instances[$alias] = $process;
    16. }
    17. //输出对象(也就是使用对象)
    18. public function make($alias,$params='')
    19. {
    20. return call_user_func_array($this->instances[$alias],[]);
    21. }
    22. }
    23. //实例化服务容器
    24. $container = new Container;
    25. //绑定服务对象
    26. $container->bind('model',function (){return new Model;});
    27. $container->bind('view',function (){return new View;});
    28. class Controller2
    29. {
    30. public function index(Container $container)
    31. {
    32. $data = $container->make('model')->getData();
    33. return $container->make('view')->fetch($data);
    34. }
    35. }
    36. $controller = new Controller2();
    37. echo $controller->index($container);
    38. //使用服务容器呢就是将你需要使用的对象先放入一个对象池,然后你使用的时候从对象池中进行选取。从一定角度上是加强了控制器的灵活性,以及控制类的功能性

    运行截图:
    那么门面是啥?Facade门面技术可以理解为更好的使用服务容器,将服务容器内的对象进行静态化操作方便控制器进行调用(看代码就可以发现你使用了门面以后客户端所调用更为简单了)

    1. namespace chapter6;
    2. //导入模型
    3. require 'Model.php';
    4. //导入视图
    5. require 'View.php';
    6. //简单的MVC思路++
    7. //使用服务容器与Facade门面
    8. //**********************服务容器 */
    9. class Container1
    10. {
    11. //对象容器
    12. protected $instances = [];
    13. //写入对象
    14. public function bind($alias, \Closure $process)
    15. {
    16. $this->instances[$alias] = $process;
    17. }
    18. //输出对象(也就是使用对象)
    19. public function make($alias,$params='')
    20. {
    21. return call_user_func_array($this->instances[$alias],[]);
    22. }
    23. }
    24. //实例化服务容器
    25. $container = new Container1;
    26. //绑定服务对象
    27. $container->bind('model',function (){return new Model;});
    28. $container->bind('view',function (){return new View;});
    29. // **********************************************Facade门面/
    30. //Facade门面技术可以理解为更好的使用服务容器,将服务容器内的对象进行静态化操作方便控制器进行调用
    31. class Facade
    32. {
    33. //首先声明一下服务容器
    34. protected static $container = null;
    35. //数据
    36. protected static $data = [];
    37. //静态初始化
    38. public static function initialize(Container1 $container)
    39. {
    40. static::$container = $container;
    41. }
    42. public static function getData()
    43. {
    44. static::$data = static::$container->make('model')->getData();
    45. }
    46. public static function fetch()
    47. {
    48. return static::$container->make('view')->fetch(static::$data);
    49. }
    50. }
    51. //***************************控制器 */
    52. class Controller3
    53. {
    54. public function __construct(Container1 $container)
    55. {
    56. Facade::initialize($container);
    57. }
    58. public function index()
    59. {
    60. //获取数据;
    61. Facade::getData();
    62. //渲染数据
    63. return Facade::fetch();
    64. }
    65. }
    66. $controller = new Controller3($container);
    67. echo $controller->index();

    路由思路

    讲路有前我们需要先说一下一些PHP的常量$_SERVER

  • $_SERVER[‘REQUEST_URI’] 相当于获取主机名/项目
  • $_SERVER[‘SCRIPT_FILENAME’] 相当于服务器上储存的绝对路径
  • $_SERVER[‘SCRIPT_NAME’] 相对当前项目上的绝对路径
  • $_SERVER[‘PATH_INFO’] 并不是所有url都拥有这个值
  • $_SERVER[‘QUERY_STRING’] 查询字符串
  • urlencode()/urldecode()将查询字符串中的值进行编码与反编码空格会变成+;
  • parse_url():解析url各部分返回一个数组
  • pathinfo()返回当前脚本路径;
  • parse_str()将查询字符串解析来键值对保存到一个数组中
  • http_build_query()将一个关联数组解析成一个字符串查询自动转移
    效果图:
    当你会使用了上方的函数和常量就可以整一个简单的路由啦!
    接下来我们写一个路由解析一下http://php.io/0217/ly1.php/admin/getinfo?id=10&username=xiaoyu比如这个连接 我们可以看见入口文件时ly1.php 后面的时控制器与控制器函数admin/getinfo再后面则是字符串查询
    1. namespace chapter6;
    2. //那么接下来搞一手路由的解析小案例
    3. $url = 'http://php.io/0217/ly1.php/admin/getinfo?id=10&username=xiaoyu';
    4. //将这个url所解析所解析
    5. class AdminController
    6. {
    7. public function getInfo($id, $username)
    8. {
    9. return "id===>{$id}"."username==>{$username}";
    10. }
    11. }
    12. //首先用PATH_INFO取出我们的PATH地址也就是我们的控制器/控制器方法
    13. $pathinfo = explode('/',filter_input(INPUT_SERVER,'PATH_INFO'));
    14. //array_filter过滤为空的数值
    15. $pathinfo = array_filter($pathinfo);
    16. //接下来由于下标错误我们用重置下标顺序
    17. $pathinfo = array_values($pathinfo);
    18. //接下来开始组合控制器和控制器函数
    19. $controller = __NAMESPACE__ . '\\' . ucfirst($pathinfo[0]) . 'Controller';
    20. $action = $pathinfo[1];
    21. //使用QUERY_STRING 获取字符串查询
    22. // $info = filter_input(INPUT_SERVER,'QUERY_STRING');
    23. // var_dump($info);
    24. //然后拆分字符串查询为数组
    25. parse_str(filter_input(INPUT_SERVER,'QUERY_STRING'),$info);
    26. //实例化对象
    27. $admin = new $controller();
    28. //callback里面可以用$admin,'getinfo'也可以我这样子写;
    29. echo call_user_func_array([$admin,$action],$info);
    看一下效果的样子:
    我们还可以解析一下这种形式http://php.io/0217/ly2.php/admin/getinfo/id/10/name/xiaoyu
  1. namespace chapter6;
  2. //那么接下来搞一手路由的解析小案例
  3. $url = 'http://php.io/0217/ly2.php/admin/getinfo/id/10/name/xiaoyu';
  4. //将这个url所解析所解析
  5. class AdminController1
  6. {
  7. public function getInfo($id, $username)
  8. {
  9. return "id===>{$id}"."username==>{$username}";
  10. }
  11. }
  12. //首先用PATH_INFO取出我们的PATH地址也就是我们的控制器/控制器方法
  13. $pathinfo = explode('/',filter_input(INPUT_SERVER,'PATH_INFO'));
  14. //array_filter过滤为空的数值
  15. $pathinfo = array_filter($pathinfo);
  16. //接下来由于下标错误我们用重置下标顺序
  17. $pathinfo = array_values($pathinfo);
  18. //接下来开始组合控制器和控制器函数
  19. $controller = __NAMESPACE__ . '\\' . ucfirst($pathinfo[0]) . 'Controller1';
  20. $action = $pathinfo[1];
  21. //然后我们要取出下标2以后的参数
  22. $arraydata = array_slice($pathinfo,2);
  23. $data = [];
  24. for($i=0;$i<count($arraydata);$i+=2)
  25. {
  26. if(isset($arraydata[$i+1])){
  27. $data[$arraydata[$i]] = $arraydata[$i+1];
  28. }
  29. }
  30. //数组拆分完毕之后就可以直接开始操作
  31. //实例化对象
  32. $admin = new $controller();
  33. echo call_user_func_array([$admin,$action],$data);

效果图:
提问!如果我要这样子的路由怎么解析?http://php.io/0217/ly2.php/admin/getinfo/id/10/name/xiaoyu.html
回答:很简单我们只需在PATH_INFO获取完后rtrim一手去掉.html就OK了!

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