1

Reference: Laravel Eloquent relationship not an object when doing anything but dd()

I am trying to output a Laravel relationship in Blade. However, this, {{ $video->channel->id }} returns a non-object error. But, when dded, like so, {{ dd($video->channel->id) }}, a value is there. I've been pulling my hair so hard because of this... What is going on? Why is there an output only when the variable is dded?

I'm testing on PHP 7.2 with Laravel 5.6. Relationships are established as per Eloquent documentation. I've tried fetching the data like this:

$videos = Video::where('foo', 'bar')->with('channel')->take(100)->get();

and

$videos = Video::where('foo', 'bar')->take(100)->get();

The same thing; same output/error.

$tokens = preg_split("/[\s,]+/", $q);
$videos = Video::with('channel')
  ->where(function ($query) use ($tokens) {
    foreach ($tokens as $token) {
      $query->orWhere('title', 'LIKE', "%$token%");
    }
   })
  ->take(100)
  ->get();
// foreach ($videos as $video)
{{ $video->channel->id }} // non-object error
{{ dd($video->channel->id) }} // WORKS! IDK Why...

Trying to get property 'id' of non-object is the actual error log.

EDIT:
Below is an image of the $videos collection fetched from Database. If in dd(), something gets outputted fine, I can only assume I'm fetching the data right, yea?

enter image description here

Valkyrurr
  • 119
  • 1
  • 12
  • 2
    Make sure you understand how `dd()` works , it's die and dump, so basically it immediately ends the execution after that function is called, the source of error might be after `dd()` is called. Try doing `var_dump()` which doesn't end the execution – Dhiraj Jun 11 '19 at 16:34
  • @Dhiraj Wow. That makes a difference. Used `dd()` a lot that I forget its actual functionality. However, that did not resolve the issue. Same error with `var_dump()` applied. – Valkyrurr Jun 11 '19 at 16:40
  • Or if you don't want it to show on the screen, use `Log::info($video->channel->id);` and check the responses in the file located in `/storage/logs`. This way it will print out some data before it breaks. – aynber Jun 11 '19 at 16:40

1 Answers1

2

As you're doing this in a loop, the error

Trying to get property 'id' of non-object

means that 1 iteration of $video->channel returns a non-object (likely null), and you can't access the property ->id of it (as null doesn't have any properties, etc.)

The reason dd() works is that it's dumping and dieing on the first iteration, which has a channel. To handle this, simply add an @if() clause:

@foreach($videos AS $video)
  @if($video->channel)
    {{ $video->channel->id }}
  @else 
    ...
  @endif
  ...
@endforeach

Or, in the query to get $videos, enforce relationship:

$videos = Video::where('foo', 'bar')->has('channel')->with('channel')->take(100)->get();

This way, $video->channel will not be null.

Tim Lewis
  • 27,813
  • 13
  • 73
  • 102
  • Let me try your sample code. Also, relationship has been enforced. Please check OP for actual code. – Valkyrurr Jun 11 '19 at 16:45
  • 1
    Not quite. `->with()` doesn't enforce it; it just loads it. `->has()` is what enforces it :) – Tim Lewis Jun 11 '19 at 16:46
  • That `->has()` without the `->with()` fixes it. Thank you so much. I'm not sure how they differ. Can you please point me to some documentation on the difference between those 2? What's the advantage of invoking both? – Valkyrurr Jun 11 '19 at 16:51
  • https://stackoverflow.com/questions/30231862/laravel-eloquent-has-with-wherehas-what-do-they-mean nevermind. found something here. Thanks again. – Valkyrurr Jun 11 '19 at 16:51
  • 1
    You can use both; what `->with()` does is eager loads the relationship, so that calling `$video->channel` doesn't execute another DB query. Using `->has()` modifies the underlying query to only include records that have a related record. Also available is `->whereHas()`, that limits the query to related records that match additional logic, like a `status` column or something similar. https://laravel.com/docs/5.8/eloquent-relationships#querying-relationship-existence has all the documentation on it. – Tim Lewis Jun 11 '19 at 16:52