>  기사  >  백엔드 개발  >  thinkphp5 URL 및 라우팅 기능에 대한 자세한 설명과 예시

thinkphp5 URL 및 라우팅 기능에 대한 자세한 설명과 예시

jacklove
jacklove원래의
2018-07-04 17:55:581869검색

이 글은 thinkphp5 URL과 라우팅 기능에 대한 자세한 설명과 예시를 주로 소개하고 있는데, 편집자 입장에서는 꽤 좋다고 생각해서 지금 공유하고 참고용으로 올려드리겠습니다. 편집기를 따라 살펴보겠습니다

이전 단어

이 기사에서는 thinkphp5URL 및 라우팅을 자세히 소개합니다

URL 액세스

ThinkPHP는 단일 입력 모드를 사용하여 애플리케이션에 액세스하고 모든 요청은 애플리케이션이 애플리케이션 항목 파일로 연결되면 시스템은 URL 매개변수에서 현재 요청된 모듈, 컨트롤러 및 작업을 구문 분석합니다. 다음은 표준 URL 액세스 형식입니다.

http://domainName/index.php/模块/控制器/操作

여기서 index.php가 호출됩니다. 응용 프로그램의 항목 파일 (항목 파일은 숨겨질 수 있으며 나중에 언급할 예정입니다.)

ThinkPHP에서 모듈의 개념은 실제로 응용 프로그램 디렉터리 아래의 하위 디렉터리이며 공식 사양에서는 디렉터리 이름이 소문자라는 것입니다. , 따라서 모듈 이름은 모두 소문자로 지정됩니다. URL이 대소문자를 지원하는지 여부에 관계없이 변환하면 모듈 이름이 강제로 소문자로 지정됩니다.

응용 프로그램 인덱스 모듈의 인덱스 컨트롤러는 다음과 같이 정의됩니다.

<?php
namespace app\index\controller;
class Index
{
  public function index()
  {
    return &#39;index&#39;;
  }
  public function hello($name = &#39;World&#39;)
  {
    return &#39;Hello,&#39; . $name . &#39;!&#39;;
  }
}

항목 파일에 직접 액세스하면 URL에 모듈, 컨트롤러 및 작업이 없기 때문에 시스템은 모듈(인덱스) 아래 기본 컨트롤러(인덱스)의 기본 동작에 액세스하므로 다음과 같습니다. 액세스는 동일합니다:

http://tp5.com/index.php
http://tp5.com/index.php/index/index/index

컨트롤러의 hello 메소드에 액세스하려면 전체 URL 주소를 사용해야 합니다

http://tp5.com/index.php/index/index/hello/name/thinkphp

URL 주소에 액세스한 후 페이지 출력 결과는 다음과 같습니다.

Hello, thinkphp!

name 매개변수는 선택 매개변수이므로 그대로 사용할 수도 있습니다

http://tp5.com/index.php/index/index/hello

URL 주소에 접속한 후 페이지 출력 결과는 다음과 같습니다.

Hello, World!

기본적으로 URL 주소의 컨트롤러 및 작업 이름은 대소문자를 구분하지 않으므로 다음 액세스는 실제로 동일합니다.

http://tp5.com/index.php/index/Index /Index
http://tp5.com/index.php/index/INDEX/INDEX

예를 들어 컨트롤러가 카멜케이스인 경우 HelloWorld 제어 컨트롤러(application/index/controller/HelloWorld.php)를 정의합니다.

<?php
namespace app\index\controller;
class HelloWorld
{
  public function index($name = &#39;World&#39;)
  {
    return &#39;Hello,&#39; . $name . &#39;!&#39;;
  }
}

올바른 URL 액세스 주소(주소는 url 메소드를 사용하여 생성할 수 있음)는

http://tp5.com/index.php/index/hello_world/index

이어야 합니다. 시스템이 자동으로 작동할 HelloWorld 컨트롤러 클래스

http://tp5.com/index.php/index/HelloWorld/index

를 사용하면 오류가 보고되고 Helloworld가 메시지가 표시됩니다. 컨트롤러 클래스가 존재하지 않습니다

If 엄격한 대소문자 구분 액세스를 원하는 경우(컨트롤러 액세스에 Camel Case 방식을 지원할 수 있도록) 애플리케이션 구성 파일에서 이를 설정할 수 있습니다.

// 关闭URL自动转换(支持驼峰访问控制器)
&#39;url_convert&#39; => false,

URL 자동 변환을 끈 후 Access를 사용해야 합니다. 다음 URL 주소(컨트롤러 이름은 컨트롤러 접미사를 제외하고 컨트롤러 클래스의 이름을 엄격하게 사용해야 함):

http://tp5.com/index.php/index/Index/index
http://tp5 . com/index.php/index/HelloWorld/index

서버 환경이 pathinfo URL 액세스를 지원하지 않는 경우 호환 가능한 방법을 사용할 수 있습니다. 예:

http://tp5.com/index.php?s= /index /Index/index

변수 s의 이름은 구성 가능합니다

5.0은 더 이상 일반 URL 액세스를 지원하지 않으므로 다음 액세스는 무엇을 입력해도 기본 컨트롤러에 액세스하게 됩니다. 그리고 연산

http://tp5.com/index.php?m=index&c=Index&a=hello

매개변수가 전달됩니다

연산 메소드의 매개변수 바인딩 기능을 통해 URL은 자동으로 얻을 수 있습니다. 여전히 위 컨트롤러를 예로 들면 컨트롤러 코드는 다음과 같습니다.

<?php
namespace app\index\controller;
class Index
{
  public function index()
  {
    return &#39;index&#39;;
  }
  public function hello($name = &#39;World&#39;)
  {
    return &#39;Hello,&#39; . $name . &#39;!&#39;;
  }
}

http://tp5.com/index.php/index/index/ hello

, appindexcontrollerIndex 컨트롤러에 액세스합니다. 클래스의 hello 메소드에서는 매개변수가 전달되지 않으므로 name 매개변수는 기본값인 World를 사용합니다. name 매개변수가 전달되면 다음을 사용하세요.

http://tp5.com/index.php/index/index/hello/name/thinkphp

페이지 출력 결과는 다음과 같습니다.

Hello, thinkphp!

Now give hello 이 메소드는 두 번째 매개변수를 추가합니다:

public function hello($name = &#39;World&#39;, $city = &#39;&#39;)
  {
    return &#39;Hello,&#39; . $name . &#39;! You come from &#39; . $city . &#39;.&#39;;
  }

액세스 주소는 http://tp5.com/index.php/index/index/hello/name/thinkphp/city/shanghai

페이지 출력입니다. 결과는 다음과 같습니다.

Hello, thinkphp! 당신은 상하이에서 왔습니다.

hello 메소드는 메소드의 매개변수 값으로 URL 주소에서 동일한 이름의 매개변수 값을 자동으로 가져오는 것을 볼 수 있습니다. 이 매개변수는 URL 매개변수의 순서에 영향을 받지 않습니다. 예를 들어 다음 URL 주소의 출력 결과는 위와 동일합니다.

http://tp5.com/index.php/index/index/ hello/city/shanghai/name/thinkphp

또는 http://tp5.com/index.php/index/index/hello?city=shanghai&name=thinkphp

를 사용하세요. URL 주소도 더욱 단순화될 수 있습니다. 매개변수의 순서로 표시되는 변수를 명확히 해야 합니다. URL 매개변수를 얻는 방법을 변경해 보겠습니다. 애플리케이션 구성 파일의 url_param_type 매개변수 값은 다음과 같이 수정됩니다.

现在,URL的参数传值方式就变成了严格按照操作方法的变量定义顺序来传值了,也就是说我们必须使用下面的URL地址访问才能正确传入name和city参数到hello方法:http://tp5.com/index.php/index/index/hello/thinkphp/shanghai

页面输出结果为:

Hello,thinkphp! You come from shanghai.

如果改变参数顺序为http://tp5.com/index.php/index/index/hello/shanghai/thinkphp

页面输出结果为:

Hello,shanghai! You come from thinkphp.

显然不是我们预期的结果。

同样,我们试图通过http://tp5.com/index.php/index/index/hello/name/thinkphp/city/shanghai

访问也不会得到正确的结果

[注意]按顺序绑定参数的话,操作方法的参数只能使用URL pathinfo变量,而不能使用get或者post变量

隐藏入口

可以去掉URL地址里面的入口文件index.php,但是需要额外配置WEB服务器的重写规则。

以Apache为例,需要在入口文件的同级添加.htaccess文件(官方默认自带了该文件),内容如下

<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>

如果用的phpstudy,规则如下:

<IfModule mod_rewrite.c> 
Options +FollowSymlinks -Multiviews 
RewriteEngine on 
RewriteCond %{REQUEST_FILENAME} !-d 
RewriteCond %{REQUEST_FILENAME} !-f 
RewriteRule ^(.*)$ index.php [L,E=PATH_INFO:$1] 
</IfModule>

接下来就可以使用下面的URL地址访问了

http://tp5.com/index/index/index
http://tp5.com/index/index/hello

如果使用的apache版本使用上面的方式无法正常隐藏index.php,可以尝试使用下面的方式配置.htaccess文件:

<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
</IfModule>

如果是Nginx环境的话,可以在Nginx.conf中添加:

location / { // …..省略部分代码
  if (!-e $request_filename) {
    rewrite ^(.*)$ /index.php?s=/$1 last;
    break;
  }
}

定义路由

URL地址里面的index模块怎么才能省略呢,默认的URL地址显得有点长,下面就来说说如何通过路由简化URL访问。

我们在路由定义文件(application/route.php)里面添加一些路由规则,如下:

return [
  // 添加路由规则 路由到 index控制器的hello操作方法
  &#39;hello/:name&#39; => &#39;index/index/hello&#39;,
];

该路由规则表示所有hello开头的并且带参数的访问都会路由到index控制器的hello操作方法。

路由之前的URL访问地址为:http://tp5.com/index/index/hello/name/thinkphp

定义路由后就只能访问下面的URL地址http://tp5.com/hello/thinkphp

[注意]定义路由规则后,原来的URL地址将会失效,变成非法请求。

但这里有一个小问题,如果我们只是访问http://tp5.com/hello

将发生错误

事实上这是由于路由没有正确匹配到,我们修改路由规则如下:

return [
  // 路由参数name为可选
  &#39;hello/[:name]&#39; => &#39;index/hello&#39;,
];

使用[]把路由规则中的变量包起来,就表示该变量为可选,接下来就可以正常访问了http://tp5.com/hello

当name参数没有传入值的时候,hello方法的name参数有默认值World,所以输出的内容为 Hello,World!

除了路由配置文件中定义之外,还可以采用动态定义路由规则的方式定义,例如在路由配置文件(application/route.php)的开头直接添加下面的方法:

use think\Route;
Route::rule(&#39;hello/:name&#39;, &#39;index/hello&#39;);

完成的效果和使用配置方式定义是一样的。

无论是配置方式还是通过Route类的方法定义路由,都统一放到路由配置文件application/route.php文件中

[注意]路由配置不支持在模块配置文件中设置

【完整匹配】

前面定义的路由是只要以hello开头就能进行匹配,如果需要完整匹配,可以使用下面的定义:

return [
  // 路由参数name为可选
  &#39;hello/[:name]$&#39; => &#39;index/hello&#39;,
];

当路由规则以$结尾的时候就表示当前路由规则需要完整匹配。

当我们访问下面的URL地址的时候:

http://tp5.com/hello // 正确匹配
http://tp5.com/hello/thinkphp // 正确匹配
http://tp5.com/hello/thinkphp/val/value // 不会匹配

【闭包定义】

还支持通过定义闭包为某些特殊的场景定义路由规则,例如:

return [
  // 定义闭包
  &#39;hello/[:name]&#39; => function ($name) {
    return &#39;Hello,&#39; . $name . &#39;!&#39;;
  },
];

或者

use think\Route;
Route::rule(&#39;hello/:name&#39;, function ($name) {
  return &#39;Hello,&#39; . $name . &#39;!&#39;;
});

[注意]闭包函数的参数就是路由规则中定义的变量

因此,当访问下面的URL地址:http://tp5.com/hello/thinkphp

会输出

Hello,thinkphp!

【设置URL分隔符】

如果需要改变URL地址中的pathinfo参数分隔符,只需要在应用配置文件(application/config.php)中设置:

// 设置pathinfo分隔符
&#39;pathinfo_depr&#39;     => &#39;-&#39;,

路由规则定义无需做任何改变,我们就可以访问下面的地址:http://tp5.com/hello-thinkphp

【路由参数】

还可以约束路由规则的请求类型或者URL后缀之类的条件,例如:

return [
  // 定义路由的请求类型和后缀
  &#39;hello/[:name]&#39; => [&#39;index/hello&#39;, [&#39;method&#39; => &#39;get&#39;, &#39;ext&#39; => &#39;html&#39;]],
];

上面定义的路由规则限制了必须是get请求,而且后缀必须是html的,所以下面的访问地址:

http://tp5.com/hello // 无效
http://tp5.com/hello.html // 有效
http://tp5.com/hello/thinkphp // 无效
http://tp5.com/hello/thinkphp.html // 有效

【变量规则】

接下来,尝试一些复杂的路由规则定义满足不同的路由变量。在此之前,首先增加一个控制器类如下:

<?php
namespace app\index\controller;
class Blog
{
  public function get($id)
  {
    return &#39;查看id=&#39; . $id . &#39;的内容&#39;;
  }
  public function read($name)
  {
    return &#39;查看name=&#39; . $name . &#39;的内容&#39;;
  }
  public function archive($year, $month)
  {
    return &#39;查看&#39; . $year . &#39;/&#39; . $month . &#39;的归档内容&#39;;
  }
}

添加如下路由规则:

return [
  &#39;blog/:year/:month&#39; => [&#39;blog/archive&#39;, [&#39;method&#39; => &#39;get&#39;], [&#39;year&#39; => &#39;\d{4}&#39;, &#39;month&#39; => &#39;\d{2}&#39;]],
  &#39;blog/:id&#39;     => [&#39;blog/get&#39;, [&#39;method&#39; => &#39;get&#39;], [&#39;id&#39; => &#39;\d+&#39;]],
  &#39;blog/:name&#39;    => [&#39;blog/read&#39;, [&#39;method&#39; => &#39;get&#39;], [&#39;name&#39; => &#39;\w+&#39;]],
];

在上面的路由规则中,我们对变量进行的规则约束,变量规则使用正则表达式进行定义。

我们看下几种URL访问的情况

// 访问id为5的内容
http://tp5.com/blog/5
// 访问name为thinkphp的内容
http://tp5.com/blog/thinkphp
// 访问2015年5月的归档内容
http://tp5.com/blog/2015/05

 【路由分组】

上面的三个路由规则由于都是blog打头,所以我们可以做如下的简化:

return [
  &#39;[blog]&#39; => [
    &#39;:year/:month&#39; => [&#39;blog/archive&#39;, [&#39;method&#39; => &#39;get&#39;], [&#39;year&#39; => &#39;\d{4}&#39;, &#39;month&#39; => &#39;\d{2}&#39;]],  
    &#39;:id&#39;     => [&#39;blog/get&#39;, [&#39;method&#39; => &#39;get&#39;], [&#39;id&#39; => &#39;\d+&#39;]],
    &#39;:name&#39;    => [&#39;blog/read&#39;, [&#39;method&#39; => &#39;get&#39;], [&#39;name&#39; => &#39;\w+&#39;]],
  ],
];

对于这种定义方式,我们称之为路由分组,路由分组一定程度上可以提高路由检测的效率

【复杂路由】

有时候,还需要对URL做一些特殊的定制,例如如果要同时支持下面的访问地址

http://tp5.com/blog/thinkphp
http://tp5.com/blog-2015-05

我们只要稍微改变路由定义规则即可:

return [
  &#39;blog/:id&#39;      => [&#39;blog/get&#39;, [&#39;method&#39; => &#39;get&#39;], [&#39;id&#39; => &#39;\d+&#39;]],
  &#39;blog/:name&#39;     => [&#39;blog/read&#39;, [&#39;method&#39; => &#39;get&#39;], [&#39;name&#39; => &#39;\w+&#39;]],
  &#39;blog-<year>-<month>&#39; => [&#39;blog/archive&#39;, [&#39;method&#39; => &#39;get&#39;], [&#39;year&#39; => &#39;\d{4}&#39;, &#39;month&#39; => &#39;\d{2}&#39;]],
];

对 blog-4620f01c9fab72e23a9b679732106cc4-e43ddfe88b0c33e4d0d4a6906a4e933c 这样的非正常规范,我们需要使用e78ad71b8a45d2a3209df4d26f1fcfa6这样的变量定义方式,而不是 :变量名方式。

简单起见,我们还可以把变量规则统一定义,例如:

return [
  // 全局变量规则定义
  &#39;__pattern__&#39;     => [
    &#39;name&#39; => &#39;\w+&#39;,
    &#39;id&#39;  => &#39;\d+&#39;,
    &#39;year&#39; => &#39;\d{4}&#39;,
    &#39;month&#39; => &#39;\d{2}&#39;,
  ],
  // 路由规则定义
  &#39;blog/:id&#39;      => &#39;blog/get&#39;,
  &#39;blog/:name&#39;     => &#39;blog/read&#39;,
  &#39;blog-<year>-<month>&#39; => &#39;blog/archive&#39;,
];

在__pattern__中定义的变量规则我们称之为全局变量规则,在路由规则里面定义的变量规则我们称之为局部变量规则,如果一个变量同时定义了全局规则和局部规则的话,当前的局部规则会覆盖全局规则的,例如:

return [
  // 全局变量规则
  &#39;__pattern__&#39;     => [
    &#39;name&#39; => &#39;\w+&#39;,
    &#39;id&#39;  => &#39;\d+&#39;,
    &#39;year&#39; => &#39;\d{4}&#39;,
    &#39;month&#39; => &#39;\d{2}&#39;,
  ],

  &#39;blog/:id&#39;      => &#39;blog/get&#39;,
  // 定义了局部变量规则
  &#39;blog/:name&#39;     => [&#39;blog/read&#39;, [&#39;method&#39; => &#39;get&#39;], [&#39;name&#39; => &#39;\w{5,}&#39;]],
  &#39;blog-<year>-<month>&#39; => &#39;blog/archive&#39;,
];

URL生成

定义路由规则之后,可以通过Url类来方便的生成实际的URL地址(路由地址),针对上面的路由规则,我们可以用下面的方式生成URL地址。

// 输出 blog/thinkphp
Url::build(&#39;blog/read&#39;, &#39;name=thinkphp&#39;);
Url::build(&#39;blog/read&#39;, [&#39;name&#39; => &#39;thinkphp&#39;]);
// 输出 blog/5
Url::build(&#39;blog/get&#39;, &#39;id=5&#39;);
Url::build(&#39;blog/get&#39;, [&#39;id&#39; => 5]);
// 输出 blog/2015/05
Url::build(&#39;blog/archive&#39;, &#39;year=2015&month=05&#39;);
Url::build(&#39;blog/archive&#39;, [&#39;year&#39; => &#39;2015&#39;, &#39;month&#39; => &#39;05&#39;]);

[注意]build方法的第一个参数使用路由定义中的完整路由地址

还可以使用系统提供的助手函数url来简化

url(&#39;blog/read&#39;, &#39;name=thinkphp&#39;);
// 等效于
Url::build(&#39;blog/read&#39;, &#39;name=thinkphp&#39;);

通常在模板文件中输出的话,可以使用助手函数,例如:

{:url(&#39;blog/read&#39;, &#39;name=thinkphp&#39;)}

如果我们的路由规则发生调整,生成的URL地址会自动变化

如果你配置了url_html_suffix参数的话,生成的URL地址会带上后缀,例如:

&#39;url_html_suffix&#39;  => &#39;html&#39;,

那么生成的URL地址 类似

blog/thinkphp.html 
blog/2015/05.html

如果你的URL地址全部采用路由方式定义,也可以直接使用路由规则来定义URL生成,例如:

url(&#39;/blog/thinkphp&#39;);
Url::build(&#39;/blog/8&#39;);
Url::build(&#39;/blog/archive/2015/05&#39;);

生成方法的第一个参数一定要和路由定义的路由地址保持一致,如果你的路由地址比较特殊,例如使用闭包定义的话,则需要手动给路由指定标识,例如: 

// 添加hello路由标识
Route::rule([&#39;hello&#39;,&#39;hello/:name&#39;], function($name){
  return &#39;Hello,&#39;.$name;
});
// 根据路由标识快速生成URL
Url::build(&#39;hello&#39;, &#39;name=thinkphp&#39;);
// 或者使用
Url::build(&#39;hello&#39;, [&#39;name&#39; => &#39;thinkphp&#39;]);

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持php中文网。

您可能感兴趣的文章:

PHP基于双向链表与排序操作实现的会员排名功能示例_php技巧

PHP实现求连续子数组最大和问题2种解决方法讲解

php获取ajax的headers方法与内容实例讲解

위 내용은 thinkphp5 URL 및 라우팅 기능에 대한 자세한 설명과 예시의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.