How to check if one record is attached to another?

11,217

Solution 1

Try instead:

$seminar->students->contains($student->id);

Presuming $student contains an instance of the Student model you can simplify it further and just use:

$seminar->students->contains($student);

When you add parentheses you're using the Laravel query builder, and you never completed the query. To do it in the manner you had originally you would need:

$seminar->students()->get()->contains($student->id);

This method could be useful if you wanted to add constraints when fetching your students.

But generally you can omit the parentheses and a Collection will be returned, allowing you to use methods like contains.

This has the additional benefit of not re-querying the database once the relationship is loaded, so will generally be a far more efficient means of fetching relationships.

If you haven't already loaded the students and want a database efficient method of checking you could instead use:

$seminar->students()->where('students.id', $student->id)->exists();

Solution 2

In your case the exception is you are calling 'contains()' function (which is for Laravel Collection) on 'Query Builder'. It should be

$seminar->students->get()->contains($student->id);

but this is inefficient since this will retrieve all the students of the seminar.

so instead,

$seminar->students()->wherePivot('student_id', $student->id)->exists();

this method will check in the intermediate table of many to many relationship for particular seminar-student pair, and will return whether exists or not.

Share:
11,217
Alex Lomia
Author by

Alex Lomia

Updated on June 16, 2022

Comments

  • Alex Lomia
    Alex Lomia almost 2 years

    I have defined a many-to-many relationship between Student and Seminar models. How can I find out if one particular student is attending one particular seminar? Non-working example of what I want to achieve is illustrated below:

    $seminar->students()->contains($student->id);
    

    The following error is shown when using the above code snippet:

    BadMethodCallException with message 'Call to undefined method Illuminate\Database\Query\Builder::contain()'

  • Alex Lomia
    Alex Lomia almost 8 years
    Thanks for an answer. Wouldn't that introduce an unnecessary load on the DB? Since it retrieves all of the students of the given $seminar from the database and only after that it checks the array with contains()
  • Matt McDonald
    Matt McDonald almost 8 years
    Yes. In which case you can't use contains as it's a Collection method. You'd instead need something like: $seminar->students()->exists($student -> id);
  • Alex Lomia
    Alex Lomia almost 8 years
    Thank you, the exists() method was exactly what I was looking for
  • Agil
    Agil over 6 years
    @MattMcDonald I have a simular issue too, do you think I can somehow use $seminar->students()->exists($student->id); inside an if statement? I never used many to many before so I'm having quite a little trouble with it.
  • Matt McDonald
    Matt McDonald over 5 years
    $seminar->students()->exists($student->id) and $seminar->students->exists($student->id) do very different things - note there are no () in the solution.
  • jgawrych
    jgawrych about 5 years
    Not sure if this has changed in laravel, but exists() doesn't take any parameters as of 5.7. The last code example will ignore the parameter and make a DB call to check if any students exist in the seminar, not just a specific one.