この記事では主に 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 'index'; } public function hello($name = 'World') { return 'Hello,' . $name . '!'; } }
エントリーファイルに直接アクセスする場合、URL にはモジュール、コントローラー、オペレーションが含まれていないため、システムは以下のデフォルトモジュール (index)、デフォルトコントローラー (Index) のデフォルトアクション (index) にアクセスします。次のアクセスは同等です:
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 アドレスの後に出力されるページは次のとおりです:
こんにちは。 World!
デフォルトでは、URL アドレス内のコントローラー名とオペレーション名は大文字と小文字が区別されないため、次のアクセスは実際には同等です:
http://tp5.com/index.php/index/Index/Index
http://tp5.com/index.php/index/INDEX/INDEX
たとえば、コントローラーがキャメルケースの場合、HelloWorld コントローラー (アプリケーション /index/controller/HelloWorld.php) を定義します。
<?php namespace app\index\controller; class HelloWorld { public function index($name = 'World') { return 'Hello,' . $name . '!'; } }
正しい URL アクセス アドレス (アドレスは url メソッドを使用して生成できます) は次のとおりです。
http://tp5.com/index.php/index/hello_world /index
システムは自動的に HelloWorld コントローラー クラスを見つけます。操作
を使用する場合
http://tp5.com/index.php/index/HelloWorld/index
エラーが報告され、Helloworld コントローラー クラスが要求されます 存在しません
厳密にしたい場合大文字と小文字を区別するアクセス (コントローラー アクセスでキャメル ケースをサポートできるように) をアプリケーション構成ファイルで設定できます:
// 关闭URL自动转换(支持驼峰访问控制器) 'url_convert' => false,
URL 自動変換をオフにした後は、次の 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/インデックス
変数の名前を設定できます
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 'index'; } public function hello($name = 'World') { return 'Hello,' . $name . '!'; } }
にアクセスすると、
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 このメソッドは 2 番目のパラメーターを追加します:
public function hello($name = 'World', $city = '') { return 'Hello,' . $name . '! You come from ' . $city . '.'; }
アクセス アドレスは http://tp5.com/index.php/index/index/hello/name/thinkphp/city/shanghai
ページの出力です
こんにちは、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操作方法 'hello/:name' => 'index/index/hello', ];
该路由规则表示所有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为可选 'hello/[:name]' => 'index/hello', ];
使用[]把路由规则中的变量包起来,就表示该变量为可选,接下来就可以正常访问了http://tp5.com/hello
当name参数没有传入值的时候,hello方法的name参数有默认值World,所以输出的内容为 Hello,World!
除了路由配置文件中定义之外,还可以采用动态定义路由规则的方式定义,例如在路由配置文件(application/route.php)的开头直接添加下面的方法:
use think\Route; Route::rule('hello/:name', 'index/hello');
完成的效果和使用配置方式定义是一样的。
无论是配置方式还是通过Route类的方法定义路由,都统一放到路由配置文件application/route.php文件中
[注意]路由配置不支持在模块配置文件中设置
【完整匹配】
前面定义的路由是只要以hello开头就能进行匹配,如果需要完整匹配,可以使用下面的定义:
return [ // 路由参数name为可选 'hello/[:name]$' => 'index/hello', ];
当路由规则以$结尾的时候就表示当前路由规则需要完整匹配。
当我们访问下面的URL地址的时候:
http://tp5.com/hello // 正确匹配
http://tp5.com/hello/thinkphp // 正确匹配
http://tp5.com/hello/thinkphp/val/value // 不会匹配
【闭包定义】
还支持通过定义闭包为某些特殊的场景定义路由规则,例如:
return [ // 定义闭包 'hello/[:name]' => function ($name) { return 'Hello,' . $name . '!'; }, ];
或者
use think\Route; Route::rule('hello/:name', function ($name) { return 'Hello,' . $name . '!'; });
[注意]闭包函数的参数就是路由规则中定义的变量
因此,当访问下面的URL地址:http://tp5.com/hello/thinkphp
会输出
Hello,thinkphp!
【设置URL分隔符】
如果需要改变URL地址中的pathinfo参数分隔符,只需要在应用配置文件(application/config.php)中设置:
// 设置pathinfo分隔符 'pathinfo_depr' => '-',
路由规则定义无需做任何改变,我们就可以访问下面的地址:http://tp5.com/hello-thinkphp
【路由参数】
还可以约束路由规则的请求类型或者URL后缀之类的条件,例如:
return [ // 定义路由的请求类型和后缀 'hello/[:name]' => ['index/hello', ['method' => 'get', 'ext' => 'html']], ];
上面定义的路由规则限制了必须是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 '查看id=' . $id . '的内容'; } public function read($name) { return '查看name=' . $name . '的内容'; } public function archive($year, $month) { return '查看' . $year . '/' . $month . '的归档内容'; } }
添加如下路由规则:
return [ 'blog/:year/:month' => ['blog/archive', ['method' => 'get'], ['year' => '\d{4}', 'month' => '\d{2}']], 'blog/:id' => ['blog/get', ['method' => 'get'], ['id' => '\d+']], 'blog/:name' => ['blog/read', ['method' => 'get'], ['name' => '\w+']], ];
在上面的路由规则中,我们对变量进行的规则约束,变量规则使用正则表达式进行定义。
我们看下几种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 [ '[blog]' => [ ':year/:month' => ['blog/archive', ['method' => 'get'], ['year' => '\d{4}', 'month' => '\d{2}']], ':id' => ['blog/get', ['method' => 'get'], ['id' => '\d+']], ':name' => ['blog/read', ['method' => 'get'], ['name' => '\w+']], ], ];
对于这种定义方式,我们称之为路由分组,路由分组一定程度上可以提高路由检测的效率
【复杂路由】
有时候,还需要对URL做一些特殊的定制,例如如果要同时支持下面的访问地址
http://tp5.com/blog/thinkphp
http://tp5.com/blog-2015-05
我们只要稍微改变路由定义规则即可:
return [ 'blog/:id' => ['blog/get', ['method' => 'get'], ['id' => '\d+']], 'blog/:name' => ['blog/read', ['method' => 'get'], ['name' => '\w+']], 'blog-<year>-<month>' => ['blog/archive', ['method' => 'get'], ['year' => '\d{4}', 'month' => '\d{2}']], ];
对 blog-4620f01c9fab72e23a9b679732106cc4-e43ddfe88b0c33e4d0d4a6906a4e933c 这样的非正常规范,我们需要使用e78ad71b8a45d2a3209df4d26f1fcfa6这样的变量定义方式,而不是 :变量名方式。
简单起见,我们还可以把变量规则统一定义,例如:
return [ // 全局变量规则定义 '__pattern__' => [ 'name' => '\w+', 'id' => '\d+', 'year' => '\d{4}', 'month' => '\d{2}', ], // 路由规则定义 'blog/:id' => 'blog/get', 'blog/:name' => 'blog/read', 'blog-<year>-<month>' => 'blog/archive', ];
在__pattern__中定义的变量规则我们称之为全局变量规则,在路由规则里面定义的变量规则我们称之为局部变量规则,如果一个变量同时定义了全局规则和局部规则的话,当前的局部规则会覆盖全局规则的,例如:
return [ // 全局变量规则 '__pattern__' => [ 'name' => '\w+', 'id' => '\d+', 'year' => '\d{4}', 'month' => '\d{2}', ], 'blog/:id' => 'blog/get', // 定义了局部变量规则 'blog/:name' => ['blog/read', ['method' => 'get'], ['name' => '\w{5,}']], 'blog-<year>-<month>' => 'blog/archive', ];
URL生成
定义路由规则之后,可以通过Url类来方便的生成实际的URL地址(路由地址),针对上面的路由规则,我们可以用下面的方式生成URL地址。
// 输出 blog/thinkphp Url::build('blog/read', 'name=thinkphp'); Url::build('blog/read', ['name' => 'thinkphp']); // 输出 blog/5 Url::build('blog/get', 'id=5'); Url::build('blog/get', ['id' => 5]); // 输出 blog/2015/05 Url::build('blog/archive', 'year=2015&month=05'); Url::build('blog/archive', ['year' => '2015', 'month' => '05']);
[注意]build方法的第一个参数使用路由定义中的完整路由地址
还可以使用系统提供的助手函数url来简化
url('blog/read', 'name=thinkphp'); // 等效于 Url::build('blog/read', 'name=thinkphp');
通常在模板文件中输出的话,可以使用助手函数,例如:
{:url('blog/read', 'name=thinkphp')}
如果我们的路由规则发生调整,生成的URL地址会自动变化
如果你配置了url_html_suffix参数的话,生成的URL地址会带上后缀,例如:
'url_html_suffix' => 'html',
那么生成的URL地址 类似
blog/thinkphp.html blog/2015/05.html
如果你的URL地址全部采用路由方式定义,也可以直接使用路由规则来定义URL生成,例如:
url('/blog/thinkphp'); Url::build('/blog/8'); Url::build('/blog/archive/2015/05');
生成方法的第一个参数一定要和路由定义的路由地址保持一致,如果你的路由地址比较特殊,例如使用闭包定义的话,则需要手动给路由指定标识,例如:
// 添加hello路由标识 Route::rule(['hello','hello/:name'], function($name){ return 'Hello,'.$name; }); // 根据路由标识快速生成URL Url::build('hello', 'name=thinkphp'); // 或者使用 Url::build('hello', ['name' => 'thinkphp']);
相关推荐:
以上がthinkphp5 の URL とルーティング関数の詳細な説明と例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。