Eloquent relationship fails to work unless dd()ed in view - php

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?

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.

Related

Paginate Issue Laravel 5.6

Was wondering if someone could check this out and let me know what I'm doing wrong. I'm trying to use paginate on a database query and render it in my view.
Is my DB query incorrect? I was following the docs to create it. Also read that I needed to remove ->get() when using paginate.
This is what is giving the error on my view: {{$item->paginate(4)}}, same happens if I use {{$item->links(4)}}
Everything renders fine if I remove paginate from the query in the controller..?
Here is what I'm working with.
Controller:
public function index()
{
// $news = DB::table('news')->orderBy('id', 'DESC')->paginate(4);
$news = DB::table('news')->select('id','title','description','listing_image','created_at','updated_at')->orderBy('id', 'DESC')->paginate(4);
return view('news.index',compact('news'));
}
View: (Getting error: Call to undefined method stdClass::paginate())
#if ($news->count())
#foreach($news as $item)
...html
#if ($item->listing_image)
...more html
#else
#endif
... more html
#endforeach
{{$item->paginate(4)}}
#endif
change {{$item->paginate(4)}} to {{ $news->links() }}

Laravel #foreach

I need to get each comment of news . Its working good for firstorFail() item
{{$news->comments()->firstOrFail()->name}}
But bring me empty result when im try this one with foreach:
#foreach($news->comments() as $comment)
{{$comment->name}}
#endforeach
The function firstOrFail will return exactly one comment. Seems like you actually want all comments? You should use this in your controller
$news->comments; // yeah that's it, it will load all comments
Also return news
return view('my.view', compact('news'));
Then use it in blade
#foreach($news->comments as $comment)
{{$comment->name}}
#endforeach
the line
$news->comments()
would require you to also call ->get() , because comments() will return the relation instead of the actual data.
This: $news->comments() bringing you query builder probably. So what you need is to ->get() for execute query like this:
#foreach($news->comments()->get() as $comment)
{{$comment->name}}
#endforeach
Edit
or as a #Roy Philips mentioned: $news->comments

Using ::find but with a custom where clause

I use ::find to find the business but business_position I need to use WHERE business_id = and WHERE id to find the correct position, and example is avalible below...
<?php
$s = Stats::find(Auth::user()->id);
$myJob = \App\Businesses::find($s->business_id);
$matchedValues = ['business_id' => $s->business_id, 'id' => $s->business_position];
$myPosition = \App\BusinessPositions::where($matchedValues)->get();
?>
And using $myPosition I use
{{ $myPosition->pay_amount }}
And on that line it throws and error...
Undefined property:
Illuminate\Database\Eloquent\Collection::$pay_amount (View:
C:\Users\Darren\MyLavProject\resources\views\pages\business\business.blade.php)
Laravel's get() returns a collection of results that match your query (even if there are none or just one, it'll be an array of Laravel model instances).
You can use first() instead of get() to grab the first result, or you can foreach through each of the results get() provides. It depends if your application permits more than one permission per business_id/id combination.
$myPosition This is an array of objects.
So if you need the result:
{{ $myPosition[0]->pay_amount }}
Or
#foreach($myPosition as $position)
{{ $position->pay_amout }}
#endforeach
Of if you don't want to use any of these:
Change your query to :
$myPosition = \App\BusinessPositions::where($matchedValues)->first();
Now you can use: {{ $myPosition->pay_amount }}

Laravel 4 : trying to get variable from same page

I'm new to Laravel and I'm getting an error which I think has more to do with logic than anything else but I can't quite seem to grasp how to overcome it.
So, I have a page with a simple form to search for a particular string in my database. But I want to have the result show up on the same page.
Here's what I have so far:
This is my Route.php:
Route::get('/', 'HomeController#index');
Route::post('find', 'HomeController#find');
This is my HomeController:
public function index()
{
return View::make('index');
}
public function search()
{
return View::make('index');
}
public function find()
{
$match = Input::get('find');
if($match) {
$results = Book::where('title', 'like', '%'.$match.'%')
->orWhere('author', 'like', '%'.$match.'%')
->get();
return View::make('index', array('results', $results));
} else {
return Redirect::to('/')->with('flash_error', 'No string added!');
}
}
And my View (index.blade.php):
{{ Form::open(array('url' => 'find', 'method' => 'POST')) }}
{{ Form::text('find', '', array('class' => 'search-query', 'placeholder' => 'Search')) }}
{{ Form::submit('Submit', array('class' => 'btn btn-info')) }}
{{ Form::close() }}
#if (Session::has('flash_error'))
{{ Session::get('flash_error') }}
#endif
#foreach ($results as $result)
{{$result->title}}
#endforeach
(eventually the foreach will be replaced by some ajax loading to display each result)
And the error says "undefined variable: results" and shows the foreach.
I get why that error shows up since on the first pass to this page the results haven't been loaded yet but how can I overcome this? I really want the data to be shown on the same page without having to go to another page to display them.
Like I said, I think this is mostly logic related (although I'm very new to Laravel so it might be that too)
Any help would be greatly appreciated !
you need to pass an associative array as your second param of the make method
return View::make('index', array('results' => $results);
The problem here is that in your use of index.blade.php in multiple controllers, you forgot which controllers provide which variables (and as a result, which variables may be omitted).
When you request / (HomeController#index), index.blade.php is rendered, but since no $results are passed to the view, you see the Undefined Variable warning. This is not a problem in HomeController#find, because you define $results. To combat this, you'll need to do something along the lines of an isset() check on $results before you foreach over it. Like so:
#if(isset($results))
#foreach ($results as $result)
{{$result->title}}
#endforeach
#endif
Your logic may vary based on your page's layout (you might want to add an else and display some alternate placeholder content).
Also, if abstracting the call to View::make() with $results into index_gen() isn't keeping your code DRY, then I'd suggest replacing it in find() with the call to View::make().

Laravel 4 Eager Loading "Undefined Property"

Why can't I access the property in an eager loaded senario?
I am trying to access the photo location for my facilities model. They have a Many:Many relationship. When I load the facility info using
$facilities = Facility::with('photos')->get();
When I try to access
foreach($facilities as $facility)
{
echo $facility->photos->id;
}
I get the Undefined property: Illuminate\Database\Eloquent\Collection::$id
If I echo $facilities->photos I end up with.
[{"id":"3",
"name":null,
"location":"facilities\/facility1.jpg\r",
"created_at":"2013-07-18 14:15:19",
"deleted_at":null,
"updated_at":null,
"pivot":{"facility_id":"5","photo_id":"3"}}]
Whats the best way to access any property in this array?
With eager loading the photos you get a photos collection and in order to get the photo you need to iterate through the photos collection e.g.
foreach($facilities as $facility)
{
foreach($facility->photos as $photo)
{
echo $photo->id;
}
}
If you only want just the first photo you can get it by calling the first() method on the collection
foreach($facilities as $facility)
{
$facility->photos->first()->id;
}
What is received from the database is an array with one object. This is why a foreach works. To access it the way you want you should add the first() method just as Atrim says, you can even drop the get() method. Only I would suggest doing it in the controller.
$facilities = Facility::with('photos')->first();
{{ $facilities->location }}
Thanks Altim, I just hit this problem too and the nested foreach is one of the solutions.
Nevertheless, I'll share with you guys the solution that I used at the end.
Instead of the nested foreach or even the eager loader, I used a Join Query Builder. In my case:
$posts = DB::table('posts')
->leftJoin('users', 'posts.user_id', '=', 'users.id')
->get();
This allowed me to use one foreach, and all the data is at the same level, in my case for instance would be something like:
#foreach ($posts as $post)
<p>{{ $post->first_name }}</p> # From users table
<p>{{ $post->title }}</p> # From posts table
<p>{{ $post->body }}</p>
#endforeach
Maybe it is not answering this question exactly , but hope it helps to others like me that ended up in this particular question.

Categories