1
votes

So if I have models

Song

and

Writer

and Song has many Writers

And I want to query songs such that I only get songs where all its writers have a certain field that is true, what would my solution be?

The Laravel whereHas function will get all songs that have at least one writer with that field, like so.

Song::whereHas('writers', function($query){
    $query->where('writerField', '=', true);
});

But what is the pure eloquent way to make sure EVERY writer related to a Song has that 'writerField' set to true?

3
Thanks for the down vote. An explanation would have been nice.jamesmpw
plz. add Your models code to Your question, and also describe how they have relations (field names)num8er

3 Answers

0
votes

I found the answer, sorry ya'll forgot to post it.

The answer is to use the count feature and invert the query.

Song::whereHas('writers', function($query){
    $query->whereNull('writerField');
}, '=', 0);

I do appreciate all the responses. I thought this question was dead because of the down vote.

0
votes

My realization is like this:

songs table has: id, title and etc
writers table has: id, name and etc
writers_songs table has: writer_id, song_id

class Song extends Model {
    protected $table = 'songs';

    public final function writers() {
        return $this->hasManyThrough('Writer', 'WriterSong');
    }
}

class WriterSong extends Eloquent {
    protected $table = 'writers_songs'; // it has to fields: song_id, writer_id
}

class Writer extends Eloquent {
    protected $table = 'writers';

    public final function songs() {
        return $this->hasManyThrough('Song', 'WriterSong');
    }
}

and this is how I do request:

$Songs = Song::with('writers')->whereHas('writers')->where('title', 'like', '%hello%')->get();
foreach($Songs AS $Song) {
    $Writers = $Song->writers;
    echo "Title: ".$Song->title.'<br/>';
    foreach($Writers AS $Writer) {
       echo "Writer: ".$Writer->name.'<br/>';
    }
}

it's simple way than keeping additional field in songs table

-2
votes

I think the whereHas makes a inner join, in this case Songs with Writers so since that is the intersection between those 2 tables you are actually getting the result you are asking for. This laracast explains a bit of what I said.

By the way I also hate people who down vote and leave without saying anything!