如何根据路由参数将模型实例传递给所有控制器和视图

How to pass a model instance to all controllers and views based on a route parameter

我正在开发一个 Laravel 控制面板项目,我们应该能够从一个站点切换到另一个站点,并根据路由中传递的 ID 获取站点的详细信息。

这本身很容易做到,但由于我将有多个控制器使用此技术,这意味着对于每个控制器和每个控制器实例,我将收集站点实例,并且由于多次重复。

这是我的资料: 路线:

Route::get(
    'cp/site/{website}/modules/feeds',
    'App\Http\Controllers\Modules_sites\Feeds\FeedController@index'
)->name('module_site.feeds.index'); 

型号:

class Website extends Model
{
    use HasFactory;
    protected $primaryKey ='site_id';
}

数据库很简单,有一个id(site_id)和name

控制器:

public function index(Website $website)
{
    dd($website -> name);  
}

上面的工作正常,但我将以跨多个控制器的数十种方法做同样的事情结束,如果需要更改怎么办。

我查看了使用 AppServiceProvider 创建 Website 实例的 ID,然后将其传递给控制器​​和视图,但我无法执行此操作,因为未定义路由在这个阶段,我似乎只能将其传递给视图。

本质上,我希望创建类似于 auth()->user() 方法的方法,该方法可从控制器和路由中获得,而无需将其传递给每个控制器。

这可能吗?

因为你的主键不是 id 所以它不会自动工作你需要告诉 laravel 按列名搜索

代码将是

Route::get('cp/site/{website:site_id}/modules/feeds', 'App\Http\Controllers\Modules_sites\Feeds\FeedController@index')->name('module_site.feeds.index');

你需要使用{website:site_id} 参考 link https://laravel.com/docs/8.x/routing#customizing-the-default-key-name

也许你可以使用中间件来设置这个值?像这样把它放在全局会话中:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class CheckWebsite
{
    public function handle(Request $request, Closure $next): mixed
    {
        $request->session()->put("website", $request->route("website"));
        return $next($request);
    }
}

或者基于每个控制器:

<?php

namespace App\Http\Controllers\Modules_sites\Feeds;

use App\Http\Controllers\Controller;
use Closure;
use Illuminate\Http\Request;

class FeedController extends Controller
{
    public function __construct()
    {
        $this->middleware(function (Request $request, Closure $next) {
            $this->website = $request->route("website");
            return $next($request);
        });
    }

    public function index()
    {
        dd($this->website->name);
    }
}

另外值得一提的是,路由不再像 Laravel 8 中那样定义。它应该是这样的:

Route::get(
    'cp/site/{website}/modules/feeds',
    [FeedController::class, 'index']
)->name('module_site.feeds.index');

通过适当导入控制器 class。