通过Laravel中的中间件转发请求

时间:2019-01-28 17:19:39

标签: php laravel

在其他框架中,存在请求转发的概念,即请求可以在内部重定向到应用程序内的另一个控制器动作,而无需使用显式重定向来回复用户。

以电子商务为例,如果产品的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呈现。

1 个答案:

答案 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);
}

回退路线应在文件中最后注册。

更多信息https://laravel.com/docs/5.7/routing#fallback-routes