I have three models creating a many-to-many relationship
ModelA(id)
ModelB(A.id,C.id)
ModelC(id,name)
How to fetch C.name using model A?
Currently model A hasOne model B, and model C hasMany model B. I tried to relate model A and C using hasOnethrough using model B but it gives me null.
public function myFunction()
{
return $this->hasOnethrough(ModelC::class, ModelB::class,
'a_id', 'id', 'id', 'c_id');
}
Based on your question ModelB is your pivot model to handle your relationship.
Normally we use pivot tables for many-to-many relationships, in that case you can use the hasManyThrough method.
You can try the above function in your ModelA model like you asked and will link to modelC through the ModelB
Then you can fetch it like a normal relationship output.
Related
I have two collections (films and actors) in films collection I have column actor_ids which contains actors ids like this
actors: ["62ced094c68f1d2da30de05d", "62cedf86c68f1d2da30de061"] and I want to create relationship between films and actors.
I define hasMany in films model
public function producer(): HasMany
{
return $this->hasMany(Actor::class);
}
And BelongsTo relation in actor model
public function films() : BelongsTo
{
return $this->belongsTo(Film::class);
}
But as result of $film->actors I get empty array.
Please help how to get data.
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
I would like to obtain for ONE user his country. So I have two tables:
User
id
country_id
Countries
id
I can't decide which relationship to use. I think it is the OneToMany relationship (Inverse) but it implies that the Countries table has the user id.
I can't understand how to use the oneToMany relationship in this case...
Docs link: https://laravel.com/docs/6.x/eloquent-relationships#one-to-many-inverse
One To Many (Inverse)
Now that we can access all of a post's comments, let's define a relationship to allow a comment to access its parent post. To define the inverse of a hasMany relationship, define a relationship function on the child model which calls the belongsTo method:
You need to create a belongsTo to relation on your user model.
class User extends Model
{
public function country()
{
return $this->belongsTo('App\Country');
}
}
I have 3 tables.
shops
shop_foods
foods
I need to fetch foods table data when I create hasmany relation with shops_food and store.
$this->hasMany('App\Diet\ShopFood', 'shop_id', 'id');
Please, show your code so we can know what are you trying to do.
But what I can see here is that you have a wrong relationship.
Why are you assigning hasMany in a Many to Many relationship?
In your Shop Model you can make a foods relationship with:
$this->belongsToMany('App\Diet\Food);
Then you can retreive you food when calling
$shop->foods
And the shop_foods with the Pivot property
If i understand correctly you want to get foods when you call shops->shop_foods. if is that
//first you call your shops as you want.
Shop::with(['shops_food' => function($query){
//the 'shops_food' relationship should be called within an array
//this way you could query the relationship as the eloquent model.
//that way you could call the 'foods' relationship inside the shops_food relationship.
$query->with('foods')
}])
...
Note that you must have the relationship declared in shop and shop_foods models
lets your models are like these
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Shop extends Model
{
//
public function shops_food()
{
//shop_id is the foreing key inside your shop_foods table
return $this->hasMany('App\ShopFood','shop_id');
}
....
}
then ShopFood Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ShopFood extends Model
{
//
public function foods()
{
//shop_food_id is the foreing key inside your foods table
return $this->hasMany('App\Food','shop_food_id');
}
....
}
This reads as if you want
public function foods() {
$this->hasMany('App\Diet\Food');
}
in your ShopFood model and in your Shop model
public function shopfoods() {
$this->hasMany('App\Diet\ShopFood')->with('foods');
}
You can also make 2 separate relations in the Shop model:
public function shopfoods() {
$this->hasMany('App\Diet\ShopFood');
}
public function shopfoodsWithFoods() {
$this->hasMany('App\Diet\ShopFood')->with('foods');
}
So that way you can use whatever you need at that moment.
But the whole thing is really not clear...
I am not even sure how the 3 table are connected, so the hasMany are just guesses.
Nevertheless you can just go with the "with" function.
PS
There is also the possibility to just declare
protected $with = ['foods'];
in your ShopFood model, if you ALWAYS want those 2 connected. It's all in the documentation.
I have Models A, B and C. A hasOne relationship with B and B hasMany relationship with C.
//Model Code
class A extends Model
{
//This relates A and B
public function relateBC(){
return $this->hasOne('App\B','aid','aid');
}
}
class B extends Model
{
//Inverse relationship with Model A
public function relateBC(){
return $this->belongsTo('App\A','aid','aid');
}
//This relates B and C
public function relateBC(){
return $this->hasMany('App\C','bid','bid');
}
}
class C extends Model
{
//Inverse relationship with Model B
public function post(){
return $this->belongsTo('App\B','bid','bid');
}
}
Below code return data from Model B
App\A::find(id)->relateAB()->get();
Below code return data from Model C
App\B:find(id)->relateBC()->get();
The below code throw BadMethodException. Method relateBC() does not exist.
App\A::find(id)->relateAB->relateBC()->get();
.
Try this:
$distantRelations = App\A::find($id)->relateAB->relateBC;
When accessed as a method (i.e. ->relateAB()), you get back the HasOne relationship object (the object you can call ->get() on), whereas when accessed as a magic property (i.e. ->relateAB), you get back the model instance (the object you can access relationship relateBC) on.
You could use the method instead of the magic property, but keep in mind that you are then the one who has to determine the relation type (one vs. many), and call either ->get() or ->first() on the underlying query builder respectively:
$distantRelations = App\A::find($id)
// 'relateAB' is a singular relation,
// so we'll need to call 'first()'
->relateAB()->first() // > App\B
// 'relateBC' is a 'many' relation,
// so we'll need to call 'get()'
->relateBC()->get(); // > App\C[]|\Illuminate\Support\Collection
HasOne calling first()
You can witness HasOne calling first() for you on the query builder at this line, executed by accessing the relation as magic property.
HasMany calling get()
You can witness HasMany calling get() for you on the query builder at this line, executed by accessing the relation as magic property.
declared primary key of A model and B model in Pivot table i.e. as foreign key of both the tables