在其他框架中,存在请求转发的概念,即请求可以在内部重定向到应用程序内的另一个控制器动作,而无需使用显式重定向来回复用户。
以电子商务为例,如果产品的SEO友好URL为/red-shoes.html
,则对该URL的请求将在内部转发至/catalog/product/id/1234
。用户将收到200响应码,并且产品ID为1234的产品页面将显示在原始URL /red-shoes.html
上。我正在尝试避免的行为是向/catalog/product/view/id/1234
发出301重定向,并丢失了友好的URL。
如何在Laravel(5.7)中实现?我可以引入一个中间件来拦截请求,但是在中间件中,我只能在应用程序内重定向。 redirect()
向用户发送302,这是我不想要的。
namespace App\Http\Middleware;
use Closure;
use App\Rewrite;
class ProductForward
{
public function handle($request, Closure $next)
{
// make a lookup to see if URI in request matches a known product
$productId = Product::lookupRequest($request);
if ($productId) { // if matches, forward to product controller
return redirect()->route('catalog_product', ['id' => $productId]); // not desired
}
// if no match is found, continue on with the request
return $next($request);
}
}
作为后续措施,如果没有路由匹配,是否可以在路由完成后执行此查找?
例如,假设存在路径/login
来呈现登录页面。如果用户转到/login
,则无需为此请求查找产品友好的URL,只需呈现登录页面即可。但是,如果用户访问/blue-shoe.html
,而这不是Laravel中的预定义路线,请执行产品查找并在之后应用程序路由,但在之前转发404呈现。
答案 0 :(得分:0)
SEO友好的网址是否可以位于products/red-shoes
之类的部分?
然后,您可以使用诸如Route::get('products/{seoName}');
之类的参数创建一条路由,该路由将导致与用于处理诸如/catalog/product/view/id/1234
之类的请求的控制器相同。在这里您可以解决并发现使用产品的ID或seo-name已达到控制器的操作,并显示匹配的产品。
基本上,您可以有两条路由products/red-shoes
和/catalog/product/view/id/1234
来显示同一页面,而无需重定向。
控制器操作
此外,您可以直接从中间件执行控制器方法。
代替呼叫
return redirect()->route('catalog_product', ['id' => $productId]);
您可能会运行
return app('App\Http\Controllers\ProductController')->show($productId);
然后,您将获得没有重定向的产品页面内容。
后备路线
为防止在每个请求上运行中间件,您可以使用备用路由。
Route::fallback(function () {
//
});
仅当请求与任何已注册的路由都不匹配时,才会执行回退路由。您可以在此处搜索产品,如果没有,则返回404响应。
所以您会得到这样的东西:
Route::fallback(function ()
{
// make a lookup to see if URI in request matches a known product
$productId = Product::lookupRequest(request());
if ($productId) { // if matches, forward to product controller
return app('App\Http\Controllers\ProductController')->show($productId);
}
abort(404);
}
回退路线应在文件中最后注册。