CakePHP 3 使资源路由在有参数和无参数的情况下工作
CakePHP 3 make resource routes work with and without parameters
我的路由文件中有一些代码:
Router::scope('/v1', function (RouteBuilder $routes) {
$routes->resources( 'Files');
});
然后是一个具有删除功能的 FilesController,例如:
public function delete($id){
echo "here"; exit();
}
当我这样做时:
DELETE http://192.168.1.197/v1/files/1
响应是 here
,但是,如果我这样做:
DELETE http://192.168.1.197/v1/files
响应是缺少 V1Controller。
我希望 CakePHP 转身说 "oops, you have passed the wrong number of required parameters"。
这里似乎发生了一些非常奇怪的事情,我不太确定是什么。如何让两者做同样的事情并指向控制器?
当启用调试模式时,CakePHP 对异常的操作非常不同。当调试为 true
时,所有异常都使用调试信息、堆栈跟踪和开发人员友好消息呈现。
当调试模式为 false
时,异常呈现为标准 HTTP 响应类型。带有 400 和 500 错误代码的句柄。
当路由器找不到匹配的路由时,不涉及控制器。 HTTP 请求永远不会超过调度阶段。是dispatcher抛出了400类型的异常。
在您给定的示例中,框架抛出一个 MissingControllerException
,HTTP 代码为 404
。
400 个错误代码通过 ErrorController
呈现。 CakePHP 带有一个默认的错误控制器,但是如果您使用 composer 模板生成一个新的应用程序,那么您应该在应用程序的控制器持有者中有一个默认的 ErrorController
。
在您的模板中应该有一个 src/Template/Error/error400.ctp
文件显示 400 代码的响应。请记住,启用调试模式时不会使用此模板。
您可以修改此模板以查找 "closely" 匹配路线,并将它们作为建议提供给用户,作为错误消息中的反馈。
您可以像这样轻松地迭代所有已配置的路由:
foreach (Router::routes() as $route) {
$name = isset($route->options['_name']) ? $route->options['_name'] : $route->getName();
$output[] = [$name, $route->template, json_encode($route->defaults)];
}
以上摘自cakephp/src/Shell/RoutesShell.php:
因为这在技术上是一个 404 错误。没有匹配的路线,您可以尝试找到 "close" 匹配的路线。这里的问题是您面临与路由器相同的路由匹配挑战 class.
路由器class使用动态路由技术,该技术采用URL参数的一部分并将它们填充为控制器名称、操作名称和用户定义的参数。
这可以显着改变,具体取决于您使用的默认路由器类型class。
例如,您可能正在使用执行以下操作的 DashedRoute
路由 class:
/**
* This route class will transparently inflect the controller, action and plugin
* routing parameters, so that requesting `/my-plugin/my-controller/my-action`
* is parsed as `['plugin' => 'MyPlugin', 'controller' => 'MyController', 'action' => 'myAction']`
*/
class DashedRoute extends Route
您可能会使用 InflectedRoute
路由 class,它执行以下操作:
/**
* This route class will transparently inflect the controller and plugin routing
* parameters, so that requesting `/my_controller` is parsed as `['controller' => 'MyController']`
*/
class InflectedRoute extends Route
因为在某些情况下路由可能会使用动态路由。无法知道 URL 段是控制器、动作还是命名参数。
更复杂的是,您还使用了名为 /v1
的范围段,预测预期路线变得更具挑战性。
您可以创建自定义路由来捕获这些边缘情况并呈现信息性错误消息,或者您可以尝试向 error400.ctp
添加逻辑以显示信息性更强的错误消息。
还有最后一个选项。 CakePHP 允许您编写自己的自定义路由 classes,and/or 使用您自己的调度程序修改中间件。
我完全用另一种方法解决了这个问题,只是停止使用 CakePHP 中的资源路由;我将代码更改为:
$routes->get('/files/*', ['controller' => 'Files', 'action' => 'view'], 'files:get');
$routes->post('/files', ['controller' => 'Files', 'action' => 'add'], 'files:post');
$routes->put('/files/*', ['controller' => 'Files', 'action' => 'edit'], 'files:put');
$routes->patch('/files/*', ['controller' => 'Files', 'action' => 'view'], 'files:patch');
$routes->delete('/files/*', ['controller' => 'Files', 'action' => 'delete'], 'files:delete');
它完全按照我在问题中想要的方式工作...
我的路由文件中有一些代码:
Router::scope('/v1', function (RouteBuilder $routes) {
$routes->resources( 'Files');
});
然后是一个具有删除功能的 FilesController,例如:
public function delete($id){
echo "here"; exit();
}
当我这样做时:
DELETE http://192.168.1.197/v1/files/1
响应是 here
,但是,如果我这样做:
DELETE http://192.168.1.197/v1/files
响应是缺少 V1Controller。
我希望 CakePHP 转身说 "oops, you have passed the wrong number of required parameters"。
这里似乎发生了一些非常奇怪的事情,我不太确定是什么。如何让两者做同样的事情并指向控制器?
当启用调试模式时,CakePHP 对异常的操作非常不同。当调试为 true
时,所有异常都使用调试信息、堆栈跟踪和开发人员友好消息呈现。
当调试模式为 false
时,异常呈现为标准 HTTP 响应类型。带有 400 和 500 错误代码的句柄。
当路由器找不到匹配的路由时,不涉及控制器。 HTTP 请求永远不会超过调度阶段。是dispatcher抛出了400类型的异常。
在您给定的示例中,框架抛出一个 MissingControllerException
,HTTP 代码为 404
。
400 个错误代码通过 ErrorController
呈现。 CakePHP 带有一个默认的错误控制器,但是如果您使用 composer 模板生成一个新的应用程序,那么您应该在应用程序的控制器持有者中有一个默认的 ErrorController
。
在您的模板中应该有一个 src/Template/Error/error400.ctp
文件显示 400 代码的响应。请记住,启用调试模式时不会使用此模板。
您可以修改此模板以查找 "closely" 匹配路线,并将它们作为建议提供给用户,作为错误消息中的反馈。
您可以像这样轻松地迭代所有已配置的路由:
foreach (Router::routes() as $route) {
$name = isset($route->options['_name']) ? $route->options['_name'] : $route->getName();
$output[] = [$name, $route->template, json_encode($route->defaults)];
}
以上摘自cakephp/src/Shell/RoutesShell.php:
因为这在技术上是一个 404 错误。没有匹配的路线,您可以尝试找到 "close" 匹配的路线。这里的问题是您面临与路由器相同的路由匹配挑战 class.
路由器class使用动态路由技术,该技术采用URL参数的一部分并将它们填充为控制器名称、操作名称和用户定义的参数。
这可以显着改变,具体取决于您使用的默认路由器类型class。
例如,您可能正在使用执行以下操作的 DashedRoute
路由 class:
/**
* This route class will transparently inflect the controller, action and plugin
* routing parameters, so that requesting `/my-plugin/my-controller/my-action`
* is parsed as `['plugin' => 'MyPlugin', 'controller' => 'MyController', 'action' => 'myAction']`
*/
class DashedRoute extends Route
您可能会使用 InflectedRoute
路由 class,它执行以下操作:
/**
* This route class will transparently inflect the controller and plugin routing
* parameters, so that requesting `/my_controller` is parsed as `['controller' => 'MyController']`
*/
class InflectedRoute extends Route
因为在某些情况下路由可能会使用动态路由。无法知道 URL 段是控制器、动作还是命名参数。
更复杂的是,您还使用了名为 /v1
的范围段,预测预期路线变得更具挑战性。
您可以创建自定义路由来捕获这些边缘情况并呈现信息性错误消息,或者您可以尝试向 error400.ctp
添加逻辑以显示信息性更强的错误消息。
还有最后一个选项。 CakePHP 允许您编写自己的自定义路由 classes,and/or 使用您自己的调度程序修改中间件。
我完全用另一种方法解决了这个问题,只是停止使用 CakePHP 中的资源路由;我将代码更改为:
$routes->get('/files/*', ['controller' => 'Files', 'action' => 'view'], 'files:get');
$routes->post('/files', ['controller' => 'Files', 'action' => 'add'], 'files:post');
$routes->put('/files/*', ['controller' => 'Files', 'action' => 'edit'], 'files:put');
$routes->patch('/files/*', ['controller' => 'Files', 'action' => 'view'], 'files:patch');
$routes->delete('/files/*', ['controller' => 'Files', 'action' => 'delete'], 'files:delete');
它完全按照我在问题中想要的方式工作...