【问题标题】:Laravel model user custom binding "/users/me/xxx"Laravel 模型用户自定义绑定“/users/me/xxx”
【发布时间】:2022-01-23 07:25:13
【问题描述】:

我有类似用户绑定的路由

Route::get('users/{user}/posts', [PostController::class, 'index']);
Route::get('users/{user}/comments', [CommentController::class, 'index']);

所以我可以使用/users/1/posts/users/5/posts 等,并且由于模型绑定,它在控制器中自动可用

public function index(User $user)
{
    dd($user);
}

但是对于当前登录的用户,我希望也可以使用/me/ 而不是 ID,例如 /users/me/posts

有没有一种方法可以在不定义单独的控制器方法的情况下手动查找用户,并且不复制所有路由?那么是否可以全局“扩展”默认 Laravel 模型绑定?

【问题讨论】:

  • 您可以使用自己的查找逻辑进行显式绑定

标签: php laravel laravel-routing


【解决方案1】:

我相信使用像这样的固定路由参数是最可持续的解决方案,尤其是在共享代码库的情况下。它会涉及一些重复的代码,但会立即明确哪些路线可用。并且可以预定义分组回调,避免重复路由定义。

$routeGroup = function ($r) {
    $r->get('posts', [PostController::class, 'index']);
    $r->get('comments', [CommentController::class, 'index']);
};

Route::prefix('users/{user}')->group($routeGroup);
Route::prefix('users/me')->group($routeGroup);

然后在你的控制器方法中使参数可选。

public function index(User $user = null)
{
    $user = $user ?? Auth::user();
    dd($user);
}

另一种可能性是覆盖模型上的resolveRouteBinding 方法。如果您使用这种方法(或 Patricus 的解决方案),我建议您将 cmets 留在路由文件中,解释您所做的事情。

class User extends Model {
    public function resolveRouteBinding($value, $field = null): ?self
    {
        return $value === 'me'
            ? Auth::user()
            : parent::resolveRouteBinding($value, $field);
    }
}

【讨论】:

  • 用户说“没有声明另一条路线”,但我同意 100% 你的解决方案是最好的解决方案,它只是另一条路线,仅此而已......
  • 谢谢。两种解决方案都很好,但我要使用 resolveRouteBinding()。 @patricus 解决方案也解决了我的问题,但更清楚的是在用户模型中定义这个而不是 boot()。所以 resolveRouteBinding() 正是我想要的。
【解决方案2】:

当然,您只需要使用explicit route model binding 而不是默认的隐式绑定。无需更改您的路线或控制器。

在您的RouteServiceProvider::boot() 方法中,您可以为user 参数添加以下绑定:

// use App\Models\User;
// use Illuminate\Support\Facades\Auth;
// use Illuminate\Support\Facades\Route;

public function boot()
{
    Route::bind('user', function ($value) {
        if ($value == 'me') {
            return Auth::user();
        }

        return User::findOrFail($value);
    });
}

现在所有定义了{user} 参数的路由都将使用该函数在路由中绑定User 模型。

您可能希望更新函数以便能够处理区分大小写,或处理以访客身份访问路由的情况,但这取决于您的实现细节。

【讨论】:

  • 很好,我在半夜醒来,意识到有比我添加更多路线的答案更好的选择;看起来有几个选项。
  • @miken32 我认为有比添加新路线更好的解决方案,因为它们可能更复杂,但添加 1 条路线更明显且更少混淆,您的解决方案是最好的(来自专业的观点)
  • @matiaslauriti 是的,我认为将其显示在 artisan route:list 中而不是将内容隐藏在某个方法中很有价值
猜你喜欢
  • 1970-01-01
  • 2016-04-23
  • 2020-05-22
  • 2018-01-10
  • 2011-02-08
  • 1970-01-01
  • 2012-07-31
  • 1970-01-01
  • 2018-08-26
相关资源
最近更新 更多