Laravel-Backpack:结合 hasMany 和 hasManyThrough 在列表中添加子句

Posted

技术标签:

【中文标题】Laravel-Backpack:结合 hasMany 和 hasManyThrough 在列表中添加子句【英文标题】:Laravel-Backpack: combine hasMany and hasManyThrough to add clauses in list 【发布时间】:2021-10-23 04:36:36 【问题描述】:

这是我所拥有的:

用户表

以“project_id”作为列之一的实例表

项目表

带有“user_id”和“instance_id”的instance_user表

带有“user_id”和“project_id”的project_user表

当我创建用户时,我希望能够通过 select2_multiple 将项目和/或实例与用户相关联,将条目添加到数据透视表中。到这里为止,一切正常。

然后,当用户登录时,在实例列表中,我希望他们只看到他们在“instance_user”表中关联的实例以及属于他们在“project_user”中关联的项目的实例桌子。所以,例如:

用户:

id name
1 Example1
2 Example2

实例:

id name project_id
1 Instance1 1
2 Instance2 1
3 Instance3 2
4 Instance4 2
5 Instance5 2

instance_user:

instance_id user_id
4 1

project_user:

project_id user_id
1 1

这里,id=1 的用户会在实例列表中看到 = Instance1, Instance2, Instance4

我尝试在 InstanceCrudController 中添加这个:

CRUD::addClause('has', 'users');
CRUD::addClause('has', 'instances_through');

这些是我的用户和实例模型:

//USER MODEL
    public function instances()
    
        return $this->belongsToMany(Instance::class);
    

    public function projects()
    
        return $this->belongsToMany(Project::class);
    

//INSTANCE MODEL
    public function users()
    
        return $this->belongsToMany(User::class);
    

    public function instances_through()
    
        return $this->hasManyThrough(
            User::class,
            ProjectUser::class,
            'project_id',
            'id',
            'id', 
            'user_id' 
        );        
    

但这显然是不正确的,因为它没有显示预期的结果,而且我认为我不太了解在这种情况下如何使用 hasManyThrough。

有没有办法做到这一点,一个函数可以返回具有给定限制的组合结果?或有关如何解决此问题的任何提示。

非常感谢。

【问题讨论】:

【参考方案1】:

即使我的回答得到了预期的结果,当有数百万条记录时,这也不是获取实例的好方法。所以你最好找一个 不同的方式来实现这一点。最有可能尝试拥有 db 表 修改,您可以在其中获取某个用户的所有实例。

这是您可以根据您的表结构使用的方法。

    通过instance_user获取实例ID 通过project_user获取实例ID 合并 ID 通过合并的 id 查找实例

示例代码。我已经在github/nipunTharuksha/Laravel-Backpack-answer 测试了这个和演示项目,我还定义了其他关系。

class InstanceCrudController extends Controller

    public function userInstances()
    
        $user = User::find(1);

        $instance_ids_via_instance_user = (clone $user)->instances()->pluck('instance_id')->toArray(); //Instance id 4
        $instance_ids_via_project_user = Instance::whereIn('project_id', (clone $user)->projects()->pluck('project_id')->toArray())->get()->pluck('id')->toArray(); // Instance is 1,2

        $instance_ids = array_merge($instance_ids_via_instance_user,$instance_ids_via_project_user);

        $instances = Instance::find($instance_ids);

        return response()->json($instances);

    

结果

[
  
    "id": 1,
    "name": "Prof. Raphaelle Robel DVM",
    "project_id": 1,
    "created_at": "2021-08-22T17:26:54.000000Z",
    "updated_at": "2021-08-22T17:26:54.000000Z"
  ,
  
    "id": 2,
    "name": "Tianna Glover",
    "project_id": 1,
    "created_at": "2021-08-22T17:26:54.000000Z",
    "updated_at": "2021-08-22T17:26:54.000000Z"
  ,
  
    "id": 4,
    "name": "Abigale Cummings",
    "project_id": 2,
    "created_at": "2021-08-22T17:26:54.000000Z",
    "updated_at": "2021-08-22T17:26:54.000000Z"
  
]

性能

【讨论】:

如果我的回答回答了您的问题,希望您可以将其标记为答案。谢谢 谢谢!你的代码给了我一个关于如何解决这个问题的想法并且它有效。我确信有很多更好、更优雅的解决方案,但由于是一个非常小的项目(最多 200 个实例和 20-30 个项目),我会选择它。【参考方案2】:

这就是我最终要做的。很高兴看到不同的方法。

//InstanceCrudController

    public function get_instance_ids($user_id)
    
        $user = User::find($user_id);

        $instance_ids_via_instance_user = $user->instances->pluck('id')->toArray(); 
        $instance_ids_via_project_user = Instance::whereIn('project_id', $user->projects->pluck('id')->toArray())->pluck('id')->toArray();

        $instance_ids = array_merge($instance_ids_via_instance_user,$instance_ids_via_project_user);                                                                 

        return $instance_ids;
    

CRUD::addClause('whereIn', 'id', $this->get_instance_ids(backpack_user()->id));

【讨论】:

以上是关于Laravel-Backpack:结合 hasMany 和 hasManyThrough 在列表中添加子句的主要内容,如果未能解决你的问题,请参考以下文章

全新安装退出代码 127

是否可以包含与相关模型相关的模型?

laravel Eloquent 查询 WhereHas 结果错误

Laravel 一对多关系不起作用 - 返回递归

Ember Mirage 模型:对于多个 hasMany 和 belongsTo

在 Laravel 中获取每个用户的最新消息(行)