繁体   English   中英

Laravel Eloquent:搜索具有一系列关系的模型

[英]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;
});

最好将whereHaswhereHas方法与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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM