How to organize Laravel ORM for relationships table - laravel

I have two table Users and Relationships. The table Relationships contains next fields:
id | user_one_id (fk to users) | user_two_id (fk to users) | status | action_user_id
The status field can be one of 4 values. 0 - pending, 1 - accepted, 2 - rejected, 3 - blocked.
Action user is those user who created or updated request. For example, user with id 1 want to be a friend with user with id 2. action_user_id will 1.
I can't organize relationships in my User model.
For example my method friends
public function friends()
{
return $this->belongsToMany(User::class, 'relationships', 'id', 'user_one_id')
->orWhere('user_two_id', $this->id);
}
creates next sql query:
select * from "users" inner join "relationships" on "users"."id" = "relationships"."user_one_id" where "relationships"."user_one_id" = ? or "user_two_id" = ?
but I understand that it is not i need.
What i need? I need 3 methods "friends", "requested" and "blackList".
The "friends" method must return all friends of current user. The "requested" method must return all friend requests to current user. And the "blackList" must return all users who are in the blocked status of current user.

Try using a where clause, based on the status to retrieve the particular data. I recreated the problem in a fresh laravel install, and I used the user class and a relationships table to reffer to two users in a relationship
//Model User: $user->friends gets the list of friends of the user
public function friends()
{
return $this->belongsToMany('App\User', 'relationships','friend_2','friend_1')->where('friendship_status','friends');
}
At the blade.php view:
#foreach(\App\User::all() as $user)
<h5>{{$user->name}}</h5>
#foreach($user->friends as $friends)
<div>
<small>Is friends with {{$friends->name}}</small>
</div>
#endforeach
#endforeach
Relationships table migration:
Schema::create('relationships', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('friend_1');
$table->unsignedbigInteger('friend_2');
$table->string('friendship_status')->default('request pending');
$table->timestamps();
});
Manually added relationships:

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();

foreach the data of relationship

I have two tables media_user and users
media_user table like [ id | user_id | media_id | link ]
I need to bring all user from media_user by relationship, so I created relation in user model:
/**
* that users belong to the media_user table.
*/
public function media()
{
return $this->hasMany('App\Models\Social_Media','user_id','id');
}
And in the view, I did this
#foreach ($user->media as $m)
// my data
#endforeach
I got the empty array when I dump the result as dd($user->media)
What is the problem pls?
The relation looks fine, please check
there are some media items for the user with a correct foreign key.
there is an attribute in the user table called media.
there is no global scope.
the $user is a valid object and belongs to the ORM model
I suggest installing debug bar and view executed query on the media table

Laravel 5 get name based on ID

I have a users and departments table. So my departments table might have a row like so
id | departmentName
----------------------
2 | Marketing
----------------------
And the users table might have something like
id | name | email | departmentId
-------------------------------------------------------
18 | Nick | nick#email.com | 2
-------------------------------------------------------
So the users table links to the departments table via the id.
So now onto my UserController, in the index function, I do
public function index()
{
$users = User::all();
return view('users.index', compact('users'));
}
Now that will display everything within my users table.
My problem is, I do not want to display the departmentId. I want to display the departmentName which is linked to that departmentID. So in the above example, my users index page for that one row should show Marketing, not 2.
How would I go about doing this?
Thanks
You can use Eloquent Relationships. What you described in your question is a One-to-Many Relation, meaning a department can have many users, and each user belongs to a department. So you'll need to setup a model for your departments table (if you haven't done so already) and then define the relationship in your User model like so:
class User extends Model
{
public function department()
{
return $this->belongsTo('App\Department', 'departmentId');
}
}
You can then access the department details in your view via that relationship:
#foreach ($users as $user)
{{ $user->department->departmentName }}
#endforeach

laravel one-to-many get data without inner join

I am trying to get a feel around the laravel ORM and I have the following models.
I have a:
user table with- id, firstname, lastname
city table with - id, name
usercity table with - user_id, city_id
The usercity table tracks the cities the user has visited.
I added the following in city model:
public function usercity()
{
return $this->hasMany('App\UserCity');
}
And another function in user model
public function usercity()
{
return $this->hasMany('App\UserCity');
}
I also added a model for UserCity and added following function there.
public function city()
{
return $this->belongsTo('App\City');
}
public function user()
{
return $this->belongsTo('App\User');
}
Now, the goal is to retrieve all the cities a user has visited. I used the following function.
$usercities = User::where('id','=',1)->first()->usercity()->get();
This works in the sense that it retrieves the user_id and city_id.
What would i need to do to get all the fields in the city table also?
Current response:
[[{"user_id":"1","city_id":"1"},{"user_id":"1","city_id":"2"},{"user_id":"1","city_id":"3"},{"user_id":"1","city_id":"4"}]]
I might be able to use inner join but I wanted to see if there was another way to retrieve the data which safely populates the data for me.
What you really have is a many-to-many relationship between users and cities, with the usercity table being the pivot table. Laravel uses the BelongsToMany relationship to implement this. You'll need to make a few changes to get this to work.
In your city model:
public function users() {
return $this->belongsToMany('App\User', 'usercity');
}
In your user model:
public function cities() {
return $this->belongsToMany('App\City', 'usercity');
}
You can get rid of the UserCity model. There is usually no reason to need a model for the pivot table.
The usercity table may need to be updated to add an id field as the primary key. I've not tried it without one, however, so it may work as you have it. Also, if you wanted, you could rename the table to city_user to conform to Laravel conventions, and then you wouldn't need to specify the table name in the relationship definitions.
Once your relationships are setup correctly, you can access a user's cities via the cities relationship on the user, and you can access a city's users via the users relationship on the city. For example:
// all of the cities visited by user 1
$user = User::find(1);
$usercities = $user->cities;
// all of the users that have visited city 1
$city = City::find(1);
$cityusers = $city->users;
You can find more information about the relationships in the documentation here.

Laravel Eloquent - many to many with where for the pivot table

I'm trying to see what the best way to do the following.
I have 3 tables: users, items and item_user.
users and items table are pretty generic, id and a few columns to hold whatever data.
item_user table has the following structure
id
item_id
user_id
user_type [ 1 - Owner | 2 - Follower | 3 - Something else ]
Relationships:
Each Item has 1 Owner (user type)
Each Item has many followers
Each User can own many Items
Each User can follow many Items
I would like to have the Owner and Followers be the Users table so I don't need to replicate user data. I created a pivot table of item_id, user_id and user_type to hold these relationships.
So the question is how to I do this in Laravel Eloquent?
Item Model looks like:
public function user() {
return $this->belongsToMany('Users');
// This isn't actually correct since it belongs to only one User but not sure how to specify a where user_type = 1;
// return $this->belongsTo('User');
}
User Model looks like:
public function item() {
return $this->hasMany('Item');
}
Thanks!
You can just append the condition to your belongsToMany declaration:
public function user() {
return $this->belongsToMany('Users')->where('user_type', 1);
}
This will return only the User entries that have user_type = 1 in your pivot table. And just to make it more clear you could name the method owner() instead of user() to reflect the added condition.

Resources