Laravel - Eloquent Joins - laravel

I'm just starting to learn laravel and its orm system, Eloquent. I'm not sure how to correctly join tables with it though. I have 3 models: User, Account, AccountType and I don't know how to join Account with Accounttype.
Account Model Class:
public function accounttype(){
return $this->hasOne('AccountType');
}
This is to pass accounts information to view:
$accounts = User::find(Auth::user()->id)->accounts;
$accounts->load('accounttype');
return View::make('accounts.accounts')->with('accounts', $accounts);
That will give the following error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'accounttypes.account_id' in 'where clause' (SQL: select * from accounttypes where accounttypes.account_id in (1, 2, 3))
It should be pulling by id in the accounttypes table not account_id. I can list the user accounts just fine, I just don't know how to join the accounttypes table to the account table.
Database Tables:
Users
id
username
password
timestamps(updated_at / created_at)
Accounts
id
name
user_id
accounttype_id
timestamps
AccountTypes
id
name
Each user can have more than one account and each account will have an account type.

In User model:
public function accounts()
{
return $this->hasMany('Account');
}
In Account model:
public function user()
{
return $this->belongsTo('User');
}
public function accountType()
{
return $this->belongsTo('AccountType', 'accounttype_id', 'id');
}
In AccountType model:
public function accounts()
{
return $this->hasMany('Account', 'accounttype_id', 'id');
}
Then in your Controller:
// This will return a user with all accounts ($user->accounts will be collection)
$user = User::with('accounts')->find(Auth::user()->id);
Or:
$user = User::with('accounts.accountType')->find(Auth::user()->id);
// You may pass the $user as well and then loop the $user->accounts in view
return View::make('accounts.accounts')->with('accounts', $user->accounts);
In your view you may loop to get all accounts like:
#foreach($accounts as $account)
{{ $account->name }}
{{ $account->accountType->name }}
#endforeach
Since $user->accounts is a collection so you may either run a loop or specifically get an account using something like this:
{{ $accounts->first()->name }}; // Get first one's name
{{ $accounts->get(0)->name }}; // Get first one's name
{{ $accounts->get(1)->name }}; // Get second one's name
{{ $accounts->last()->name }}; // Get last one's name
if you pass the $user instead of $accounts like this:
return View::make('accounts.accounts')->with('user', $user);
Then change the loop as well, like this:
#foreach($user->accounts as $account)
{{ $account->name }}
{{ $account->accountType->name }}
#endforeach
You can make sure if that user has accounts in the view before you start the loop, like:
#if($user->accounts->count())
// Loop Here
#endif

Related

How to make this Eloquent relationship in Laravel

I have a table called users with a column username. Another table called students with a column code. I have made a hasMany relationship in User model like below and it's working fine.
public function students()
{
return $this->hasMany(Student::class,'code','username');
}
I have another table called institutes where a column is similar to students table named inst. I need to show data from institutes table while showing data of an user. How to make this relationship?
users table
username|mobile|address|password
students table
username|name|inst|roll|reg
institutes table
name|inst|address|phone
This is my home controller
public function index()
{
$admins = User::where('username','=',Auth::user()->username)->get();
return view('home', compact('admins'));
}
And this is my view
#foreach($admins as $key => $admin)
#foreach($admin->students as $student)
{{ $student->reg }}
#endforeach
#endforeach
Add migration to your Students table :
$table->unsignedBigInteger('user_id')->nullable();
$table->foreign('user_id')->references('id')->on('users')->onUpdate('cascade')->onDelete('set null');
Update your model User on students method :
return $this->hasMany(Student::class);
Add "with method"
$admins = User::where('username','=',Auth::user()->username)->with('students')->get();

How to access other fields on a three way pivot in Laravel?

Here's what my architecture looks like:
The idea is that a user have a role on a given group. Of course, the user belongs to many groups, and a user can have multiple roles (in different groups)
I'm trying to get all the groups a user belongs to.
Please forgive me for not using the convention to name the pivot table as groups_roles_users, I decided this way for readability.
So, in the User model I say:
public function groups() {
return $this->belongsToMany('\App\Group', 'roles_in_groups');
}
In a view I do:
#foreach ($user->groups as $group)
{{ $group->name }}
#endforeach
works perfectly.
Now I want to access the roles table. I want to print something like: In {{ $group->name }} you're a {{ $group->role->name }}, obviously, It doesn't work like that.
If I use the pivot property, it will give me only the user_id and group_id, not even the role_id to search with an static method.
SO, how can I accomplish that?
I'm using Laravel 5.7
Maybe try:
public function roles() {
return $this->belongsToMany('\App\Role', 'roles_in_groups');
}
$user = \User::with(['roles','groups'])->first();
$role_name = $user->role->name
$group_name = $user->group->name
https://laravel.com/docs/5.7/eloquent-relationships#eager-loading

How to retrieve user name from user table by using data (user_id) from another table having relationship

I have two models
User.php
public function opportunities()
{
return $this->hasMany('App\Opportunity');
}
Opportunity.php
public function user()
{
return $this->belongsTo('App\User');
}
I have user_id column in opportunities table and inserted user id (from user table using Auth) every time user posts record.
Now i need a view to return "this post is posted this user".
First I find the post id by
$posts = Opportunity::find($id);
$posted_by = User::find($posts->user_id);
return view('opportunity.detail')->with('post', $posts, 'posted_by', $posted_by);
I have rendered user name by {{$posted_by->name}}
But I got undefined constant in the view file $posted_by while $post is fine. Am I doing it in right way or not? I am passing two array variable to the post and its not working. Any help will be appreciated.
Your controller could look like:
return view('opportunity.detail', [
'post' => Opportunity::find($id);
]);
In the view to show user name:
Post {{ $post->title }} posted by {{ $post->user->name }}
https://laravel.com/docs/5.5/eloquent-relationships#relationship-methods-vs-dynamic-properties
If for some reason you want to use ->with(), do this:
->with(['post' => $posts, 'posted_by' => $posted_by]);
Or:
->with('post', $posts)->with('posted_by', $posted_by);
You can put this
public function getUserName() {
return User::where('id', $this->user_id)->first()->name;
}
in your Opportunity.php model and call it in you view
#foreach ($posts as $post)
{{ $post->getUserName() }}
#endforeach

Laravel Many To Many Method Issue

I have a many to many relationship between the models User & Notification.
User Model:
public function notifications()
{
return $this->belongsToMany('Yeayurdev\Models\Notification', 'notifications_user', 'user_id', 'notification_id')
->withPivot('notifier');
}
Notification Model:
public function user()
{
return $this->belongsToMany('Yeayurdev\Models\User', 'notifications_user', 'notification_id', 'user_id');
}
Pivot Table:
ID USER_ID NOTIFICATION_ID
1 2 1
In my view, I retrieve a list of all notifications for a user like so.
#foreach (Auth::user()->notifications as $notification)
{{ $notification->user->username }}
#endforeach
The problem is that when I try to get the username of the user with that notifications, I get the error Undefined property: Illuminate\Database\Eloquent\Collection::$username. "Username" is the column on my users table which is just a string. I don't see where I'm going wrong because if I just do "$notificatin->user" it gives me the collection.
Thanks!
As you said, the relationship is many-to-many, so $notification->user in your case is returning a collection of User models, NOT a single user. If you need only a first user then just do
{{ $notification->user()->first()->username }}
If you need to print out all users for every notification, then you will need a loop here to go through all users.
#foreach (Auth::user()->notifications as $notification)
#foreach($notification->user as $notificationUser)
{{ $notificationUser->username }}
#endforeach
#endforeach
I would recommend renaming user() relationship to users() to avoid confusion in the future.

Laravel - oneToMany returning Undefined property

I just searched for this problem in all posts but i cant get the answer.
I have 3 tables: users | categorys | sectors with the below model:
User.php
public function categorys(){
return $this->hasMany('Category');
}
Category.php
public function user(){
return $this->belongsTo('User');
}
public function sectors(){
return $this->hasMany('Sector');
}
Sector.php
public function category(){
return $this->belongsTo('Category');
}
Tables
users:
id,name
categorys:
id,name,user_id(fk)
sectors:
id,name,category_id(fk)
I want to print in a view all the sectors from authenticated user, with something like this:
$user = new User;
$user = Auth::user();
$sectors = $user->categorys->sectors;
and use this in $sectors variable in view
#foreach($sectors as $sector)
{{ $sector->id }}
{{ $sector->name }}
#endforeach
But i get this error:
Undefined property: Illuminate\Database\Eloquent\Collection::$sectors
Need help! Thanks
BR
Either you forgot to mention it in your article, or the sector_id field is missing in the categorys table.
According to your database structure there is no foreign key from table categorys to table sectors
As i mentioned before here is the answer for the above issue.
The hasmanythought relation is the correct way to relate and easy query thouse 3 tables.
For model User.php you need to create the relationship:
public function sectors(){
return $this->hasManyThrough('Sector','Category');
}
Now in your controller you need to do:
$user = new User;
$user = Auth::user();
$sectors = $user->sectors;
#return the view showsectors
return View::make('showsectors')->with('sectors', $sectors);
Use this variable (sectors) to print the query result (all sector's descriptions from one user) in your view, with something like the below:
#foreach($sectors as $sector)
{{ $sector->id }}
{{ $sector->description }}
#endforeach
Thanks for helping with this.
BR

Resources