全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

自制PHP框架之路由与控制器

我们为什么要使用路由?原因1:一个更漂亮的URI

1.URI的改进

刚刚开始学PHP时,我们一定写过blog.php?id=1之类的URI,使用GET方式获取参数。这样的URI有两个缺点,一是容易被SQL注射攻击,二是维护性可读性差,大家可以比较下面两种URI哪一种更具备可读性。

www.mysite.com/blog.php?id=1

上面URI是我们初学PHP最常用的。

www.mysite.com/blog/1

这种URI是目前最流行的URI,举个例子,比如很多读书类,电影类网站,都使用了这样的URI,这样的URI要比index.php?a=1&b=2&c=3&d=4....要简洁很多。

2.实现方法

在WEB项目的根目录下写一个.htaccess文件

RewriteEngine On

RewriteRule ^([a-zA-Z0-9/]*)$ index.php/$1

重写规则,让域名后面的字符串直接做为一个参数传入index.php,这样index.php就成为了你整个WEB应用的中心,定义了“请求和响应的映射”。

原因2:单一入口机制的易维护性

1.路由数组

一个PHP初学者,刚开始做项目,项目做着做着规模做大了,常常这个PHP页面给另一个PHP页面用GET方法传值,有时传的值还不止一个,时间一久,你的WEB项目,N个PHP页面宛如一个复杂的蜘蛛网,让你难以维护。一旦有修改,会涉及很多PHP文件,工作量很大。

MVC的单一入口机制可以解决维护难的问题,路由就是一套映射,可以让你一个URI对应一个方法。

$route=[

  ''=>'IndexController@Index',

  'blog'=>'BlogController@Show',

  'blog/{id}/{name}'=>'BlogController@Show',

];

2.获取参数

$path=$_SERVER['PATH_INFO'];

$path=ltrim($path,'/');

echo $path.PHP_EOL;

我们在浏览器里输入:www.mysite.com/blog/1后,path变量为/blog/1。使用ltrim函数删除左边的斜杠,然后使用explode把字符串拆解成数组。

$path_arr=explode('/', $path);

核心代码如下:

if(isset($_SERVER['PATH_INFO'])){

  $path=$_SERVER['PATH_INFO'];

  $path=ltrim($path,'/');

  $path_arr=explode('/', $path);

}

 

if(isset($path_arr[0])){

  $key=$path_arr[0];

  unset($path_arr[0]);

}

else{

  $key='';

}

 

if(isset($path_arr[1])){

  $parameters=array_values($path_arr);

}

 

 

if(isset($route[$key])){

  $arr=explode('@', $route[$key]);

   

  $controller=new $arr[0];

  $action=$arr[1];

   

  if(isset($parameters)){

    $controller->$action($parameters);

  }

  else{

    $controller->$action();

  }  

}

else{

  require 'error.html.php';

}

unset函数可以销毁数组中key和value,但是并不会重建索引,所以path_arr[0]是要调用的控制器类和方法名,path_arr[1]或者path_arr[1..N]就作为传入方法的参数。

重定向和错误页面是WEB系统中最常见的,如果不用路由机制,你可能要没完没了的重复写重定向或者错误页面的显示或者跳转代码,有了路由,只需要一句话就可以完成。

原因3:减少资源的消耗

MVC采用了控制器(controller)来响应请求(request),每次请求来时,应该在指定的一个PHP文件中初始化这个控制器,而不是分别在不同的PHP文件中做初始化工作,这样可以减少资源的消耗。

是不是一定要用控制器?方案1:不用控制器

我们现在路由数组里添加一项,value不是一个字符串,而是一个匿名函数(Closure)

$route=[

  ''=>'Index',

  'blog'=>'BlogController@Show',

  'blog/{id}/{name}'=>'BlogController@Show',

  'f'=>function(){echo 'hello';}

]; 

这里的route[f]是一个匿名函数,并不是一个控制器类的方法,所以,我们要把上一节路由代码做一下修改:

if(isset($route[$key])){

  if($route[$key] instanceof Closure){

    $route[$key]();

  }

  else{

    $arr=explode('@', $route[$key]);  

    $controller=new $arr[0];

    $action=$arr[1];  

    if(isset($parameters)){

      $controller->$action($parameters);

    }

    else{

      $controller->$action();

    }

  }

}

else{

  require 'error.html.php';

}

方案2:使用控制器

每一次都require一个html页面是一件很不优雅的事情,所以我们写一个render函数

function render($path,array $args){

  extract($args);

  require($path);

}

接上一篇博客,我们知道每个URI对应了一个方法,但是我们常常遇到这样的问题:

<?php 

 

class Controller{

  public function __call($method,$args){

    echo 'has not this function'.$method;

  }

}

 

class IndexController extends Controller{

  public function Index(){

    echo __CLASS__;

    for($i=1;$i<=20;++$i){

      $data[$i]='content';

    }

 

    render('template.html.php',['data'=>$data]);

  }

}

 

class BlogController extends Controller{

  public function Show(){

    echo __CLASS__;

    for($i=1;$i<=10;++$i){

      $data[$i]='blog';

    }

    render('template.html.php',['data'=>$data]);

  }

}

 

?>

用不用控制器,取决于你的业务复杂度。个人建议使用控制器,但是对于业务很简单的页面跳转或检查,可以直接写在一个匿名函数里。

控制器里写些什么?

我们也许写过这样的代码:

class IndexController extends Controller{

  public function Index($content){

    return '<html><head></head><body>'.$content.'</body></html>';

  }

}

这样把界面的代码嵌入的写法是非常难以维护的,也是很多开发人员(包括我)最厌恶的写法,因为这种写法并没有做好界面与业务逻辑的分离,所以我们需要使用视图。

<html>

  <head>

   

  </head>

   

  <body>

    <?php foreach($data as $key=>$value){ ?>  

      <div>

        <?php echo $key.':'.$value; ?>  

      </div>

    <?php } ?>

  </body>

</html>

每一次调用控制器的某个方法时,render函数都会把参数以关联数组的形式传入,做到“业务逻辑”和“表现”的浅层次分离,但是这种分离还不是最好的,因为前端开发人员仍然需要面对甚至处理PHP代码,后端开发人员也有和前端人员沟通的成本,所以后面某一节,会再谈一种更好的分离方式。


# 自制php框架  # php  # 路由框架  # PHP路由与控制器  # easyswoole一键安装脚本及宝塔安装错误问题  # thinkphp框架类库扩展操作示例  # PHP框架实现WebSocket在线聊天通讯系统  # thinkPHP框架乐观锁和悲观锁实例分析  # 浅谈laravel框架与thinkPHP框架的区别  # PHP实现用户异地登录提醒功能的方法【基于thinkPHP框架】  # 自制PHP框架之设计模式  # 自制PHP框架之模型与数据库  # 详解PHP框架EasySwoole  # 是一个  # 开发人员  # 让你  # 跳转  # 做着  # 写过  # 重定向  # 也有  # 器里  # 一是  # 两种  # 还不  # 要把  # 采用了  # 很简单  # 要用  # 可以直接  # 大了  # 要比  # 重写 


相关文章: 贸易公司网站制作流程,出口贸易网站设计怎么做?  微信h5制作网站有哪些,免费微信H5页面制作工具?  香港服务器部署网站为何提示未备案?  如何解决ASP生成WAP建站中文乱码问题?  香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧  高端智能建站公司优选:品牌定制与SEO优化一站式服务  制作网站哪家好,cc、.co、.cm哪个域名更适合做网站?  建站之星微信建站一键生成小程序+多端营销系统  如何安全更换建站之星模板并保留数据?  微课制作网站有哪些,微课网怎么进?  如何确保西部建站助手FTP传输的安全性?  沈阳制作网站公司排名,沈阳装饰协会官方网站?  南阳网站制作公司推荐,小学电子版试卷去哪里找资源好?  建站之星官网登录失败?如何快速解决?  html制作网站的步骤有哪些,iapp如何添加网页?  如何在Golang中使用replace替换模块_指定本地或远程路径  如何选择域名并搭建高效网站?  linux top下的 minerd 木马清除方法  南京网站制作费用,南京远驱官方网站?  Thinkphp 中 distinct 的用法解析  网站制作哪家好,cc、.co、.cm哪个域名更适合做网站?  黑客入侵网站服务器的常见手法有哪些?  如何通过VPS建站无需域名直接访问?  建站之星×万网:智能建站系统+自助建站平台一键生成  如何在IIS中新建站点并配置端口与IP地址?  宁波免费建站如何选择可靠模板与平台?  如何在沈阳梯子盘古建站优化SEO排名与功能模块?  视频网站app制作软件,有什么好的视频聊天网站或者软件?  如何选择网络建站服务器?高效建站必看指南  网站制作公司哪里好做,成都网站制作公司哪家做得比较好,更正规?  高防服务器:AI智能防御DDoS攻击与数据安全保障  建站主机如何选?高性价比方案全解析  Python lxml的etree和ElementTree有什么区别  深圳企业网站制作设计,在深圳如何网上全流程注册公司?  SQL查询语句优化的实用方法总结  如何快速搭建支持数据库操作的智能建站平台?  c++怎么实现高并发下的无锁队列_c++ std::atomic原子变量与CAS操作【详解】  青浦网站制作公司有哪些,苹果官网发货地是哪里?  微信小程序制作网站有哪些,微信小程序需要做网站吗?  如何获取免费开源的自助建站系统源码?  建站org新手必看:2024最新搭建流程与模板选择技巧  如何通过二级域名建站提升品牌影响力?  如何在新浪SAE免费搭建个人博客?  如何破解联通资金短缺导致的基站建设难题?  建站之星后台管理如何实现高效配置?  c# Task.Yield 的作用是什么 它和Task.Delay(1)有区别吗  高端云建站费用究竟需要多少预算?  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  建站主机是否等同于虚拟主机?  网站建设制作需要多少钱费用,自己做一个网站要多少钱,模板一般多少钱? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。