使用CakePHP v3.3.16
我想写一个后备路由,如果URL没有连接到任何操作,那么它应该转到该后备。
为此类
创建了SEO友好网址的路由 $routes->connect(
':slug',
['prefix'=>'website','controller' => 'Brands', 'action' => 'index'],
['routeClass' => 'DashedRoute']
);
$routes->connect(
':slug/*',
['prefix'=>'website','controller' => 'Products', 'action' => 'index'],
['routeClass' => 'DashedRoute']
);
但它也包含了所有控制器操作,因此如果我尝试拨打控制器 ex:cart / index ,它会转到网站/品牌/索引/索引
如果我必须删除它,我必须创建一个像这样的路径
$routes->connect('/cart',['controller' => 'Cart'], ['routeClass' => 'DashedRoute']);
依此类推其他控制器进行访问。
实施例: 我有一个控制器 CartController 操作 addCart
案例1
如果我访问网址my_project/cart/addCart/
它应该转到购物车控制器操作
案例2
如果我访问网址my_project/abc/xyz/
并且没有名为abc的控制器,那么它应该转到 BrandsController 操作索引
My Current routes.php看起来像这样
Router::defaultRouteClass(DashedRoute::class);
Router::scope('/', function (RouteBuilder $routes) {
$routes->connect('/', ['prefix'=>'website','controller' => 'Home', 'action' => 'index']);
$routes->connect('/trending-brands', ['prefix'=>'website','controller' => 'Brands', 'action' => 'trending']);
$routes->connect('/users/:action/*',['prefix'=>'website','controller' => 'Users'], ['routeClass' => 'DashedRoute']);
$routes->connect('/cart',['prefix'=>'website','controller' => 'Cart'], ['routeClass' => 'DashedRoute']);
$routes->connect('/cart/:action/*',['prefix'=>'website','controller' => 'Cart'], ['routeClass' => 'DashedRoute']);
$routes->connect(
':slug',
['prefix'=>'website','controller' => 'Brands', 'action' => 'index'],
['routeClass' => 'DashedRoute']
);
$routes->connect(
':slug/*',
['prefix'=>'website','controller' => 'Products', 'action' => 'index'],
['routeClass' => 'DashedRoute']
);
$routes->connect(':controller', ['prefix'=>'website'], ['routeClass' => 'DashedRoute']);
$routes->connect(':controller/:action/*', ['prefix'=>'website'], ['routeClass' => 'DashedRoute']);
$routes->fallbacks(DashedRoute::class);
});
Router::prefix('website', function (RouteBuilder $routes) {
$routes->fallbacks(DashedRoute::class);
});
Plugin::routes();
答案 0 :(得分:3)
您的修改完全无效我的第一个答案,所以我决定发布另一个答案。
路由器无法实现您想要实现的目标,因为路由器无法判断特定路由是否存在控制器/操作。这是因为路由器只使用url模板并委托在请求堆栈中加载控制器的任务。
您可以使用Middleware来模拟此功能
检查请求属性params
是否已设置,然后根据需要对其进行验证,如果目标控制器不存在,则将其更改为回退控制器。
只需确保将RoutingMiddleware
执行放在中间件之前,否则您将无法检查params,因为路由不会被解析。
中间件实现了一种方法__invoke()
。
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Cake\Http\ControllerFactory;
use Cake\Routing\Exception\MissingControllerException;
class _404Middleware {
public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
{
//$params = (array)$request->getAttribute('params', []);
try {
$factory = new ControllerFactory();
$controller = $factory->create($request, $respond);
}
catch (\Cake\Routing\Exception\MissingControllerException $e) {
// here you fallback to your controllers/action or issue app level redirect
$request = $request->withAttribute('params',['controller' =>'brands','action' => 'index']);
}
return $next($request, $response);
}
}
然后在App\Application
中附上attaching middlewares
$middlewareStack->add(new _404Middleware());
请重新清理代码,因为我没有在真正的环境下进行测试。
经过深思熟虑:如果您希望为所有未找到的资源创建错误页面,那么您不需要所有这些,而只需在Template/Error/error404.ctp
中自定义错误模板。
答案 1 :(得分:1)
如果我必须删除它,我必须创建一个这样的路径/依此类推到另一个控制器来访问。
不需要在模式中指定每个控制器/名称,而是可以先创建所有指定路由,然后在它们下面放置以下路由以捕获所有不匹配的路由。
$routes->connect(':/prefix/:controller/:action/*', [], ['routeClass' => 'DashedRoute']);
也许另一个没有前缀
$routes->connect('/:controller/:action/*', [], ['routeClass' => 'DashedRoute']);
既然你提到你正在使用3.3.*
蛋糕版本,你的路线可以写成路线范围的推荐
Router::prefix('website', function ($routes) {
// All routes here will be prefixed with `/prefix`
// And have the prefix => website route element added.
$routes->fallbacks(DashedRoute::class);
$routes->connect(
'/:slug',
['controller' => 'Brands', 'action' => 'index']
);
$routes->connect(
':slug/*',
['controller' => 'Products', 'action' => 'index']
});