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

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.

Related

How to organize Laravel ORM for relationships table

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:

Defining relations on same table Laravel 5.3

I have a refferal system in my application.ie, One user can reffer other.
Users table
id name
1 A
2 B
3 C
Referrals table
id referrer_id referee_id
1 1 2
2 2 3
I want to show the referrals made by a user.
User Model
public function referrals()
{
return $this->hasMany('App\Models\Referral','referee_id','id');
}
Referral Model
public function referrer_user()
{
return $this->belongsTo('Modules\User\Models\User','referrer_id','id');
}
public function referee_user()
{
return $this->belongsTo('Modules\User\Models\User','referee_id','id');
}
Defining hasMany relationship in User model and belongsTo relationship in Referrals Model, I'am not getting the desired result.
#foreach($user->referrals as $key => $referral)
{{dd($referral->referee_user->name)}}
#endforeach
This returning me the name of user itself(referrer) not the referee
You are referring the ManyToMany relationship the wrong way.
Anyways, it'll be much easier and efficient the following way.
id name referred_by
1 abc null
2 def 1
3 gfd 2
User Model
/**
* Who did he bring onboard?
*/
public function referrals(){
return $this->hasMany('....User', 'referred_by');
}
//Who brought him onboard..
public function referree(){
return $this->belongsTo('...User', 'referred_by');
}
Just check out the appropriate syntax.

Laravel eloquent use id from one table to search junction table?

So I have 3 tables
-Business
- id
-Address
- id
-business_address
- business_id
- address_id
And now at the moment when I go into a view business page I pass business->id from business table as $id:
public function displayBusiness($id) {
$business = Business::find($id);
$address = Address::find($id);
Which works absolutely fine at this moment but what if address has a different id?
so:
-Business
- id = 1
-Address
- id = 2
-business_address
- business_id = 1
- address_id = 2
So how can I modify that so that when id in business table = 1 it goes into business_address and find matching address id and bring back records that match it
What you should have is a relationship. So in your Business model you'd add the following.
public function addresses() {
return $this->belongsToMany(Address::class, 'business_address', 'address_id', 'business_id');
}
Then in your Address model you'd have the following.
public function addresses() {
return $this->belongsToMany(Business::class, 'business_address', 'business_id', 'address_id');
}
With this, you can now do the following.
public function displayBusiness($id) {
$business = Business::with('addresses')->find($id);
}
Then you access addresses by doing $business->addresses.
This is all based on what you currently have, so I'm assuming that one Address can belong to several Business. If this should not be the case, you'll need to refactor your relationship and database, as the pivot table isn't needed.

How to do complicated query SQL in Laravel?

I use three entities: user, categories, user_categories, articles, articeles_category
Each user can be subscribe on some categories, so table user_categories will be:
user_category
id user_id category_id
1 1 1
articles_category
id article_id category_id
1 1 1
articles
id name
1 Bla
So, I need to select all articles where articeles_category that correspond to the categories on user subsribed in table user_categories.
I tried this:
Articles::with("categories")->with("publisher.categories")->where("user_id", 1);
public function categories()
{
return $this->hasMany("App\ArticlesCategory", "article_id", "id");
}
public function publisher()
{
return $this->hasOne("App\User", "id", "user_id");
}
I have some ideas.
At first join tables:
user_categories with articeles_category by conditions:
user_categories.category_id = articeles_category.id AND user_categories.user_id = 4
Second is:
Select articles from Articles join with previous query.
Third is
To make global where by user_id
If your models are linked from users to categories to articles, you can do:
$categories = $user->categories()->with('articles')->get();
Then group them under the same collection (if you want):
$articles = $categories->map(function($category){
return $category->articles;
});
Alternatively, if you do not have the user instance:
$user = User::find($user_id)->with('categories.articles').->get();
See eager loading: https://laravel.com/docs/5.4/eloquent-relationships#eager-loading

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.

Resources