Laravel Eloquent - 通过用户模型上的方法对用户关系进行排序
Posted
技术标签:
【中文标题】Laravel Eloquent - 通过用户模型上的方法对用户关系进行排序【英文标题】:Laravel Eloquent - Order users relationship by a method on the user model 【发布时间】:2017-12-31 04:35:43 【问题描述】:我正在使用 Laravel Spark 开发 API 端点。
此端点返回给定团队及其用户。
// in App\Team
public function users()
return $this->belongsToMany(
'App\User', 'team_users', 'team_id', 'user_id'
)->withPivot('role');
但是,我希望通过用户模型上的方法对这些用户进行排序。
在我的 App\User 模型上,我有一个方法:
public function currentQueueLength()
returns an integer based upon the users current appointments,
有什么方法可以返回用户关系,但通过该方法的结果对用户进行排序?
【问题讨论】:
User::currentQueueLength()
到底是做什么的?
@haakym 运行一个可怕的循环来计算用户服务的总时间。用户是理发师,并且可以与分配的服务进行许多约会。有各种模型关系,但该方法返回一个整数分钟。通常称为例如$user->currentQueueLength()
明白了。我的第一个想法是您可以使用$appends
属性和访问器方法将currentQueueLength()
作为User
模型上的属性预加载,然后在Team:: users()
调用中按此属性排序。这种方法的问题在于,听起来currentQueueLength()
是一项代价高昂的操作(根据您的最后评论,是吗?)所以理想情况下,您可以有条件地执行此操作。也许重构你的currentQueueLength()
可能是第一步?
【参考方案1】:
如果将current_queue_length
作为属性添加到User
模型,则可以按此属性进行排序。
您可以通过将属性添加到$appends
数组并创建访问器来添加属性:
class User extends Model
protected $appends = ['currentQueueLength'];
public function getCurrentQueueLengthAttribute()
return $this->currentQueueLength();
感谢这个问题:Add a custom attribute to a Laravel / Eloquent model on load?
然后在Team
中你可以像这样添加方法:
class Team extends Model
public function users()
return $this->belongsToMany(
'App\User', 'team_users', 'team_id', 'user_id'
)->withPivot('role');
public function usersByCurrentQueueLength()
return $this->users->orderBy('current_queue_length');
正如我在评论中提到的,这种方法的问题在于,听起来currentQueueLength()
是一项代价高昂的操作(基于您的评论),因此理想情况下,您可以有条件地执行此操作,但是,我不确定怎么做!您可能需要重新考虑实现 currentQueueLength()
的方法,这可能会为您构建此查询的方式提供更多选择。
【讨论】:
【参考方案2】:您可以通过像这样对用户进行排序来实现这一点:
Team::with('users')
->all();
$team->users->sort(
function ($user1, $user2)
return $user1->currentQueueLength() - $user2->currentQueueLength();
);
关于 sort 的更多信息:要按升序排序,当第一项小于第二项时返回 -1。所以你可以使用:
return $user1->currentQueueLength() < $user2->currentQueueLength() ? -1 : 1;
并按降序排序,当第一项小于第二项时返回+1。
return $user1->currentQueueLength() < $user2->currentQueueLength() ? 1 : -1;
如果它是用户模型中的一个字段,您可以这样做:
$teams = Team::with(['users' => function ($q)
$q->orderBy('Field', 'asc'); // or desc
])->all();
对于财产的情况:
// asc
$team->users->sortBy('userProperty');
// desc
$team->users->sortByDesc('userProperty');
希望有帮助:)
【讨论】:
我认为@lovelock 想要在Team::users()
调用中实现排序within? currentQueueLength
目前也不是 User
上的属性,但它可以成为 $appends
+ 访问器的属性,正如我在我对问题的评论中提到的那样,但它可能是一项昂贵的操作,并且除了这个实例之外是不需要的,所以也许不是理想?以上是关于Laravel Eloquent - 通过用户模型上的方法对用户关系进行排序的主要内容,如果未能解决你的问题,请参考以下文章
Laravel 5 Eloquent - 将计算值作为列添加到集合
Laravel 混合获取 Eloquent 急切加载嵌套多个模型
Laravel count Eloquent belongsToMany 相关模型