【问题标题】:Laravel 5.4: how to pass model object to controller via middleware?Laravel 5.4:如何通过中间件将模型对象传递给控制器​​?
【发布时间】:2018-01-05 22:30:44
【问题描述】:

我正在 Laravel 5.4 中创建一个应用程序,其中我有一个中间件 ValidateBooking,然后是一个控制器,它使用类似 /booking/6/car 的 URL 调用,其中列出了分配给该预订的所有汽车。

ValidateBooking 中间件中,我使用Booking::find(6) Eloquent 函数验证上述URL 中的预订ID 6。但我想要的是,如果 Booking 存在然后将该对象传递给控制器​​,所以我不会在控制器中再次获取它。我不想为同一件事查询数据库两次。

我尝试了几种方法将模型对象与中间件中的$request 合并,但无法在控制器中正确访问它。

我的中间件代码是:

<?php

namespace App\Http\Middleware\Booking;

use Closure;
use App\Booking\Booking;

class ValidateBooking
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $booking = Booking::find($request->booking_id);
        if (!$booking) {
            return redirect(route('booking.show', $request->booking_id));
        }
        $request->attributes->add(['bookingInstance' => $booking]);
        return $next($request);
    }
}

然后像这样在 Controller 中获取它:

$request-&gt;get('bookingInstance')

如果我传递任何字符串值或其他东西,它会起作用,但不是对象?请告知什么是最好的方法。

【问题讨论】:

    标签: laravel laravel-5 laravel-middleware


    【解决方案1】:

    您只需对请求对象使用merge() 函数即可。

    public function handle($request, Closure $next)
    {
        $booking = Booking::find($request->booking_id);
        if (!$booking) {
            return redirect(route('booking.show', $request->booking_id));
        }
        $request->merge(['bookingInstance' => $booking]);
        return $next($request);
    }
    

    除了使用被证明有效的$request-&gt;merge()之外,只需将模型对象添加到请求中,以下内容还可以帮助您访问控制器中的模型:

    $request->booking = $booking;
    

    唯一需要注意的就是确保永远不会有一个名为 booking 的参数,以免覆盖它。

    【讨论】:

    • 确实,使用合并工作。 @Prashant 你应该考虑这个。
    • @Chris 我试过这个,但问题是我试图在控制器类的构造函数中访问请求,在我的例子中,控制器的构造函数在中间件 handle() 之前被调用,如何我应该解决这个问题吗?
    • 您能否将控制器的代码添加到问题中。为什么在构造函数中需要它?在中间件运行后,您不能等待并在被调用以处理请求的函数中执行操作吗?
    【解决方案2】:

    我想你想看的是Explicit Route Model bindings

    如果您向RouteServiceProvider 添加显式绑定,则可以在中间件和控制器中访问该参数。

    // app/Providers/RouteServiceProvider.php
    
    public function boot()
    {
        parent::boot();
        Route::model('booking', \App\Booking\Booking::class);
    }
    
    
    // routes/web.php
    
    Route::get('/booking/{booking}/car', 'BookingController@car')->middleware('booking.validate');
    
    
    // app/Http/Middleware/ValidateBooking.php
    
    public function handle($request, Closure $next)
    {
        $booking = $request->booking;
    
        // ...
    
        return $next($request);
    }
    
    
    // app/Http/Controllers/BookingController.php
    
    public function car(Request $request)
    {
        dd($request->booking);
    }
    

    【讨论】:

    • 谢谢,看起来不错。相反,如果中间件我只是将模型与路由 qnd 绑定,如果它没有找到任何预订,那么我可以处理 404 将其重定向到我需要的地方,这会起作用吗?或者我需要一个中间件。我只是想验证是否存在预订,否则会出错。请提出您的想法?
    • 我通常在我的控制器中使用findOrFail($id)。我不确定如果 Laravel 找不到路由绑定会发生什么。它可能会为您抛出 404。测试一下。
    【解决方案3】:

    这是你可以做的。我曾经遇到过这个问题。

     public function handle($request, Closure $next)
    {
        $booking = Booking::find($request->booking_id);
        if (!$booking) {
            return redirect(route('booking.show', $request->booking_id));
        }
        sesion()->put('bookingInstance', $booking);
        return $next($request);
    }
    

    这很简单。

    【讨论】:

      猜你喜欢
      • 2017-12-27
      • 2016-10-18
      • 1970-01-01
      • 2016-04-08
      • 2016-05-15
      • 1970-01-01
      • 1970-01-01
      • 2018-12-22
      • 2019-07-16
      相关资源
      最近更新 更多