Laravel查询范围具有动态值
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Laravel查询范围具有动态值相关的知识,希望对你有一定的参考价值。
我正在努力想出能够满足我需求的构建器与原始SQL的正确组合。我有一个设置允许用户配置X
TournamentQuizmasters
的X
数量需要Teams
。我需要在mysql级别上进行此计算以提高效率,因此我可以快速查询所有符合条件的团队。我有其他查询范围来确定合格的团队是什么(例如withEnoughPlayers()
)。
这段代码不起作用,但我认为它传达了我的意图。
// A collection of Teams
class TeamSet extends Model {
public function scopeWithEnoughQuizmastersBasedOnTeamCount(Builder $q, Tournament $tournament)
{
// Pull only the groups that bring enough quizmasters. The required number
// of quizmasters is based off of the number of teams they're bringing.
return $q->whereHas('group', function (Builder $q) use ($tournament) {
$q->has(
'tournamentQuizmasters',
'>=',
DB::raw('FLOOR(('.$tournament->settings->quizmastersToRequireByTeamCount().' * '.$q->selectRaw('COUNT(*)')->teams()->withEnoughPlayers($tournament)->toSql().') / '.$tournament->settings->teamCountToRequireQuizmastersBy().')')
);
});
}
}
运行这个查询我得到Call to undefined method IlluminateDatabaseEloquentBuilder::teams()
我相信是因为selectRaw()
进行它。我也不认为我可以按照我在这里的方式实际调用->teams()
,但是我有点失明,因为我应该改变它以获得我正在寻找的结果。
如何在使用查询构建器时执行此动态表达式,以便我可以使用我的范围?
我正在使用Laravel 5.7
Models & Relations
class TeamSet {
public function group() : BelongsTo
{
return $this->belongsTo(Group::class);
}
public function teams() : HasMany
{
return $this->hasMany(Team::class)
}
}
class Team {
public function teamSet() : BelongsTo
{
return $this->belongsTo(TeamSet::class)
}
}
class Group {
public function tournamentQuizmasters() : HasMany
{
return $this->hasMany(TournamentQuizmaster::class);
}
public function teams() : HasManyThrough
{
return $this->hasManyThrough(Team::class, TeamSet::class);
}
}
class Tournament {
public function teamSets() : HasMany
{
return $this->hasMany(TeamSet::class);
}
public function teams() : HasManyThrough
{
return $this->hasManyThrough(Team::class, TeamSet::class);
}
}
class TournamentQuizmaster {
public function group() : BelongsTo
{
return $this->belongsTo(Group::class);
}
public function tournament() : BelongsTo
{
return $this->belongsTo(Tournament::class);
}
}
型号描述:
TeamSet
- 代表团队集合的单一实体。这使我们的用户能够使用同一组团队参加多个锦标赛。Team
- 球员的集合Group
- 组名。这在app中的其他地方使用,但每个TeamSet
都属于一个组。Tournament
- 相当不言自明TournamentQuizmaster
- 比赛的裁判或裁判。每个小组都需要根据他们的团队数量来提供这些X.
$泰国队>设置
它作为json存储在数据库中,但是转换为对象,因此我有一个合理的位置来保持默认值。这是该类的片段:
use IlluminateSupportFluent;
class Settings extends Fluent
{
const DEFAULT_MAXIMUM_PLAYERS_PER_TEAM = 5;
const DEFAULT_MINIMUM_PLAYERS_PER_TEAM = 3;
public function __construct($attributes = [])
{
if ($attributes !== null) {
parent::__construct($attributes);
}
}
public function shouldRequireQuizmasters() : bool
{
return $this->get('requireQuizmasters', 'none') != 'none';
}
public function shouldRequireQuizmastersByGroup() : bool
{
return $this->get('requireQuizmasters', null) == 'group';
}
public function quizmastersToRequireByGroup() : int
{
return $this->get('quizmastersToRequireByGroup', 1);
}
public function setQuizmastersToRequireByGroup(int $quizmasterCount)
{
$this->quizmastersToRequireByGroup = $quizmasterCount;
}
public function shouldRequireQuizmastersByTeamCount() : bool
{
return $this->get('requireQuizmasters', null) == 'team_count';
}
public function quizmastersToRequireByTeamCount() : int
{
return $this->get('quizmastersToRequireByTeamCount', 1);
}
存储在数据库中的json最终看起来像:
{"collectShirtSizes":"1","collectQuizmasterPreferences":"1","allowsGuestPlayers":true,"minimumPlayersPerTeam":3,"maximumPlayersPerTeam":6,"requireQuizmasters":"group","quizmastersToRequireByGroup":1,"quizmastersToRequireByTeamCount":1,"teamCountToRequireQuizmastersBy":2}
我可以使用下面的文章中的subSelect技术做一些这样的事情。 https://reinink.ca/articles/dynamic-relationships-in-laravel-using-subqueries
基于此,您可以将具有足够玩家的团队数量添加到您的群组查询中,并将其与锦标赛测验大师计数进行比较。我希望我能理解你的查询。也许这样的事情。
/// In Group
public function scopeHasRequiredAmount(Builder $builder, Tournament $tournament)
{
return $builder->withCount('tournamentQuizmasters')
->teamsWithEnoughPlayersCount()
->havingRaw(
'tournamentQuizmasters_count > FLOOR((' . $tournament->settings->quizmastersToRequireByTeamCount() .
'* teams_with_enough_players_count ) /'
. $tournament->settings->teamCountToRequireQuizmastersBy() . ')'
);
}
/// adds count of teams with enough players to query
public function scopeTeamsWithEnoughPlayersCount(Builder $builder, Tournament $tournament)
{
return $builder->addSubSelect('teams_with_enough_players_count', Team::selectRaw('count(*)')
->whereColumn('groups.id', 'teams.group_id')
->withEnoughPlayers($tournament)
);
}
/// In Teamset
function scopeWithEnoughQuizmastersBasedOnTeamCount(Builder $builder, $tournament)
{
return $builder->whereHas('group', function (Builder $q) use ($tournament) {
$q->hasRequiredAmount($tournament);
});
}
以上是关于Laravel查询范围具有动态值的主要内容,如果未能解决你的问题,请参考以下文章
Laravel Eloquent - 如何将范围查询内的计算值作为模型列或集合属性返回