我有一个严重的问题。
我有3个模特
角色模型:
<?php
class Role extends Eloquent{
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'roles';
public function users()
{
return $this->belongsToMany('User', 'user_roles');
}
}
用户模型:
public function roles()
{
return $this->belongsToMany('Role', 'user_roles');
}
现在在我的控制器中,我通过选定的角色获得用户,或者如果没有被选中,我将获得与所有角色相关的所有用户:
$roles = Role::with([
'users' => function($query) use ($memtype)
{
$query->where('users.membertype', $memtype);
$query->orderBy('users.name');
$query->paginate(10);
}
])->where('id', $role_id)->get();
如果我不想按角色过滤,我使用以下代码:
$roles = Role::with([
'users' => function($query) use ($memtype)
{
$query->where('users.membertype', $memtype);
$query->orderBy('users.name');
$query->paginate(10);
}
])->get();
在我看来
我正在尝试通过以下代码生成分页链接,
@foreach($roles as $role)
@foreach($role->users as $user)
{{ $user->name }}
<br>
{{ $user->email }}
@endforeach
{{ $role->users()->links() }}
@endforeach
但我收到错误:
ErrorException
调用未定义的方法Illuminate \ Database \ Query \ Builder :: links()(查看:C:\ xampp \ htdocs \ waytohouse \ app \ views \ admin.blade.php)
请帮我解决这个问题..
此外,我在以下链接中尝试了Option1:
Laravel 4.1: How to paginate eloquent eager relationship?
但是如何在option1中添加约束。在我的情况下,它是膜类型? 提前谢谢!
答案 0 :(得分:3)
有一些事情是不可能的,你想要做什么(显然不可能采用雄辩的关系方法)。
Eloquent处理急切加载的方式,而你使用paginate
会导致整个事情不正确。
让我们检查没有paginate
的示例:
select users.*, user_roles.user_id as pivot_user_id, user_roles.role_id as pivot_role_id
inner join user_roles on user_roles.user_id = users.id
where user_roles.role_id in ( .. some ids here .. );
然后Eloquent会将返回的users
与其roles
匹配。
现在,通过paginate
,我们基本上会将limit
和offset
添加到查询中。所以这就是:
select users.*, [...]
where user_roles.role_id in ( .. some ids here .. )
limit 10 offset 0;
这意味着您只需将行数切成10行。总共10个,而不是每个角色10个。
话虽如此,你最终会得到意想不到的,完全不真实的结果(除非幸运的是,只有10个或更少的用户可以返回,但我不会指望这个用户好运。)
还有另外一件事:
$role->users; // collection of eager loaded users
$role->users(); // BelongsToMany relation object
后者完全独立于先前急切加载的集合,与您在with
闭包中调用的任何内容无关。
因此,分页相关模型的唯一方法实际上是使用:
$users = $role->users()->paginate(10);
// for example:
$roles = Role::where(..)->get();
$roles->map(function ($role) {
$role->users = $role->users()->paginate(10);
});
为每个角色。这意味着每个角色都要查询一次db。
此外,您需要让Laravel了解哪个角色的用户已分页。我想ajax是你用来向用户展示这个的唯一方法,所以好的。如果没有,那就太麻烦了。
另一种方法是加载所有东西和&#39; paginatin&#39;集合$role->users
,但我肯定不会。
答案 1 :(得分:0)
实际上,如何使用分区(在PostgreSQL中)为每个用户角色选择10个用户。这是查询:
SELECT * FROM (
SELECT *, rank() over (partition by role_id order by id) FROM users
) AS partitioned_users
WHERE rank > 10 AND rank <= 20
所以SQL不是问题。唯一的问题是,如何使用laravel Query Builder构建查询。可以像这样在没有分页的情况下急切加载:
UserRole::with(['users' => function($query) {
$subQ = DB::table('users AS partitioned_users')->select('*')
->addSelect(DB::raw('rank() over (partition by user_role_id order by id desc)'));
/** @var Builder $query */
$query->from(DB::raw("(".$subQ->toSql().") AS users"))
->where('rank', '<=', 10)
->setBindings(array_merge_recursive($subQ->getBindings(), $query->getBindings()));
})->all()
这样,它将加载所有用户角色,并为每个用户角色预先加载前10个用户。
但我还没有想出分页部分。我们需要的是创建自定义分页,使用此SQL:
WHERE rank > :offset AND rank <= :limit
而不是使用标准:
LIMIT :limit OFFSET :offset
一旦我弄明白,我就会更新你。