路由
class Cake\Routing\
路由提供了将URL映射到控制器操作的工具。 通过定义路由,您可以分离应用程序的实现方式与其URL的结构。
在CakePHP中的路由还包括反向路由的想法,其中参数数组可以转换为URL字符串。 通过使用反向路由,您可以重新考虑应用程序的网址结构,而无需更新所有代码。
快速浏览
本节将通过示例介绍CakePHP路由器的最常见用法。 通常,您希望将某些内容显示为目标网页,因此您需要将其添加到routes.php文件中:
use Cake\Routing\Router;
// Using the scoped route builder.
Router::scope('/', function ($routes) {
$routes->connect('/', ['controller' => 'Articles', 'action' => 'index']);
});
// Using the static method.
Router::connect('/', ['controller' => 'Articles', 'action' => 'index']);
Router
提供两个接口用于连接路由。 静态方法是向后兼容的接口,而作用域构建器在构建多个路由时提供更简洁的语法,并提供更好的性能。
当你的网站的主页被访问时,这将执行ArticlesController
的索引方法。 有时候,您需要接受多个参数的动态路由,例如,查看文章内容的路由就是这种情况:
Router::connect('/articles/*', ['controller' => 'Articles', 'action' => 'view']);
上述路由将接受任何看起来像
/articles/15
URL,并调用ArticlesController
的方法view(15)
。 但这不会阻止人们尝试访问看起来像/articles/foobar
网址。 如果你愿意,你可以限制一些参数符合正则表达式:
Router::connect(
'/articles/:id',
['controller' => 'Articles', 'action' => 'view'],
['id' => '\d+', 'pass' => ['id']]
);
上一个示例将星座匹配器更改为一个新的占位符:id
。 使用占位符允许我们验证URL的部分,在这种情况下,我们使用\d+
正则表达式,以便只有数字匹配。 最后,我们告诉路由器通过指定pass
选项将id
占位符作为view()
函数的函数参数。 稍后再使用此选项。
CakePHP路由器还可以反向匹配路由。 这意味着,从包含匹配参数的数组,它能够生成一个URL字符串:
use Cake\Routing\Router;
echo Router::url(['controller' => 'Articles', 'action' => 'view', 'id' => 15]);
// Will output
/articles/15
路由还可以标记为唯一的名称,这允许您在构建链接时快速引用它们,而不是指定每个路由参数:
use Cake\Routing\Router;
Router::connect(
'/login',
['controller' => 'Users', 'action' => 'login'],
['_name' => 'login']
);
echo Router::url(['_name' => 'login']);
// Will output
/login
为了帮助保持路由代码干燥,路由器具有“范围”的概念。 范围定义公共路径段,并且可选地路由默认值。 在范围内连接的任何路由将从其包装范围继承路径/默认值:
Router::scope('/blog', ['plugin' => 'Blog'], function ($routes) {
$routes->connect('/', ['controller' => 'Articles']);
});
上述路由将匹配/blog/
并发送到Blog\Controller\ArticlesController::index()
。
应用程序框架带有几个路由,让您开始。 添加自己的路由后,如果不需要,可以删除默认路由。
连接路由
-
static
Cake\Routing\Router::
connect
( $ route , $ defaults = [] , $ options = [] )
为了保持代码干燥,你应该使用“路由范围”。 路由范围不仅让你保持你的代码DRY,他们还帮助路由器优化其操作。 如上所示,你也可以使用Router::connect()
连接路由。 此方法默认为/
scope。 要创建一个范围并连接一些路由,我们将使用scope()
方法:
// In config/routes.php
use Cake\Routing\Route\DashedRoute;
Router::scope('/', function ($routes) {
$routes->fallbacks(DashedRoute::class);
});
connect()
方法最多需要三个参数:您要匹配的URL模板,路由元素的默认值和路由选项。 选项经常包括正则表达式规则,以帮助路由器匹配URL中的元素。
路由定义的基本格式为:
$routes->connect(
'URL template',
['default' => 'defaultValue'],
['option' => 'matchingRegex']
);
第一个参数用于告诉路由器您尝试控制哪种类型的URL。 URL是正常的斜线分隔字符串,但也可以包含通配符(*)或路由元素 。 使用通配符告诉路由器您愿意接受任何提供的附加参数。 没有*的路由仅匹配提供的确切模板模式。
一旦你指定了一个URL,你使用connect()
的最后两个参数来告诉CakePHP在一个请求匹配后如何处理。 第二个参数是关联数组。 数组的键应以URL模板表示的路由元素命名。 数组中的值是这些键的默认值。 让我们看看一些基本的例子,我们开始使用connect()的第三个参数:
$routes->connect(
'/pages/*',
['controller' => 'Pages', 'action' => 'display']
);
此路由在用CakePHP分发的routes.php文件中找到。 它匹配以/pages/
开头的任何URL,并将它转移到PagesController
的display()
操作。 对/pages/products
请求将映射到PagesController->display('products')
。
除了贪婪的星/*
还有/**
结尾的星号语法。 使用结尾双星,将捕获URL的剩余部分作为单个传递的参数。 当您想要使用包含/
的参数时,这是有用的:
$routes->connect(
'/pages/**',
['controller' => 'Pages', 'action' => 'show']
);
/pages/the-example-/-and-proof
的传入URL将导致一个传递the-example-/-and-proof
。
您可以使用connect()
的第二个参数提供由路由的默认值组成的任何路由参数:
$routes->connect(
'/government',
['controller' => 'Pages', 'action' => 'display', 5]
);
此示例显示如何使用connect()
的第二个参数定义默认参数。 如果您构建了一个网站,其中包含针对不同类别客户的产品,则可以考虑创建路由。 这允许您链接到/government
而不是/pages/display/5
。
路由器的另一个常见用途是为控制器定义“别名”。 让我们说,不是访问/users/some_action/5
的常规URL,我们希望能够通过/cooks/some_action/5
访问它。 以下路由处理:
$routes->connect(
'/cooks/:action/*', ['controller' => 'Users']
);
这告诉路由器任何以/cooks/
开头的URL都应该发送给用户控制器。 调用的操作将取决于:action
参数的值。 通过使用路由元素 ,您可以创建可变路由,接受用户输入或变量。 上述路线也使用贪婪星。 贪婪的星标表示Router
这个路由应该接受任何额外的位置参数给定。 这些参数将在Passed Arguments数组中可用 。
当生成URL时,也使用路由。 如果上述路由是找到的第一个匹配['controller' => 'Users', 'action' =>'some_action', 5]
使用['controller' => 'Users', 'action' => 'some_action', 5]
作为URL将输出/cooks/some_action/5
。
路由元素
您可以指定自己的路由元素,这样您就可以在URL中定义控制器操作的参数所在的位置。 当发出请求时,这些路由元素的值在控制器的$this->request->getParam()
中找到。 当定义自定义路由元素时,您可以选择指定正则表达式 - 这告诉CakePHP如何知道URL是否正确形成。 如果选择不提供正则表达式,则任何非字符将被视为参数的一部分:
$routes->connect(
'/:controller/:id',
['action' => 'view'],
['id' => '[0-9]+']
);
上面的例子说明了如何创建一个快速的方法来从任何控制器通过创建一个看起来像/controllername/:id
的URL来查看模型。 提供给connect()
的URL指定两个路由元素:controller
和:id
。 :controller
元素是CakePHP默认路由元素,因此路由器知道如何匹配和识别URL中的控制器名称。 :id
元素是自定义路由元素,必须通过在connect()的第三个参数中指定匹配的正则表达式来进一步澄清。
当使用:controller
参数时,CakePHP不会自动生成小写和虚线的URL。 如果你需要这个,上面的例子可以这样改写:
use Cake\Routing\Route\DashedRoute;
$routes->connect(
'/:controller/:id',
['action' => 'view'],
['id' => '[0-9]+', 'routeClass' => DashedRoute::class]
);
DashedRoute
类将确保:controller
和:plugin
参数正确地小写和虚线。
如果在从CakePHP 2.x应用程序迁移时需要低阶和低字节URL,则可以使用InflectedRoute
类。
▲ 注意: 用于路线元素的模式不能包含任何捕获组。 如果它们,路由器将无法正常工作。
一旦定义了这个路由,请求/apples/5
将调用ApplesController的view()方法。 在view()方法中,您需要访问$this->request->getParam('id')
传递的ID。
如果应用程序中有单个控制器,并且不希望控制器名称显示在URL中,则可以将所有URL映射到控制器中的操作。 例如,要将所有URL映射到home
控制器的操作,例如具有/demo
而不是/home/demo
URL,您可以执行以下操作:
$routes->connect('/:action', ['controller' => 'Home']);
如果您想提供不区分大小写的网址,可以使用正则表达式内联修饰符:
$routes->connect(
'/:userShortcut',
['controller' => 'Teachers', 'action' => 'profile', 1],
['userShortcut' => '(?i:principal)']
);
再举一个例子,你会成为一个路由专家:
$routes->connect(
'/:controller/:year/:month/:day',
['action' => 'index'],
[
'year' => '[12][0-9]{3}',
'month' => '0[1-9]|1[012]',
'day' => '0[1-9]|[12][0-9]|3[01]'
]
);
这是相当参与,但显示如何强大的路线可以。 提供的URL具有四个路由元素。 第一个是我们熟悉的:它是一个默认路由元素,它告诉CakePHP期望一个控制器名称。
接下来,我们指定一些默认值。 不管控制器如何,我们想要调用index()动作。
最后,我们指定将以数字形式匹配年,月和日的一些正则表达式。 请注意,正则表达式中不支持括号(分组)。 您仍然可以指定替代项,如上所述,但不能用括号分组。
一旦定义,此路由将匹配/articles/2007/02/01
, /articles/2004/11/16
2004/11/16,将请求传递到各自控制器的index()动作,日期参数在$this->request->getParam()
在CakePHP中有几个具有特殊含义的路由元素,除非你想要特殊的含义,否则不应该使用
controller
用于为路由命名控制器。action
用于为路由命名控制器操作。plugin
用于命名控制器所在的插件。prefix
用于前缀路由_ext
用于文件扩展路由 。_base
设置为false
以从生成的URL中删除基本路径。 如果您的应用程序不在根目录中,这可以用于生成“蛋糕相对”的URL。_scheme
设置以在不同的方案(如webcal或ftp)上创建链接。 默认为当前方案。_host
设置要用于链接的主机。 默认为当前主机。_port
如果需要在非标准端口上创建链接,请设置端口。_full
如果为true
, FULL_BASE_URL常数将添加到生成的URL前。#
允许您设置URL哈希碎片。_ssl
设置为true
可将生成的URL转换为https或false
以强制使用http。_method
定义要使用的HTTP动词/方法。 在使用创建RESTful路由时很有用。_name
路由名称。 如果您设置了命名路由,您可以使用此键指定它。
将参数传递给Action
当使用Route Elements连接路由时,你可能想让routes元素传递参数。 pass
选项将所有路由元素也作为参数传递到控制器函数中:
// src / Controller / BlogsController.php
public function view ( $ articleId = null , $ slug = null )
{
//这里有一些代码...
}}
// routes.php
Router :: scope ( '/' , function ( $ routes ) {
$ routes - > connect (
'/ blog /:id-:slug' , // Eg / blog / 3-CakePHP_Rocks
[ 'controller' => 'Blogs' , 'action' => 'view' ],
[
//在路由模板中定义路由元素
//作为函数参数传递。 订单从这以来重要
//将简单地将“:id”映射到您的操作中的$ articleId
'pass' => [ 'id' , 'slug' ],
//定义一个'id'必须匹配的模式。
'id' => '[0-9] +'
]]
);
});
现在感谢反向路由功能,您可以传入如下的URL数组,CakePHP将知道如何形成在路由中定义的URL:
// view.ctp
// This will return a link to /blog/3-CakePHP_Rocks
echo $this->Html->link('CakePHP Rocks', [
'controller' => 'Blog',
'action' => 'view',
'id' => 3,
'slug' => 'CakePHP_Rocks'
]);
// You can also used numerically indexed parameters.
echo $this->Html->link('CakePHP Rocks', [
'controller' => 'Blog',
'action' => 'view',
3,
'CakePHP_Rocks'
]);
使用命名路径
有时你会发现输入一个路由的所有URL参数太详细,或者你想利用命名路由的性能改进。 当连接路由时,您可以指定_name
选项,此选项可用于反向路由,以标识要使用的路由:
// Connect a route with a name.
$routes->connect(
'/login',
['controller' => 'Users', 'action' => 'login'],
['_name' => 'login']
);
// Generate a URL using a named route.
$url = Router::url(['_name' => 'login']);
// Generate a URL using a named route,
// with some query string args.
$url = Router::url(['_name' => 'login', 'username' => 'jimmy']);
如果你的路由模板包含任何路由元素,如
:controller
你需要提供这些作为选项到Router::url()
。
▲ 注意: 整个应用程序中的路径名称必须是唯一的。 相同的_name不能使用两次,即使名称出现在不同的路由范围内。
在构建命名路由时,您可能希望遵守路由名称的一些约定。 CakePHP通过允许您在每个作用域中定义名称前缀,使构建路由名称变得更容易:
Router::scope('/api', ['_namePrefix' => 'api:'], function ($routes) {
// This route's name will be `api:ping`
$routes->connect('/ping', ['controller' => 'Pings'], ['_name' => 'ping']);
});
// Generate a URL for the ping route
Router::url(['_name' => 'api:ping']);
// Use namePrefix with plugin()
Router::plugin('Contacts', ['_namePrefix' => 'contacts:'], function ($routes) {
// Connect routes.
});
// Or with prefix()
Router::prefix('Admin', ['_namePrefix' => 'admin:'], function ($routes) {
// Connect routes.
});
您还可以在嵌套作用
_namePrefix
使用_namePrefix
选项,它的工作原理如下:
Router::plugin('Contacts', ['_namePrefix' => 'contacts:'], function ($routes) {
$routes->scope('/api', ['_namePrefix' => 'api:'], function ($routes) {
// This route's name will be `contacts:api:ping`
$routes->connect('/ping', ['controller' => 'Pings'], ['_name' => 'ping']);
});
});
// Generate a URL for the ping route
Router::url(['_name' => 'contacts:api:ping']);
在命名的作用域中连接的路由只有在路由也被命名时才添加名称。 无名路由不会有
_namePrefix
应用于它们。
前缀路由
static Cake\Routing\Router:: prefix ( $ name , $ callback )
许多应用程序需要一个管理部分,特权用户可以进行更改。 这通常通过特殊URL(如/admin/users/edit/5
。 在CakePHP中,可以使用prefix
作用域方法启用前缀路由:
use Cake\Routing\Route\DashedRoute;
Router::prefix('admin', function ($routes) {
// All routes here will be prefixed with `/admin`
// And have the prefix => admin route element added.
$routes->fallbacks(DashedRoute::class);
});
前缀被映射到应用程序的Controller
命名空间中的子Controller
空间。 通过将前缀作为单独的控制器,您可以创建更小和更简单的控制器。 前缀和非前缀控制器通用的行为可以使用继承, 组件或traits封装 。 使用我们的用户示例,访问URL/admin/users/edit/5
将调用src / Controller / Admin / UsersController.php传递5的edit()
方法作为第一个参数。 所使用的视图文件将是src / Template / Admin / Users / edit.ctp
您可以使用以下路由将URL / admin映射到页面控制器的index()
操作:
Router::prefix('admin', function ($routes) {
// Because you are in the admin scope,
// you do not need to include the /admin prefix
// or the admin route element.
$routes->connect('/', ['controller' => 'Pages', 'action' => 'index']);
});
创建前缀路由时,可以使用$options参数设置其他路由参数:
Router::prefix('admin', ['param' => 'value'], function ($routes) {
// Routes connected here are prefixed with '/admin' and
// have the 'param' routing key set.
$routes->connect('/:controller');
});
您还可以在插件作用域中定义前缀:
Router::plugin('DebugKit', function ($routes) {
$routes->prefix('admin', function ($routes) {
$routes->connect('/:controller');
});
});
以上将创建一个路由模板,如/manager/admin/:controller
。 连接的路由将prefix
route元素设置为manager/admin
。
当前前缀将从控制器方法通过$this->request->getParam('prefix')
当使用前缀路由时,设置前缀选项很重要。 以下是使用HTML帮助构建此链接的方法:
// Go into a prefixed route.
echo $this->Html->link(
'Manage articles',
['prefix' => 'manager', 'controller' => 'Articles', 'action' => 'add']
);
// Leave a prefix
echo $this->Html->link(
'View Post',
['prefix' => false, 'controller' => 'Articles', 'action' => 'view', 5]
);
▲ 注意: 在连接回退路由之前,应连接前缀路由。
插件路由
static Cake\Routing\Router:: plugin ( $ name , $ options = [] , $ callback )
应使用
plugin()
方法创建插件的路由。 此方法为插件的路由创建一个新的路由范围:
Router::plugin('DebugKit', function ($routes) {
// Routes connected here are prefixed with '/debug_kit' and
// have the plugin route element set to 'DebugKit'.
$routes->connect('/:controller');
});
创建插件作用域时,您可以自定义与
path
选项一起使用的路径元素:
Router::plugin('DebugKit', ['path' => '/debugger'], function ($routes) {
// Routes connected here are prefixed with '/debugger' and
// have the plugin route element set to 'DebugKit'.
$routes->connect('/:controller');
});
以上将创建一个看起来像/admin/debug_kit/:controller
。 它将设置prefix
和plugin
路由元素。
您可以通过将插件键添加到URL数组来创建指向插件的链接:
Router::prefix('admin', function ($routes) {
$routes->plugin('DebugKit', function ($routes) {
$routes->connect('/:controller');
});
});
相反,如果活动请求是一个插件请求,并且您想创建一个没有插件的链接,您可以执行以下操作:
echo $this->Html->link(
'New todo',
['plugin' => 'Todo', 'controller' => 'TodoItems', 'action' => 'create']
);
通过设置
plugin => null
你告诉路由器,你想创建一个不是插件的一部分的链接。
SEO友好路由
有些开发者更喜欢在网址中使用破折号,因为它被认为可以提供更好的搜索引擎排名。 DashedRoute
类可以在您的应用程序中使用,能够将插件,控制器和骆驼化动作名称路由到虚线URL。
例如,如果我们有一个ToDo
插件,一个TodoItems
控制器和一个showItems()
动作,可以通过以下路由器连接访问/to-do/todo-items/show-items
:
use Cake\Routing\Route\DashedRoute;
Router::plugin('ToDo', ['path' => 'to-do'], function ($routes) {
$routes->fallbacks(DashedRoute::class);
});
匹配特定的HTTP方法
路由可以使用_method
路由密钥匹配特定的HTTP方法:
Router::scope('/', function($routes) {
// This route only matches on POST requests.
$routes->connect(
'/reviews/start',
['controller' => 'Reviews', 'action' => 'start', '_method' => 'POST']
);
});
您可以使用数组匹配多个HTTP方法。 因为_method
参数是路由键,它参与URL解析和URL生成。
匹配特定主机名
路由可以使用_host
选项仅匹配特定主机。 您可以使用*.
通配符匹配任何子域:
Router::scope('/', function($routes) {
// This route only matches on http://images.example.com
$routes->connect(
'/images/default-logo.png',
['controller' => 'Images', 'action' => 'default'],
['_host' => 'images.example.com']
);
// This route only matches on http://*.example.com
$routes->connect(
'/images/old-log.png',
['controller' => 'Images', 'action' => 'oldLogo'],
['_host' => '*.example.com']
);
});
_host
选项也用于URL生成。 如果您的_host
选项指定了确切的域,则该域将包含在生成的URL中。 但是,如果您使用通配符,则需要在生成URL时提供_host
参数:
// If you have this route
$routes->connect(
'/images/old-log.png',
['controller' => 'Images', 'action' => 'oldLogo'],
['_host' => '*.example.com']
);
// You need this to generate a url
echo Router::url([
'controller' => 'Images',
'action' => 'oldLogo',
'_host' => 'images.example.com'
]);
路由文件扩展名
static Cake\Routing\Router:: extensions ( string | array | null $ extensions , $ merge = true )
要使用路由处理不同的文件扩展名,您可以将以下内容添加到路由文件中:
Router::scope('/', function ($routes) {
$routes->extensions(['json', 'xml']);
...
});
这将启用在
extensions()
调用之后连接的所有路由的命名扩展。 在其之前连接的任何路由将不会继承扩展。
▲ 注意: 设置扩展应该是你在范围内做的第一件事,因为扩展只会应用于在扩展设置后连接的路由。
通过使用扩展,您告诉路由器删除任何匹配的文件扩展名,然后解析剩余的。 如果您要创建/page/title-of-page.html等网址,则可以使用以下方式创建路线:
Router::scope('/page', function ($routes) {
$routes->extensions(['json', 'xml', 'html']);
$routes->connect(
'/:title',
['controller' => 'Pages', 'action' => 'view'],
[
'pass' => ['title']
]
);
});
然后创建映射回路由的链接只需使用:
$this->Html->link(
'Link title',
['controller' => 'Pages', 'action' => 'view', 'title' => 'super-article', '_ext' => 'html']
);
请求处理使用文件扩展名根据内容类型进行自动视图切换。
创建RESTful路由
路由器使您能够轻松地为控制器生成RESTful路由。 当您为应用程序创建API端点时,RESTful路由很有用。 如果我们想允许REST访问配方控制器,我们会这样做:
// In config/routes.php...
Router::scope('/', function ($routes) {
$routes->extensions(['json']);
$routes->resources('Recipes');
});
第一行设置了一些默认路由以方便REST访问,其中方法指定所需的结果格式(例如xml,json,rss)。 这些路由是HTTP请求方法敏感的。
HTTP format | URL.format | Controller action invoked |
---|---|---|
GET | /recipes.format | RecipesController::index() |
GET | /recipes/123.format | RecipesController::view(123) |
POST | /recipes.format | RecipesController::add() |
PUT | /recipes/123.format | RecipesController::edit(123) |
PATCH | /recipes/123.format | RecipesController::edit(123) |
DELETE | /recipes/123.format | RecipesController::delete(123) |
CakePHP的Router类使用了许多不同的指标来检测正在使用的HTTP方法。 这里他们是优先级:
- _method POST变量
- X_HTTP_METHOD_OVERRIDE
- REQUEST_METHOD标头
_method POST变量有助于将浏览器用作REST客户端(或任何其他可以执行POST的操作)。 只需将_method的值设置为要仿真的HTTP请求方法的名称。
创建嵌套的资源路由
一旦连接了作用域中的资源,您就可以连接子资源的路由。 子资源路由将以原始资源名称和id参数为前缀。 例如:
Router::scope('/api', function ($routes) {
$routes->resources('Articles', function ($routes) {
$routes->resources('Comments');
});
});
将为
articles
和comments
生成资源路由。 评论路线将如下所示:
/api/articles/:article_id/comments
/api/articles/:article_id/comments/:id
您可以通过以下
article_id
获取article_id
中的CommentsController
:
$this->request->getParam('article_id');
默认情况下,资源路由映射到包含作用域的相同前缀。 如果您有嵌套和非嵌套资源控制器,您可以使用前缀在每个上下文中使用不同的控制器:
Router::scope('/api', function ($routes) {
$routes->resources('Articles', function ($routes) {
$routes->resources('Comments', ['prefix' => 'articles']);
});
});
以上会将“注释”资源映射到
App\Controller\Articles\CommentsController
。 使用单独的控制器可以使您的控制器逻辑更简单。 以这种方式创建的前缀与前缀路由兼容。
▲ 注意: 虽然您可以根据需要尽可能深入地嵌套资源,但不建议将超过2个资源嵌套在一起。
限制创建的路由
默认情况下,CakePHP将为每个资源连接6个路由。 如果您只想连接特定的资源路由,您可以使用only
选项:
$routes->resources('Articles', [
'only' => ['index', 'view']
]);
将创建只读资源路由。 路由名称为
create
, update
, view
, index
和delete
。
更改控制器使用的操作
您可能需要更改在连接路由时使用的控制器操作名称。 例如,如果您的edit()
操作被调用put()
您可以使用actions
键重命名使用的actions
:
$routes->resources('Articles', [
'actions' => ['update' => 'put', 'create' => 'create']
]);
上面将使用
put()
作为edit()
动作,而create()
而不是add()
。
映射其他资源路由
您可以使用map
选项映射其他资源方法:
$routes->resources('Articles', [
'map' => [
'deleteAll' => [
'action' => 'deleteAll',
'method' => 'DELETE'
]
]
]);
// This would connect /articles/deleteAll
除了默认路由,这也将连接/ articles / delete_all的路由 。 默认情况下,路径段将匹配键名称。 您可以使用资源定义中的“path”键来自定义路径名:
$routes->resources('Articles', [
'map' => [
'updateAll' => [
'action' => 'updateAll',
'method' => 'DELETE',
'path' => '/update_many'
],
]
]);
// This would connect /articles/update_many
如果您定义“only”和“map”,请确保您映射的方法也在“仅”列表中。
资源路由的自定义路由类
您可以在resources()
的$options
数组中提供connectOptions
键,以提供connect()
使用的自定义设置:
Router::scope('/', function ($routes) {
$routes->resources('Books', [
'connectOptions' => [
'routeClass' => 'ApiRoute',
]
];
});
资源路由的URL变形
默认情况下,多字控制器的URL片断是控制器名称的下划线形式。 例如, BlogPostsController
的URL片段将是/ blog_posts 。
你可以通过改变选项指定一个替代的转折型:
Router::scope('/', function ($routes) {
$routes->resources('BlogPosts', [
'inflect' => 'dasherize' // Will use ``Inflector::dasherize()``
];
});
上面将生成URL样式如: / blog-posts / * 。
▲ 注意: 从CakePHP 3.1起,官方应用程序框架使用DashedRoute作为其默认路由类。 'inflect' => 'dasherize'在连接资源路由时使用'inflect' => 'dasherize'选项来确保URL一致性。
传递参数
传递的参数是在发出请求时使用的附加参数或路径段。 它们通常用于将参数传递给控制器方法。
http://localhost/calendars/view/recent/mark
在上面的例子中, recent
和mark
都传递给CalendarsController::view()
。 传递的参数以三种方式提供给您的控制器。 首先作为调用的动作方法的参数,其次它们在$this->request->getParam('pass')
可用作数字索引数组。 当使用自定义路由时,您可以强制特定参数进入传递的参数。
如果你访问前面提到的URL,并且你有一个控制器操作,看起来像:
class CalendarsController extends AppController
{
public function view($arg1, $arg2)
{
debug(func_get_args());
}
}
您将获得以下输出:
Array
(
[0] => recent
[1] => mark
)
这些相同的数据也可以在你的控制器,视图和助手的
$this->request->getParam('pass')
。 传递数组中的值将根据它们在调用的URL中显示的顺序进行数字索引:
debug($this->request->getParam('pass'));
以上任一将输出:
Array
(
[0] => recent
[1] => mark
)
在生成URL时,使用路由数组 ,将传递的参数作为值添加到数组中,而不带字符串键:
['controller' => 'Articles', 'action' => 'view', 5]
由于
5
有一个数字键,它被视为传递的参数。
生成网址
-
static
Cake\Routing\Router::
url
( $ url = null , $ full = false )
生成URL或反向路由是CakePHP中的一个功能,用于允许您更改URL结构,而无需修改所有代码。 通过使用路由数组定义URL,您可以稍后配置路由,生成的URL将自动更新。
如果您使用以下字符串创建网址:
$this->Html->link('View', '/articles/view/' . $id);
再后来决定
/articles
应该被称为'文章',而不是,你必须通过你的整个应用程序的URL重命名。不过,如果你定义你的链接,如:
$this->Html->link(
'View',
['controller' => 'Articles', 'action' => 'view', $id]
);
然后,当你决定改变你的网址,你可以通过定义路由这样做。这将同时更改传入URL映射,以及生成的URL。
当使用数组的URL,可以使用特殊键同时定义查询字符串参数和文件片段:
Router::url([
'controller' => 'Articles',
'action' => 'index',
'?' => ['page' => 1],
'#' => 'top'
]);
// Will generate a URL like.
/articles/index?page=1#top
路由器也将转换任何未知参数在路由数组查询字符串参数。该?
供使用旧版本的CakePHP的向后兼容性。
生成URL时,也可以使用任何特殊的路由元素:
_ext
用于路由文件扩展路由。_base
设置为false
从生成的URL删除的基本路径。如果你的应用是不是在根目录下,这可以用来生成是“蛋糕亲属”的网址。_scheme
将创建不同的方式,如链接webcal
或ftp
。默认为当前方案。_host
设置为用于链接的主机。默认为当前主机。_port
如果你需要创建非标准端口的链接设置端口。_full
如果true
该FULL_BASE_URL
常数将被追加到生成的URL。_ssl
设置为true
将生成的URL转换为HTTPS或false
强制HTTP。_name
路线名称。如果您已经安装命名路由,您可以使用此键来指定。
重定向路由
重定向路由允许您发出HTTP状态30倍重定向传入的路线,并在不同的URL指向他们。当你想通知资源已经被移动客户端应用程序,你不希望暴露两个网址为相同的内容,这非常有用。
仿佛找到匹配的,他们执行实际的头重定向路由重定向从正常的途径不同。重定向,则可能对您的应用程序或外部位置中的一个目的地:
Router::scope('/', function ($routes) {
$routes->redirect(
'/home/*',
['controller' => 'Articles', 'action' => 'view'],
['persist' => true]
// Or ['persist'=>['id']] for default routing where the
// view action expects $id as an argument.
);
})
重定向/home/*
到/articles/view
并传递参数/articles/view
。使用数组作为重定向目的地,您可以使用其他途径来定义URL字符串应该被重定向到。您可以重定向到使用字符串的URL作为目标外部位置:
Router::scope('/', function ($routes) {
$routes->redirect('/articles/*', 'http://google.com', ['status' => 302]);
});
这将重定向
/articles/*
到http://google.com
与302 HTTP状态。
自定义路由类
自定义路由类,可以扩展和更改路由如何解析个人请求和处理反向路由。路线班有几个约定:
- 路线类可望在可以找到
Routing\\Route
你的应用程序或插件的命名空间。 - 路线类应该扩展
Cake\Routing\Route
。 - 路线类应实现的一个或两个
match()
和/或parse()
。
该parse()
方法用于分析传入的URL。应产生的,可以拆分成一个控制器及动作请求参数的阵列。返回false
从这个方法来指示匹配失败。
该match()
方法用于匹配的URL参数数组,并创建一个字符串的URL。如果URL参数不匹配的路径false
应返回。
通过使路由时,可以使用自定义的路由类routeClass
选项:
$routes->connect(
'/:slug',
['controller' => 'Articles', 'action' => 'view'],
['routeClass' => 'SlugRoute']
);
这条路线将创建一个实例SlugRoute
,让你实现自定义的参数处理。您可以使用使用标准插件路线类插件的语法。
默认路由类
-
静
Cake\Routing\Router::
defaultRouteClass
(
$ routeClass = NULL
)
如果你要使用的所有路由的备用路由类除了默认的Route
,你可以通过调用这么做Router::defaultRouteClass()
设置任何路由前,避免指定routeClass
每个路由选项。例如使用:
use Cake\Routing\Route\InflectedRoute;
Router::defaultRouteClass(InflectedRoute::class);
会导致在此之后连接到使用的所有路由
InflectedRoute
的路由类。调用该方法不带参数将返回当前的默认路由类。
回退法
Cake\Routing\Router::
fallbacks
(
$ routeClass = NULL
)
该回退的方法是定义默认路由一个简单快捷。该方法使用传递的路由类所定义的规则,如果没有类提供了由返回的类Router::defaultRouteClass()
使用。
调用像这样回退:
use Cake\Routing\Route\DashedRoute;
$routes->fallbacks(DashedRoute::class);
相当于下列显式调用:
use Cake\Routing\Route\DashedRoute;
$routes->connect('/:controller', ['action' => 'index'], ['routeClass' => DashedRoute:class]);
$routes->connect('/:controller/:action/*', [], ['routeClass' => DashedRoute:class]);
▲ 注意: 使用默认路由类(Route)与回退,或任何与路线:plugin和/或:controller路线的元素将导致不一致的URL的情况下。
创建持久URL参数
您可以使用URL过滤功能挂钩到URL生成过程。过滤函数被调用之前的网址会根据路由匹配,这可以让你的路由之前准备的URL。
回调的过滤功能应该期望以下参数:
$params
该网址参数正在处理中。$request
当前的请求。
该URL过滤功能应始终返回PARAMS即使不变。
URL过滤器,可以实现像执着参数功能:
Router::addUrlFilter(function ($params, $request) {
if ($request->getParam('lang') && !isset($params['lang'])) {
$params['lang'] = $request->getParam('lang');
}
return $params;
});
过滤功能在它们所连接的顺序应用。
另一种使用情况正在改变运行时某条路(例如插件路线):
Router::addUrlFilter(function ($params, $request) {
if (empty($params['plugin']) || $params['plugin'] !== 'MyPlugin' || empty($params['controller'])) {
return $params;
}
if ($params['controller'] === 'Languages' && $params['action'] === 'view') {
$params['controller'] = 'Locations';
$params['action'] = 'index';
$params['language'] = $params[0];
unset($params[0]);
}
return $params;
});
这将改变以下路线:
Router::url(['plugin' => 'MyPlugin', 'controller' => 'Languages', 'action' => 'view', 'es']);
进入:
Router::url(['plugin' => 'MyPlugin', 'controller' => 'Locations', 'action' => 'index', 'language' => 'es']);
在处理的URL命名参数
虽然命名参数是在CakePHP的3.0删除,应用程序可能已发布的URL包含它们。您可以继续接受包含命名参数的URL。
在你的控制器的beforeFilter()
方法,你可以打电话parseNamedParams()
来提取传递的参数的命名参数:
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
Router::parseNamedParams($this->request);
}
这将填充
$this->request->getParam('named')
在传递的参数中找到的任何命名参数。这被解读为一个命名参数的任何传递参数,它将传递的参数列表中删除。