背景

在我的Laravel应用程序中,我有模型OrganizationRegionLocation,它们都通过一个Assignment模型与User模型存在多态关系.(AssignmentUserRole和其他三个实体之一之间的三向关系,但这与这里的问题并不严格相关.

我想为其他三个模型的每个控制器添加一个showUsers方法,以获取与该实体关联的所有用户.为了避免在所有三个控制器中复制粘贴相同的代码,我创建了一个trait,如下所示:

use App\Http\Resources\UserSimpleWithRoleResource;
use App\Models\Assignment;
use Illuminate\Database\Eloquent\Model;

trait GetsRelatedUsers
{
    function listUsers(Model $model)
    {
        // Thanks to explicit model binding,
        // `$model` can be any supported model.

        $assignments = Assignment::with(['user:id,given_name,surname', 'role:id,name,display_order'])
            ->has('user') // prevents assignments for soft-deleted users from showing up
            ->atPlace($model) // a scope that also adds other conditions based on the provided model
            ->get();

        return UserSimpleWithRoleResource::collection($assignments);
    }
}

为了解析路由中的Model $model值,我需要在RouteServiceProviderboot方法中有显式的模型绑定,如下所示:

Route::model('location', Location::class);
Route::model('region', Region::class);
Route::model('organization', Organization::class);

问题

在我的routes文件中,我设置了OrganizationRegionLocation的三个控制器,以允许查看和编辑软删除模型,如下所示:

Route::apiResource('organizations', \App\Http\Api\Organizations\Controller::class)->withTrashed(['show', 'update']);
Route::apiResource('regions', \App\Http\Api\Regions\Controller::class)->withTrashed(['show', 'update']);
Route::apiResource('locations', \App\Http\Api\Locations\Controller::class)->withTrashed(['show', 'update']);

在添加显式模型绑定之前,内置的隐式模型绑定将判断路由是否存在withTrashed选项,并将模型解析器更改为包括垃圾项.但是,显式绑定不执行此判断.

除了在我的显式模型绑定中完全重新实现对$route->allowsTrashedBindings()的判断之外,有没有一种好的方法来实现这一点,以便一些路由可以包括垃圾项目,而其他路由则不能?

推荐答案

以下是迄今为止我能想出的最好的办法,尽管我并不太满意:

Route::bind('location', function ($id, RouteDefintion $route) {
    return Location::query()
        ->when($route->allowsTrashedBindings(), function ($query) {
            $query->withTrashed();
        })
        ->findOrFail($id);
});

Route::bind('region', function ($id, RouteDefintion $route) {
    return Region::query()
        ->when($route->allowsTrashedBindings(), function ($query) {
            $query->withTrashed();
        })
        ->findOrFail($id);
});

Route::bind('organization', function ($id, RouteDefintion $route) {
    return Organization::query()
        ->when($route->allowsTrashedBindings(), function ($query) {
            $query->withTrashed();
        })
        ->findOrFail($id);
});

注:

  • RouteDefinitionuse Illuminate\Routing\Route as RouteDefintion;,因为路由外观已经使用了Route.
  • 回调函数中的$route参数没有文档说明;我通过查看框架源代码找到了它.
  • 我可能可以简化这个过程,通过创建一个函数,接受一个模型类,这样我就不必重复三次了,但我真的想先看看是否有一个更优雅的答案.

Php相关问答推荐

仅显示特定WooCommerce产品类别的额外产品字段

自定义WooCommerce帐户下载列表

PHP日期操作,将多个日期输出为格式化字符串

允许在WooCommerce管理员优惠券列表中显示自定义优惠券类型

通过DO LAMP进行身份验证并从邮箱发送邮箱的最简单方式是什么

在Laravel中为表添加前缀,以将它们逻辑地分组

是否使用联系人表单7 wpcf7_Feedback_Response输出答复中的html?

防止在WordPress短代码中显示重复产品并请求代码更正

如何批量处理消息总线中的消息

如何用十进制和字母数字减go 和添加 id

如何使用 AJAX、PHP 和 MYSQL 在 Select 项目时在文本框中填充数据

WooCommerce:如果购物车中已存在产品,则增加购物车商品数量

将一个表中的行连接为不同表MYSQL中的一列

标签打印机的 CSS

提交仅包含活动详细信息选项卡表单的主表单

Windows 身份验证在 IIS 中验证什么?我可以在我的情况下禁用匿名身份验证吗?

Laravel 8:会话不适用

如何从此字符串创建 Carbon 对象:2022-06-21T05:52:46.648533678Z?

如何在 Laravel 中验证多个输入?

在管理表单字段中