Blogger Information
Blog 30
fans 0
comment 1
visits 22018
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
0217 MVC服务容器门面与路由思路
Admin
Original
716 people have browsed it

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了!

Correcting teacher:天蓬老师天蓬老师

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