Ali Erfani
Ali Erfani

Reputation: 692

Laravel 5.1 Eloquent: How to retrieve a collection based on some conditions?

I need to filter a collection of projects based on some conditions. Hear is the scenario.

//This is part of projects table schema
  Schema::create('projects', function (Blueprint $table) {
           ...
            $table->smallInteger('source_lang_id')->index()->unsigned();
            $table->smallInteger('target_lang_id')->index()->unsigned();
           ...
        });
//This is part of translator_infos schema
Schema::create('translator_infos', function (Blueprint $table) {
          ....
            $table->smallInteger('from_l_1_id')->index()->unsigned();
            $table->smallInteger('from_l_2_id')->index()->nullable()->unsigned();
            $table->smallInteger('from_l_3_id')->index()->nullable()->unsigned();
            $table->smallInteger('from_l_4_id')->index()->nullable()->unsigned();
            $table->smallInteger('to_l_1_id')->index()->unsigned();
            $table->smallInteger('to_l_2_id')->index()->nullable()->unsigned();
            $table->smallInteger('to_l_3_id')->index()->nullable()->unsigned();
            $table->smallInteger('to_l_4_id')->index()->nullable()->unsigned();
        ....
        });

So each project has a source and target language. Translators may have 4 language pairs. What I need is that to filter the collection of projects and find projects that their source and target language match at least one of the translator language pairs and pass this collection to the view. For now the query I'm using is the following:

$projects=Project::orderBy('created_at', 'desc')->where('status_id', "=", 1)->paginate(15);

How can I add this condition to the query? I tried using the following scope in my Project model but it is only appropriate for one pair of languages:

public function scopeLangMatch($query, $from, $to)
    {
        $match=[
            'source_lang_id'=>$from,
            'target_lang_id'=>$to
        ];
        return $query->where($match);
    }

Upvotes: 0

Views: 135

Answers (2)

Hailwood
Hailwood

Reputation: 92581

Try rewriting your scope as follows:

public function scopeLangMatch($query, $matches) {

    $useOr = false;
    foreach($matches as $from => $to){
        $match=['source_lang_id'=>$from, 'target_lang_id'=>$to];
        $query = ($useOr ? $query->orWhere($match) : $query->where($match));
        $useOr = true;
    }

    return $query;
}

Then you can use it as

Project::langMatch([
    1 => 2, 
    3 => 4, 
    5 => 6,
    7 => 8
])->get();

which also gives you the flexibility to define more or less matches in the future without having to modify your code or worry about param matching.

Upvotes: 1

Ali Erfani
Ali Erfani

Reputation: 692

Thanks to @Hailwood suggestion I found the solution. I defined the following scope in the Project model:

public function scopeLangMatch($query, $from1,$from2,$from3,$from4, $to1, $to2, $to3, $to4)
    {
        $match=[
            'source_lang_id'=>$from1,
            'target_lang_id'=>$to1
        ];
        $match2=[
            'source_lang_id'=>$from2,
            'target_lang_id'=>$to2
        ];
        $match3=[
            'source_lang_id'=>$from3,
            'target_lang_id'=>$to3
        ];
        $match4=[
            'source_lang_id'=>$from4,
            'target_lang_id'=>$to4
        ];
        return $query->where($match)->orWhere($match2)->orWhere($match3)->orWhere($match4);
    }

Upvotes: 0

Related Questions