query builder returns array instead of collection - laravel

User.php(User model)
class User extends Authenticatable
{
public function profiles(){
return $this->hasOne('App\Profile');
}
}
Profile.php (Profile model)
class Profile extends Model
{
public function users(){
return $this->belongsTo('App\User');
}
}
Function which returns data to view:
public function show_users(){
$users = User::where('id','!=',Auth::user()->id)->get();
return view('pages.show_users')->withUsers($users);
}
show_user.blade.php(View)
#foreach($users as $user)
{{$user->profile->first_name}} //Gives error:Trying to get property of non-object
{{$user->profiles['first_name']}} // Gives desired result
#endforeach
Why the result is returned in array instead of collection?

The reason that you are getting that error is beacause
Some users might not have a profile. so calling first_name on profile which is a null object will throw an error.
What you can is on php7 you can do
#foreach($users as $user)
{{$user->profiles->first_name ?? 'No first name'}}
#endforeach
php 5.6 and below
#foreach($users as $user)
#if($user->profiles->isNotEmpty())
{{$user->profiles->first_name}}
#else
No name
#endif
#endforeach
And moreover why don't use eager loading to load your profiles for performance benefit. Your query now will create the N+1 query problem.
You can change your query to
public function show_users()
{
$users = User::with('profiles')->where('id','!=',Auth::user()->id)->get();
return view('pages.show_users')->withUsers($users);
}
Hope it helps

The result returned is indeed a collection. It is just a typo issue
You forget an s here in profiles
{{ $user->profiles->first_name }}
Also please note that even if you access first_name as such
{{ $user->profiles['first_name'] }}
It doesn't mean it is not a collection.
If you check the source of Illuminate\Database\Eloquent\Model.php, you will see that it implements some cool functions such as offsetGet, offsetSet, and offsetExists
More information here. PHP ArrayAccess

Related

one to may relationship, Display all post along with there users

//Post table
user()
`belongsTo(User::class);`
//user table
posts()
hasMany(post::class);
//I want to get all the post available in the DB, Display along with the users associated with the post.
Use foreign key and primary key in relationships to get the results.
In Post
public function user()
{
return $this->belongsTo('App\User','users_id','users_id') //first parameter-foreign key,second parameter-local key
}
In User
public function posts()
{
return $this->hasMany('App\Post','users_id','users_id')
}
Now get all the posts using
$posts = Post::get();
return view('your-view')->with('posts',$posts);
You can retrieve user information in view using
#foreach($posts as $post)
$user = $post->user->name;
#endforeach
Hope it helps..
Guessing your relations look like this:
User:
public function posts()
{
return $this->hasMany('App\Post');
}
Post:
public function user()
{
return $this->belongsTo('App\User')
}
You could get all the posts in your controller, like this:
$posts = Post::get();
return view('your view', $posts);
And in your blade, to display posts and their users, do it like this:
#foreach($posts as $post)
$post->user->name
#endforeach
$posts = Post::with('user')->get();

How to use index method to display a listing of the resource in Laravel

I created a customerController with Laravel resource. Now I want to show the list of the customers from the database using the index() method and it doesn't work when I visit the customer/index route. However if use the show() method instead and visit the customer/show route, it works perfectly.
Why does this behave this way and how do I get the index() method to do this?
class CustomerController extends Controller
{
public function index()
{
$customers = Customer::all();
return view('customer')->with('customers' , $customers);
}
public function show($id)
{
// adding the code in the index() method here makes the code run
// as expected
}
}
customer.blade.php
<ul>
#foreach($customers as $customer)
<li>{{$customer->name}}</li>
#endforeach
</ul>
routes/web.php
Route::resource('customer' , 'CustomerController');
I expect the output to be:
.sucre
.hameed
.micheal
I just learned how to use resource on Laravel 8.
Which version are you using?
Run php artisan route:list on your console to see every route available and their names.
To see all customers through your index function do the following:
public function index()
{
$customers = Customer::all();
return view('customer', [
'customers' => $customers
]);
}
Now just access your customer.blade.php file on browser.
PS: Don't forget of #foreach
#foreach ($customers as $customer)
{{ $customer->attribute }}
#endforeach
Hope this could be useful.

Get username from ID

I have a blade template in a Laravel 5.5 app that is returning a user ID integer
I am looking for a way to get the users name from that value within the blade template
The value is just saved in the table and there is no relationship setup, is there a way to get the username without having to set up a relationship?
** UPDATE **
My products controller looks like this...
public function index()
{
$users = User::all();
$products= Product::all();
return view('products.index',compact('products', 'users'));
}
So now I have the users available inside the blade template but now I need to get the user from the id that is contained in produts
In your controller that's passing the user data to the view, you can either pass the entire $user object and print it in your view like {{ $user->name }} or set yourself a variable that holds just the username and pass that in for however you're using it.
I would do the first one though, something like:
public function index()
{
$user = User::where('id',$id)->firstOrFail();
return view('dashboard.index', compact('user'));
}
Or if you're getting all users from the database, an example would be:
public function index()
{
$users = User::all();
return view('dashboard.index', compact('users'));
}
Then in your view you can do
#foreach($users as $user)
{{ $user->name }}
#endforeach
Edit
Since seeing your updated question, you would benefit from making a relationship between your users and your products. So, you would say that a user has many products and that a product belongs to a user.
class User extends Model
{
/**
* Get all of the products for the user.
*/
public function products()
{
return $this->hasMany('App\Product');
}
}
And then
class Product extends Model
{
/**
* Get the user that is assigned to the product
*/
public function user()
{
return $this->belongsTo('App\User');
}
}
Once you have set this up, you can loop through your products and get the username like this:
#foreach($products as $product)
{{ $product->user->name }}
#endforeach
Create helper file: follow this rule to make it : https://laravel-news.com/creating-helpers
and make one function like this:
function getUsername($uerId) {
return \DB::table('users')->where('user_id', $userId)->first()->name;
}
and call this function from your view like this :
{{getUsername($id))}} //it will print user name;
{{\App\User::findOrFail($id)->name}}
Auth::user()->name if user is online. if not you must have controller function like:
$users = User::all();
and in blade
#foerach($users as $user)
{{$user->name}}
#endforeach

Laravel Eager Loading and dynamically bind model relationship

Laravel version: 5.3
In my User model class i have a method like :
public function hasOneRelation($model)
{
return $this->hasOne($model);
}
And then i call this method like below code:
User::hasOneRelation('App\Client')->first();
i got the correct value but is there any N+1 problem.....
There is no way to eager load this dynamic relationship, so if you attempt to use this relationship in a loop, yes, you will end up with an N+1 problem.
You shouldn't have any N+1 issue here because you won't be calling that as a property of a model. That and just stay away from calling that in a loop on your model. You get the N+1 issue if you were to do something like:
//User Model
public function contract()
{
return $this->hasOne(Contract::class);
}
//Controller
public function index()
{
$users = User::all();
return view('users.index', compact('users'));
}
//View
<ul>
#foreach($users as $user)
<li>{{$user->contract->type}}</li>
#endforeach
</ul>
Loading the relation on each model within a loop instead of lazy loading it like:
//Controller
public function index()
{
$users = User::with('contract')->get();
return view('users.index', compact('users'));
}
Yes you just face N+1 problem. Read laravel official doc https://laravel.com/docs/5.3/eloquent-relationships#eager-loading

Access an attribute through Laravel relationship

I would like to get the ID of a house related to a user but I get the famous Trying to get property of non-object error.
In my index.blade.php I use
{{ $user->house->id }}
User.php
public function house()
{
return $this->hasOne('App\House');
}
House.php
public function user()
{
return $this->belongsTo('App\User');
}
What should I do ?
Be sure that the user has house object. Try this:
#if ($user->house)
{{ $user->house->id }}
#endif

Resources