thinkphp-路由、路由的变量规则和闭包、地址和参数、域名和跨域请求

2824次阅读 50人点赞 作者: WuBin 发布时间: 2024-05-15 09:55:55
扫码到手机查看

路由的定义

简介

路由的作用就是让URL 地址更加的规范和优雅,或者说更加简洁;

设置路由对URL 的检测、验证等一系列操作提供了极大的便利性;

路由是默认开启的,如果想要关闭路由,在config/app.php 配置;

// 是否启用路由
'with_route' => false,
路由的配置文件在config/route.php 中,配置文件作用是配置信息,定义文件在route/app.php,主要作用就是定义路由规则;

route 目录下的定义文件的文件名随机,都有效,或多个均有效果;

比如在route/app.php中书写规则

// Index控制器下的hello方法
Route::get('hello/:name', 'Index/hello');

对应的控制器中的方法是 controller/Index.php

public function hello($name = 'ThinkPHP6')
    {
        return 'hello,' . $name;
    }
通过命令行模式键入到当前项目目录后输入命令:php think run 启动, 此时,public 目录会自动被绑定到顶级域名:127.0.0.1:8000 上;我们只要在地址栏键入:http://localhost:8000 或(127.0.0.1:8000)即可;本地可能会提示让你访问started On <http://0.0.0.0:8000/>,这时候不要理会这个,直接访问上面提到127地址即可。

路由定义

先创建一个控制器controller/Address.php

<?php
namespace app\controller;

class Address
{
    public function index()
    {
        return 'index';
    }

    public function details($id)
    {
        return 'details 目前调用的id:'.$id;
    }
}

在没有定义路由规则的情况下,我们访问address/details 包含id 的URL 为:

http://localhost:8000/address/details/id/5 

或者http://localhost:8000/address/details/id/5.html [类似于静态的访问地址]

将这个URL 定义路由规则,在根目录route 下的app.php 里配置;

// Route::rule('地址(随意写)/:方法参数', '控制器/控制器的方法');
Route::rule('ds/:id', 'Address/details');
其中有Route::get Route::post Route::rule(get和post都支持),控制器首字母大小写均可,建议用大写语义更明确。

当路由配置好以后,源地址http://localhost:8000/address/details/id/5再访问就会提示非法请求的错误(不设置强制路由情况下,这个也应该可以正常访问),这时候就只能按照新的路由规则访问:

http://127.0.0.1:8000/ds/4 或者 http://127.0.0.1:8000/ds/4.html (4.php或者4.xml 都会整体当作参数传递,仅支持.html)

rule()方法是默认请求是any,即任何请求类型均可,第三参数可以限制:

Route::rule('details/:id', 'Address/xxx, 'GET'); //GET
Route::rule('details/:id', 'Address/xxx, 'POST'); //POST
Route::rule('details/:id', 'Address/xxx, 'GET|POST'); //GET 或POST
所有请求方式(快捷方式):GET(get)、POST(post)、DELETE(delete)、PUT(put)PATCH(patch)、*(any,任意请求方式) 默认是any
Route::get(...)、Route::post(...)、Route::delete(...)...

快捷方式,就是直接用Route::get、Route::post 等方式即可,无须第三参数;

地址栏一般都是get,不要用post 

当我们设置了强制路由的时候,访问首页就会报错,必须强制设置首页路由;

开始强制路由,需要在app/route.php 里面进行配置,然后配置首页路由(默认是false);

'url_route_must' => true,
Route::rule('/', 'Index/index'); //反斜杠就是首页默认访问的地址

设置强制路由后,每一个控制器路径都需要设置路由才行,否则无法访问

访问http://127.0.0.1:8000/address/details/id/5,就会提示:当前访问路由未定义或不匹配

同样的可以更改首页指向的控制器

Route::rule('/', 'Test/index');

在路由的规则表达式中,有多种地址的配置规则(比较常用)

//静态路由
Route::rule('ad', 'Address/index');
//静态动态结合的地址
Route::rule('details/:id', 'Address/details');
//多参数静态动态结合的地址
Route::rule('search/:id/:uid', 'Address/search');
//全动态地址,不限制是否search 固定
Route::rule(':search/:id/:uid', 'Address/search');
//包含可选参数的地址
Route::rule('find/:id/[:content]', 'Address/find');
//规则完全匹配的地址
Route::rule('search/:id/:uid$', 'Address/search');

路由定义好之后,我们在控制器要创建这个路由地址,可以通过url()方法实现

例如在控制器中,返回address/details/id/5 这个链接的路由地址:

不定义标识的做法

 public function url()
    {
        return url('Address/details', ['id' => 5]);
    }

访问这个方法就能获得:/ds/5.html 这个地址,即是路由地址。(通常这种地址用于模板中的链接)

如果没有设置对应的route规则,那么这个url方法会返回:/Address/details.html?id=5

定义标识的做法

 public function url()
    {
        Route::get('ds/:id', 'Address/details', 'GET|POST')->name('ds');
        return url('ds', ['id' => 5]);
    }

就是如果在app/route.php中没有定义规则,那么就用上面这种方法,给路由定义一个名字->name,然后再返回。

一般都使用第一种方法。

路由的变量规则和闭包

变量规则

系统默认的路由变量规则为\w+,即字母、数字、中文和下划线;

如果你想更改默认的匹配规则,可以修改config/route.php 配置(一般不需要更改)

// 默认的路由变量规则
'default_route_pattern' => '[\w\.]+',

如果我们需要对于具体的变量进行单独的规则设置,则需要通过pattern()方法;

将details 方法里的id 传值,严格限制必须只能是数字\d+;

Route::get('ds/:id', 'Address/details')->pattern([
    'id' => '\d+'
]);

这时候再访问

http://127.0.0.1:8000/ds/adas 直接报错

http://127.0.0.1:8000/ds/5adas 会将参数截断,5adas会只保留5,5.5也会只保留5

如果控制器方法中,需要传递多个参数,并分别设置不同的验证规则

控制器中

 public function search($id, $uid)
    {
        return "详情-{$id}-{$uid}";
    }

route/app.php

Route::get('ss/:id/:uid', 'Address/search')->pattern([
    'id' => '\d+',
    'uid' => '\d+'
]);

访问http://127.0.0.1:8000/ss/5/6 输出 详情-5-6

以上两种,均为局部变量规则,也可以直接在route/app.php 设置全局变量规则

//  在开头设置验证,那么其下面所有的路由都会按照这个规则验证
Route::pattern([
    'id' => '\d+',
    'uid' => '\d+'
]);

Route::get('ss/:id/:uid', 'Address/search');
此全局仅为本route/app.php的全局,并非整个系统的全局

也支持使用组合变量规则方式,实现路由规则

除了支持/:,还支持如下

Route::rule('ds-<id>', 'Address/details');

这时候访问地址就变成了:http://127.0.0.1:8000/ds-6,其中各种搭配随意组合,-也可以替换成_

动态组合的拼装,地址和参数如果都是模糊动态的,可以使用如下方法

比如,我有多个控制器文件,controller/Helloworld.php、Hellojs.php、Hellowu.php等,这时候就可以用动态控制器名

Route::rule('hi-<name>-<id>', 'Hello:name/index');

其中Hello:name ,Hellow是固定不变的字符串前缀,:name是动态变化的名称,而此名称就通过'hi-<name>-<id>中的<name>进行传递。如此,那么访问地址为:http://127.0.0.1:8000/hi-world-5或5.html,就访问到了Helloworld.php中的Index方法了。

Route::rule('hi/:name/:id', 'Hello:name/index');

闭包支持

闭包支持我们可以通过URL 直接执行,而不需要通过控制器和方法;只要执行了这个规则就会返回:

Route::get('think', function () {
    return 'hello,ThinkPHP6!';
});

同样的也可以传递参数

Route::get('think/:name', function ($name) {
    return "hello, {$name}";
});

路由的地址和参数

路由地址

路由的地址一般为:控制器/操作方法构成

//默认Index 控制器
Route::rule('/', 'index');
//控制器/操作方法
Route::rule('details/:id', 'Address/details');

支持多级控制器,并且支持路由到相应的地址;

//目录为:app\controller\group
namespace app\controller\group;
//地址为:app\controller\group
http://localhost:8000/group.blog/details/id/5
//支持多级路由
Route::rule('details/:id', 'group.Blog/details');

对于地址,还有一种完整路径的方式去执行操作方法:完整类名@操作方法

比如我创建一个静态方法

 public static function details2($id)
{
        return 'details 目前调用的id2:'.$id;
 }
Route::rule('ds/:id', 'app\controller\Address@details2');
Route::rule('ds/:id', '\app\controller\Address@details2');

另一种静态方式:完整路径支持这种方法的路由地址:完整类名::静态方法

Route::rule('ds/:id', '\app\controller\Address::details2');
注意:静态方式只能调用静态方法,如果调用非静态方法就会报错!@方法无论方法是不是静态都可以调用!

路由可以通过::redirect()方法实现重定向跳转,第三参数为状态码;

Route::redirect('ds/:id', 'http://localhost/', 302);

路由参数

设置路由的时候,可以设置相关方法进行,从而实施匹配检测和行为执行

ext 方法作用是检测URL 后缀,比如:我们强制所有URL 后缀为.html;

Route::rule('details/:id', 'address/details')->ext('html');
Route::rule('details/:id', 'address/details')->ext('html|shtml');

强制让地址链接末尾检测是否有html,添加了->ext(html),那么{id}.html就不会整体作为参数传递了。此时,只有访问{id}.html才不会报错。

https 方法作用是检测是否为https 请求,结合ext 强制html 如下

Route::get('details/:id', 'address/details')->ext('html')->https();

如果想让全局统一配置URL 后缀的话,可以在config/route.php 中设置

具体值可以是单个或多个后缀,也可以是空字符串(任意后缀),false 禁止后缀

// URL伪静态后缀
'url_html_suffix'       => 'html',

denyExt 方法作用是禁止某些后缀的使用,使用后直接报错,如下是禁止后缀为png和gif;

Route::rule('ds/:id', 'Address/details2')->denyExt('gif|png');

domain 方法作用是检测当前的域名是否匹配,完整域名和子域名均可

Route::rule('ds/:id', 'Address/details')->domain('localhost');
Route::rule('ds/:id', 'Address/details')->domain('news.abc.com');
Route::rule('ds/:id', 'Address/details')->domain('news'); // 简化的二级域名

如果验证失败那么就会报错。

ajax/pjax/json 方法作用是检测当前的页面是否是以上请求方式

Route::rule('ds/:id', 'Address/details')->ajax();

filter 方法作用是对额外参数进行检测,额外参数可表单提交post(严格看表单传递过来的参数是否匹配)

Route::rule('details/:id', 'address/details')->filter(['id'=>5, 'type'=>1]);

必须传递过来的参数是id=5 type=1的时候才能匹配到这个路由

append 方法作用是追加额外参数,这个额外参数并不需要通过URL 传递;

控制器中先写一个方法

 public function details2($id, $status)
    {
        return 'details 目前调用的id2:'.$id . $status;
    }

其中第二个参数,就用来接收append传递过来的额外的参数

// 追加一个参数
Route::rule('ds/:id', 'Address/details2')->append(['status' => 'a']);

如果你想统一配置多个参数,方便管理,可以使用option 方法数组配置;

Route::rule('ds/:id', 'Address/details')->option([
    'ext' => 'html', // 必须是html
    'https' => true  // 必须是https请求
]);

路由的域名和跨域请求

域名路由

如果想限定在news.abc.com 这个域名下才有效,通过域名路由闭包的形式

Route::domain('news.abc.com', function() {
    Route::rule('ds/:id', 'Address/details');
});

限定域名之后,使用localhost/ds/5就无法访问了,打开就会报错。

支持多个二级(子)域名开头部分,使用相同的路有规则

Route::domain(['news', 'blog', 'live'], function() {
    Route::rule('ds/:id', 'Address/details');
});

可以作为方法,进行二级(子)域名开头部分的检测,或完整域名检测

Route::rule('details/:id', 'Address/details')->domain('news');
Route::rule('details/:id', 'Address/details')->domain('news.abc.com');
路由域名也支持:ext、pattern、append 等路由参数方法的操作
Route::domain(['news', 'blog', 'live'], function() {
    Route::rule('ds/:id', 'Address/details');
})->ext('html');

即可以整体写,这些域名下的请求,后缀都使用->ext方法。

跨域请求

当不同域名进行跨域请求的时候,由于浏览器的安全限制,会被拦截

所以,为了解除这个限制,我们通过路由allowCrossDomain()来实现

Route::rule('details/:id', 'Address/details')->allowCrossDomain();
实现跨域比如没有实现的header 头文件多了几条开头为Access 的信息

如果你想限制跨域请求的域名,则可以增加一条参数

Route::rule('ds/:id', 'Address/details')
    ->allowCrossDomain([
        // 只能是news.abc.com:8000 这个域名来取我的数据 仅对其开放
        'Access-Control-Allow-Origin' => 'http://news.abc.com:8000'
    ]
);
点赞 支持一下 觉得不错?客官您就稍微鼓励一下吧!
关键词:thinkphp
推荐阅读
  • uniapp实现被浏览器唤起的功能

    当用户打开h5链接时候,点击打开app若用户在已经安装过app的情况下直接打开app,若未安装过跳到应用市场下载安装这个功能在实现上主要分为两种场景,从普通浏览器唤醒以及从微信唤醒。

    8337次阅读 531人点赞 发布时间: 2022-12-14 16:34:53 立即查看
  • Vue

    盘点Vue2和Vue3的10种组件通信方式

    Vue中组件通信方式有很多,其中Vue2和Vue3实现起来也会有很多差异;本文将通过选项式API组合式API以及setup三种不同实现方式全面介绍Vue2和Vue3的组件通信方式。

    3474次阅读 255人点赞 发布时间: 2022-08-19 09:40:16 立即查看
  • JS

    几个高级前端常用的API

    推荐4个前端开发中常用的高端API,分别是MutationObserver、IntersectionObserver、getComputedstyle、getBoundingClientRect、requ...

    13422次阅读 867人点赞 发布时间: 2021-11-11 09:39:54 立即查看
  • PHP

    【正则】一些常用的正则表达式总结

    在日常开发中,正则表达式是非常有用的,正则表达式在每个语言中都是可以使用的,他就跟JSON一样,是通用的。了解一些常用的正则表达式,能大大提高你的工作效率。

    12217次阅读 392人点赞 发布时间: 2021-10-09 15:58:58 立即查看
  • 【中文】免费可商用字体下载与考证

    65款免费、可商用、无任何限制中文字体打包下载,这些字体都是经过长期验证,经得住市场考验的,让您规避被无良厂商起诉的风险。

    10562次阅读 846人点赞 发布时间: 2021-07-05 15:28:45 立即查看
  • Vue

    Vue3开发一个v-loading的自定义指令

    在vue3中实现一个自定义的指令,有助于我们简化开发,简化复用,通过一个指令的调用即可实现一些可高度复用的交互。

    14437次阅读 1153人点赞 发布时间: 2021-07-02 15:58:35 立即查看
  • JS

    关于手机上滚动穿透问题的解决

    当页面出现浮层的时候,滑动浮层的内容,正常情况下预期应该是浮层下边的内容不会滚动;然而事实并非如此。在PC上使用css即可解决,但是在手机端,情况就变的比较复杂,就需要禁止触摸事件才可以。

    14342次阅读 1167人点赞 发布时间: 2021-05-31 09:25:50 立即查看
  • Vue

    Vue+html2canvas截图空白的问题

    在使用vue做信网单页专题时,有海报生成的功能,这里推荐2个插件:一个是html2canvas,构造好DOM然后转canvas进行截图;另外使用vue-canvas-poster(这个截止到2021年3月...

    27483次阅读 2157人点赞 发布时间: 2021-03-02 09:04:51 立即查看
  • Vue

    vue-router4过度动画无效解决方案

    在初次使用vue3+vue-router4时候,先后遇到了过度动画transition进入和退出分别无效的情况,搜遍百度没没找到合适解决方法,包括vue-route4有一些API都进行了变化,以前的一些操...

    23619次阅读 1820人点赞 发布时间: 2021-02-23 13:37:20 立即查看
交流 收藏 目录