lumen/laravel Eloquent hasManyThrough 3 models relation - laravel-5

I try to acomplish a relation with 3 models:
Cities.php //table cities
id
name
Neighbourhoods.php //table neighbourhoods
id
name
city_id
Blocks.php //table blocks
id
name
neighbourhood_id
My models looks like this:
Cities.php
public function neighbourhoods()
{
return $this->hasManyThrough('App\Neighbourhoods', 'App\Blocks', 'neighbourhood_id', 'city_id', 'id');
}
Neighbourhoods.php
public function blocks()
{
return $this->hasMany('App\Blocks', 'neighbourhood_id', 'id');
}
Blocks.php
public function neighbourhoods()
{
return $this->belongsToMany('App\Neighbourhoods', 'neighbourhood_id', 'id');
}
The result shoud be:
results
city1:
neighbourhoods:
neighbourhood1:
block1
block2
block3
neighbourhood2
block1
block2
city2:
neighbourhoods:
neighbourhood1:
blocks:
block1
block2
block3
neighbourhood2:
blocks:
block1
block2
Calling the results:
return Blocks::with('neighbourhoods')->get();
I know that my models are not properly named. City (singular), Neighbourhood (singlar), Block (singular) but passing parameters shoud work.
I just can't figure our why it does not work.
RELATIONSSHIP SOLUTION based on #Gaurav Rai's response
First of all, my models are wrong named. Please condider naming your database using plurals for example: cities, neighbourhoods, blocks and your models singular for example: City.php, Neighbourhood.php and Block.php
Based on my problem, the solution is:
Cities.php
public function neighbourhoods()
{
return $this->hasMany('App\Neighbourhoods', 'city_id', 'id');
// because my model is called Cities.php,
// the function will look by default
// for the column cities_id in neighbourhoods table,
// thats why we need to specifiy city_id column
}
public function blocks()
{
return $this->hasManyThrough('App\Blocks', 'App\Neighbourhoods', 'city_id', 'neighbourhood_id', 'id');
}
Neighbourhoods.php
public function cities()
{
return $this->belongsTo('App\Cities', 'city_id', 'id');
}
public function blocks()
{
return $this->hasMany('App\Blocks', 'neighbourhood_id','id');
}
Blocks.php
public function neighbourhoods()
{
return $this->belongsTo('App\Neighbourhoods', 'neighbourhood_id');
}
Calling the relation:
return Cities::with(['neighbourhoods', 'blocks'])->get();

I think your relationships are not well defined:
Cities.php
public function neighbourhoods()
{
return $this->hasMany('App\Neighbourhoods');
}
public function blocks()
{
return $this->hasManyThrough('App\Neighbourhoods', 'App\Blocks');
}
Neighbourhoods.php
public function blocks()
{
return $this->hasMany('App\Blocks');//by default it will consider id
}
public function city()
{
return $this->belongsTo('App\City');
}
Blocks.php
public function neighbourhoods()
{
return $this->belongsTo('App\Neighbourhoods');
}

Related

Laravel get all products from parent category or subcategory using eloquent

I would like to retrieve all products of chosen parent category.Product model have hasmany relation to product_category_mapping table.
If product have subcategory result like,
"MAinCatergory":[
{
id="",
name:"Drinks",
"ChildCategory":[
{
"id":1,
"name":"Juce",
"Products":[{
name:"apple juce",
price:10,
....
}]
}
]
}
]
}
If product under main category only return array like,
"MAinCatergory":[
{
id="",
name:"Drinks",
"Products":[{
name:"apple juce",
price:10,
....
}]
}
}
]
}
category table fields - id,name,parent_id
product table fields - id,name,price,..,
product-category-mapping table fields - id,category_id,product_id
category model
public function children()
{
return $this->hasMany('App\Models\Category', 'parent_id');
}
public function parent()
{
return $this->belongsTo('App\Models\Category', 'parent_id');
}
public function product_category()
{
return $this->hasMany('App\Models\ProductCategoryMapping', 'category_id');
}
product model
public function product_category()
{
return $this->hasMany('App\Models\ProductCategoryMapping','product_id');
}
product-category_mapping
public function product()
{
return $this->belongsTo(Product::class,'product_id','id');
}
public function category()
{
return $this->belongsTo(Category::class,'category_id','id');
}
Something like this might suffice.
App\Models\Category::with('children', 'product_category.product')->get()
Suggestion, try implement pivot many to many relation instead this product_category_mapping, then model relation would change a bit.
For pivot relation, you need to modify the Category model
public function products()
{
return $this->belongsToMany('App\Models\Product', 'product-category-mapping');
}
and in product Model
public function categories()
{
return $this->belongsToMany('App\Models\Category','product-category-mapping');
}
Note:This is not the complete integration, but to give you an idea, for full logic see https://laravel.com/docs/9.x/eloquent-relationships#many-to-many
in your product model add like this:
public function product_categorys(){
return $this->hasMany('App\Models\ProductCategoryMapping','product_id');
}
and in controller you can get inside your function like this Product::with('product_categorys')->get();

Polymorphic BelongsTo relationship in Laravel

How could I set relationships to use just one table (model_types) in Laravel to store types for cars and bikes?
Car model
public function carTypes()
{
return $this->hasMany(CarType::class);
}
CarType model (inverse relationship):
public function car()
{
return $this->belongsTo(Car::class);
}
Bike model
public function bikeTypes()
{
return $this->hasMany(BikeType::class);
}
BikeType model (inverse relationship):
public function bike()
{
return $this->belongsTo(Bike::class);
}
There are 2 options I can think of to solve this problem, the first being a simple table using a type column and the other is using polymorphic relations which is a little overkill.
The first option is to have a type column on your model_types table which you could use to determine the type and adding constants in your ModelType class like this:
const TYPE_CAR = 1;
const TYPE_BIKE = 2;
Then you can easily access the data like so, so from the Car model it's
public function modelType()
{
return $this->belongsTo(ModelType::class)->where('type', ModelType::TYPE_CAR);
}
If you wanted to access it from the model_types table it would look like this:
public function cars()
{
return $this->hasMany(Car::class)
}
public function bikes()
{
return $this->hasMany(Bike::class)
}
You have it reversed.
A car can belong to one car type, but one car type can apply to many cars.
The same goes for bikes.
You don't need a polymorphic relationship.
Car model
public function carType()
{
return $this->belongsTo(ModelType::class);
}
Bike model
public function bikeType()
{
return $this->belongsTo(ModelType::class);
}
ModelType model
public function cars()
{
return $this->hasMany(Car::class);
}
public function bikes()
{
return $this->hasMany(Bike::class);
}
Not sure about inverse relationship, but in your Car model you should use
public function carTypes()
{
return $this->hasMany(ModelType::class, 'foreign_key', 'local_key');
}
Car Model:
public function carTypes() {
return $this->hasMany(ModelType::class);
}
Bike Model:
public function bikeTypes() {
return $this->hasMany(ModelType::class);
}
ModelType Model:
public function car() {
return $this->belongsTo(Car::class, 'modeltype_car_id');
}
public function bike() {
return $this->belongsTo(Bike::class, 'modeltype_bike_id');
}

How to access a relationship through another relationship

I am working on a survey system and I have a problem accessing one relationship through another.
I have these models and these relationships
Post
id
survey_id
public function survey()
{
return $this->belongsTo(Survey::class);
}
Surveys
id
survey_type_id
public function surveyOptions()
{
return $this->belongsToMany(Survey_options::class);
}
public function surveyType()
{
return $this->belongsTo(Survey_type::class);
}
public function posts()
{
return $this->hasMany(Post::class);
}
Survey_types
id
public function surveyOptions()
{
return $this->belongsToMany(Survey_options::class);
}
Survey_options
id
survey_type_id
public function values()
{
return $this->hasMany(Option_value::class);
}
options_values
survey_options_id
survey_id
public function surveyOptions()
{
return $this->belongsTo(Survey_options::class);
}
Survey_Survey_options (pivot)
survey_id
survey_options_id
I need to do a query with eadger loading to bring me all the posts with survey, surveyOptions, withCount comments y options_values of each surveyOptions. Something like this:
$post->survey->surveyOptions->options_values_count
I have managed to create this query that works for me everything except fetching the option_values count from each SurveyOption. How can I do it?
$posts = Post::with([
'survey' => function ($query) {
$query->withCount('totalSurveys');
},
'survey.surveyOptions',
'image',
'categories'
])
->withCount('comments')
->get();

Call to undefined relationship [person] on model [App\Note]

i have a notes, cards and person table wich notes table has card_id and person_id
now once i want load card data i alse want load person name's name but laravel give this error: Call to undefined relationship [person] on model [App\Note].
sorry my english is not good.
this my relationships:
notes:
public function card()
{
return $this->blongsTo(Card::class);
}
public function person()
{
return $this->blongsTo(Person::class);
}
cards:
public function notes()
{
return $this->hasMany(Note::class);
}
persons
public function notes()
{
return $this->hasMany(Note::class);
}
and this my action:
public function showCard(Card $card)
{
$card->load('notes.person');
return view('cards.card',compact('card'));
}
whats wrong?
You have a spelling mistake. Check the relationship, it says: ->blongsTo instead of belongsTo.
public function card()
{
return $this->belongsTo(Card::class);
}
public function person()
{
return $this->belongsTo(Person::class);
}

Laravel Retrieve related model through pivot table

So i'm a bit confused with this situation, I have the current relations:
User hasmany Favourite
favourites references to a Recipe model
favourites is a pivot table but when I retrieve the favourites for a given user like:
$user->favourites
i get the favourite with the pivot data, but I want to get the fields of the recipe
Recipe.php:
public function favourites()
{
return $this->hasMany('App\Favourite');
}
User.php:
public function favourites()
{
return $this->hasMany('App\Favourite');
}
Favourite.php:
public function user()
{
return $this->belongsTo('App\User','user_id');
}
public function recipes()
{
return $this->belongsTo('App\Recipe','recipe_id');
}
EDIT : there was no problem at all, just needed to call:
#foreach($user->favourites as $favourite)
{{ $favourite->recipe->name }}
#endforeach
You need to set your relation to Has Many Through instead of just has Many.
https://laravel.com/docs/5.2/eloquent-relationships#has-many-through
Recipe.php:
public function favourites()
{
return $this->hasManyThrough('App\Favourite', 'App\User');
}
User.php:
public function favourites()
{
return $this->hasManyThrough('App\Favourite', 'App\Receipe');
}
Favourite.php:
public function user()
{
return $this->hasManyThrough('App\User','App\Receipe');
}

Resources