Eloquent Relationship on the same model - laravel

I am using the User model and want to reference other users on a One to Many relationship.
With two models, this would be done by a Many to Many but this attempt at it is obviously wrong:
public function relatedUsers()
{
return $this->belongsToMany(User::class, 'related_user', 'user_id', 'user_id');
}
Is there a better way I can achieve my goal? I don't need an inverse method.

You can use hasMany() or belongsTo() (according to your need) relation for same model relationship
Define hasMany relationship in User model:
public function relatedUsers() {
return $this->hasMany('User','user_id');
}
Example:
Consider you have one User object
$user = User::where('id',$id)->first();
If you want to access related records
$related_users = $user->relatedUsers; // this will return all related users for particular object

Related

access relation inside hasMany relation

I have a model request.php has this relation :
public function requestItems(): HasMany
{
return $this->hasMany(RequestItemd::class, 'request_id', 'id');
}
inside this relation there is another relation
public function item()
{
return $this->belongsTo(Item::class, 'item_id', 'id');
}
how to reach to belongsTo relation and retrieve data through the original hasMany relation?
You will need to loop over your items or get the individual item, something like this:
$requestItemsQuery->each(function($reqestItmId) {
$item = $reqestItmId->item;
});
there are a few other ways of doing this though, so if you share how you are planning to use the reference i might be able to give a better answer

How to define multiple belongsTo in laravel

My table has many foreign key for example prefecture_id, gender_id and status_id.
And I made model for those table.
So I want to define multiple belongsTo method like following for get all data with query builder..
But In fact belongsTo can't use like this.
public function foreign(){
return $this->belongsTo([
'App/Prefecture',
'App/Gender',
'App/Status',
]
}
And if the only way is defining multiple method for belongs to.
How do I get all belongstos data in querybuilder.
Please give me advice.
As far as I am aware, there's not a way to get multiple belongsTo from a single method. What you have to do is make one method for each relationship and when you want to load the relationships you can do the following.
Model
public function prefecture()
{
return $this->belongsTo(\App\Prefecture::class);
}
public function gender()
{
return $this->belongsTo(\App\Gender::class);
}
public function status()
{
return $this->belongsTo(\App\Status::class);
}
Query
// This will get your model with all of the belongs to relationships.
$results = Model::query()->with(['prefecture', 'gender', 'status'])->get();

Laravel detaching HasManyThrough relationships with ease

SCENARIO
Let's say that there's a system where companies could add other companies to their list of favorites. To fetch this record I would do something like the following:
// Returns a list of favorite companies for the current user's company
$user->company()->favorites;
Note that the favorites represent the hasManyThrough relationship.
public function favorites()
{
return $this->hasManyThrough(Company::class, CompanyFavorite::class, 'company_id_owner', 'id', 'id', 'company_id_selected');
}
IDEAL SOLUTION I'm looking for a solution where I could remove the record from the intermediary relationship table making use of the hasManyThrough object. Example:
$user->company()->favorites()->detach([...companies_ids]);
HasManyThrough is not the right relationship here, use BelongsToMany instead:
public function favorites()
{
return $this->belongsToMany(
Company::class, 'company_favorites', 'company_id_owner', 'company_id_selected'
);
}
This relationship provides all the necessary methods like attach() and detach():
$user->company()->favorites()->detach([...companies_ids]);

Eloquent hasOne vs belongsTo degenerate to same function if both keys are specified?

For the case of a one-to-one relationship, if I fully specify the keys in the method calls, is there a difference between hasOne and belongsTo relationships? Or, asked differently, if I used hasOne on both sides of the relation, would it be the same result?
Yes it works for some cases to specify the keys and make the relation work. And with some cases I mean mainly retrieving results. Here's an example:
DB
users profiles
----- --------
id id
etc... user_id
etc...
Models
Using "wrong" relations with hasOne twice
class User extends Eloquent {
public function profile(){
return $this->hasOne('Profile');
}
}
class Profile extends Eloquent {
public function user(){
return $this->hasOne('User', 'id', 'user_id');
}
}
Queries
Let's say we wanted to get the user from a certain profile
$profile = Profile::find(1);
$user = $profile->user;
This is working. But it's not working how it's supposed to be. It will treat the primary key of users like a foreign key that references user_id in profiles.
And while this may work you will get in trouble when using more complicated relationship methods.
For example associate:
$user = User::find(1);
$profile = Profile::find(2);
$profile->user()->associate($user);
$profile->save();
The call will throw an exception because HasOne doesn't have the method associate. (BelongsTo has it)
Conclusion
Whereas belongsTo and hasOne may behave similar in some situations. They are clearly not. More complex interactions with the relationship won't work and it's nonsense from a semantic point of view.

Laravel - Pivot table for three models - how to insert related models?

I have three models with Many to Many relationships: User, Activity, Product.
The tables look like id, name. And in the each model there are functions, for example, in User model:
public function activities()
{
return $this->belongsToMany('Activity');
}
public function products()
{
return $this->belongsToMany('Product');
}
The pivot table User_activity_product is:
id, user_id, activity_id, product_id. The goal is to get data like: User->activity->products.
Is it possible to organize such relations in this way? And how to update this pivot table?
First I suggest you rename the pivot table to activity_product_user so it complies with Eloquent naming convention what makes the life easier (and my example will use that name).
You need to define the relations like this:
// User model
public function activities()
{
return $this->belongsToMany('Activity', 'activity_product_user');
}
public function products()
{
return $this->belongsToMany('Product', 'activity_product_user');
}
Then you can fetch related models:
$user->activities; // collection of Activity models
$user->activities->find($id); // Activity model fetched from the collection
$user->activities()->find($id); // Activity model fetched from the db
$user->activities->find($id)->products; // collection of Product models related to given Activity
// but not necessarily related in any way to the User
$user->activities->find($id)->products()->wherePivot('user_id', $user->id)->get();
// collection of Product models related to both Activity and User
You can simplify working with such relation by setting up custom Pivot model, helper relation for the last line etc.
For attaching the easiest way should be passing the 3rd key as a parameter like this:
$user->activities()->attach($activityIdOrModel, ['product_id' => $productId]);
So it requires some additional code to make it perfect, but it's feasible.
The solution was found with some changes.
In the models relationships look like:
// User model
public function activities()
{
return $this->belongsToMany('Activity', 'user_activity_product', 'user_id', 'activity_id')->withPivot('product_id');
}
public function products()
{
return $this->belongsToMany('Product', 'user_activity_product', 'user_id', 'product_id')->withPivot('activity_id');
}
To update pivot table:
$user->products()->save($product, array('activity_id' => $activity->id));
- where product and activity ids I get from Input.
And, for example, to check if "user -> some activity -> some product is already exists":
if ($company->activities->find($activity_id)->products()->where('product_id', '=', $product_id)->wherePivot('company_id', $company_id)->get()->count() > 0) {
// code...
}
I think it needs improvements but it works for me now.

Resources