[英]Laravel Eloquent: Search models with array of relationships
我在雄辩的模型Candidate
中具有以下作用域,让我们获取一个Collection,其中每个项目都有一个与Collections $fields
和$categories
相匹配的关系。
也就是说,它让我得到了具有所有$fields
和$categories
的候选人集合。
class Candidate extends Model {
public function scopeMatching($query, $fields, $categories ) {
return $query->get()->filter( function ( $candidate ) use ( $categories, $fields ) {
$outcome = false;
foreach ($categories as $category){
$outcome = $candidate->categories->contains( $category );
}
foreach ($fields as $field){
$outcome = $candidate->fields->contains( $field );
}
return $outcome;
});
}
public function user() {
return $this->belongsTo( User::class );
}
public function jobs() {
return $this->belongsToMany(Job::class);
}
public function categories() {
return $this->belongsToMany(Category::class);
}
public function fields() {
return $this->belongsToMany(Field::class);
}
}
测试方法的用法示例:
// Pick 2 random categories
$categories = Category::all()->random( 2 );
// Pick 5 random fields.
$fields = Field::all()->random( 5 );
// Pick a random candidate.
$candidate = Candidate::all()->random();
// Attach categories and fields to candidate.
$candidate->categories()->attach( $categories );
$candidate->fields()->attach( $fields );
// Filter candidates to get only matching ones.
$candidates = Candidate::with(['fields','categories'])->matching($fields, $categories);
它工作正常,但我想知道这是否是最好的方法。 是否有一种更好的,更“雄辩的”的方式来执行此操作而不使用两个foreach
循环?
$collection = collect([
'field1' => 'value1',
'field2' => 'value2',
'field3' => 'value3',
]);
$outcome = $collection->contains(function ($value, $key) use ($category) {
return $value == $category;
});
最好将whereHas
的whereHas
方法与whereIn
一起whereIn
因为它们将使用SQL而不是PHP for循环,这将最终提高效率。
$query->whereHas('fields', function($q) use($fields) {
$q->whereIn('id', $fields->pluck('id'));
})->orWhereHas('categories', function($q) use($categories) {
$q->whereIn('id', $categories->pluck('id');
})->get();
该查询与获取至少有一个字段关系谁的id是在所有考生fields
数组或具有至少一个类别的关系谁的ID是在categories
阵列。
您可以在文档Laravel Query Builder文档中阅读有关这些方法的更多信息。
Josh建议的解决方案可行 ,但是我做了一些调整,因为我想匹配所有字段,但要匹配ANY类别。
public function scopeMatching( Builder $query, Collection $fields, Collection $categories ) {
foreach ( $fields as $field ) {
$query = $query->whereHas( 'fields', function ( Builder $q ) use ( $field ) {
$q->where( 'id', $field->id );
} );
}
$query->whereHas( 'categories', function ( Builder $q ) use ( $categories ) {
$q->whereIn( 'id', $categories->pluck( 'id' ) );
});
return $query->get();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.