Laravel-Backpack: 组合 hasMany 和 hasManyThrough 以在列表中添加子句
Laravel-Backpack: combine hasMany and hasManyThrough to add clauses in list
这是我的:
用户table
实例 table 将“project_id”作为列之一
项目table
instance_user table 与“user_id”和“instance_id”
project_user table 与“user_id”和“project_id”
当我创建用户时,我希望能够通过 select2_multiple 将项目 and/or 实例关联到用户,将条目添加到数据透视 tables。到目前为止,一切正常。
然后,当用户登录时,在实例列表中,我希望他们只看到他们在“instance_user”table 中关联的实例以及属于的实例他们在“project_user”table 中关联的项目。所以,例如:
用户:
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。
有什么方法可以做到这一点,其中一个函数可以 return 具有给定限制的组合结果?或者有关如何处理此问题的任何提示。
非常感谢。
Even my answer get the expected result this is not a good way to get instances when there are millions of records. So you better find a
different way to achieve this. Most probably try to have db table
modification where you can get all the instances for a certain user.
这是您可以根据您的 table 结构使用的方法。
- 通过
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"
}
]
性能
这就是我最终所做的。很高兴看到不同的方法。
//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));
这是我的:
用户table
实例 table 将“project_id”作为列之一
项目table
instance_user table 与“user_id”和“instance_id”
project_user table 与“user_id”和“project_id”
当我创建用户时,我希望能够通过 select2_multiple 将项目 and/or 实例关联到用户,将条目添加到数据透视 tables。到目前为止,一切正常。
然后,当用户登录时,在实例列表中,我希望他们只看到他们在“instance_user”table 中关联的实例以及属于的实例他们在“project_user”table 中关联的项目。所以,例如:
用户:
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。
有什么方法可以做到这一点,其中一个函数可以 return 具有给定限制的组合结果?或者有关如何处理此问题的任何提示。
非常感谢。
Even my answer get the expected result this is not a good way to get instances when there are millions of records. So you better find a different way to achieve this. Most probably try to have db table modification where you can get all the instances for a certain user.
这是您可以根据您的 table 结构使用的方法。
- 通过
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"
}
]
性能
这就是我最终所做的。很高兴看到不同的方法。
//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));