[英]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.