Laravel: 2nd level relationship only fetching single row - php

I am using Laravel 5.6 and I have relation between 3 tables. Cart->cartItem->Images
Here is my controller code:
$cart = Cart::where('created_by_id', Auth::user()->id)->with('cartDetails')->first();
Here is my cart model:
public function CartItem()
{
return $this->hasMany('App\Http\models\CartItem', 'cart_id')->with('images');
}
Here is the model of cartItem:
public function images()
{
return $this->belongsTo('App\Http\models\ProductImage', 'item_id', 'product_id');
}
Now in result I am getting only single image even though I have multiple images in the database. It always picking up the last inserted image.
I want to get all images or at least the first one but not the last one.
Please help.

You should use hasMany() relation instead of belongsTo():
public function images()
{
return $this->hasMany('App\Http\models\ProductImage', 'item_id', 'product_id');
}

if you have multiple images in the database of items then you have to use hasMany() insted of belongsTo().
public function images()
{
return $this->hasMany('App\Http\models\ProductImage', 'item_id', 'product_id');
}
When use belongTo() ?
suppose you have post and comment model. Now you want post of comment . That is inverse of a hasMany relationship.To define the inverse of a hasMany relationship, define a relationship function on the Comment (child) model which calls the belongsTo method
public function post()
{
return $this->belongsTo('App\Post');
}

Related

Laravel Many to many to many sync

I've got a problem since several days in Laravel.
My database is like attached picture.database
User<->Role many-to-many-relationship works correctly.
In addition, I would like to add another many-to-many relationship in role_user pivot table. So I did:
user.php:
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function role_users()
{
return $this->hasMany(RoleUser::class);
}
role.php:
public function users()
{
return $this->belongsToMany(User::class);
}
public function role_users()
{
return $this->hasMany(RoleUser::class);
}
And pivot roleUser.php:
public function user()
{
return $this->belongsTo(User::class);
}
public function role()
{
return $this->belongsTo(Role::class);
}
public function tags()
{
return $this->belongsToMany(Tag::class);
}
When I populate tables, I can get data: relations work.
Now I want to save data and let Laravel to populate tables automatically. At this moment and time, I save roles data in users.php with:
$this->Roles()->sync($roles);
($roles is an json array data from a form request..).
Pivot table get the user_id and role_id. Ok, cool.
Now, what should I write to get role_user_id and tag_id in role_user pivot table when I add a roles?
Thank you in advance!
I think you should use
$this->Roles()->attach($roles);
Rather than
$this->Roles()->sync($roles);
Because if I'm not wrong, sync will remove the pivot data. And you should pass the primary_key and foreign_key to your belongsToMany function. If you wanted to add data to the pivot column in your pivot table, try to add ->withPivot('column name');

1 to 1 and 0 to many relationship Laravel not working

I am struggling with an eloquent request. Let me explain what I want to do:
I have two models: User and Item
One User can have many Item and one Item belongs to One user.
I wrote the two method for this relation in my models as followed:
class Item extends Model
{
public function user() {
return $this->belongsTo(User::class);
}
}
class User extends Model {
public function items() {
return $this->hasMany(Item::class, 'items', 'user_id', 'user_people_id');
}
}
I try to access to the items from my controller its user's relation with:
public function index()
{
$items = Item::with('user')->get();
dd($items);
FYI: I seeded my items table with 10 items and my user table with 4 users:
items table:
users table:
My problem is that in the when I check my query with dd() here is what I get: Only the 4 first items get the relation, the others 6 return a null value
Relation working:
Relation returning null:
Thank you for helping me!
According to Laravel doc, hasMany relationship parameters are the following:
return $this->hasMany(Myclass::class, 'foreign_key', 'local_key');
So try to change your relationship in your User class like that
// change this
return $this->hasMany(Item::class, 'items', 'user_id', 'user_people_id');
// to this
return $this->hasMany(Item::class, 'user_people_id', 'id');
The easiest solution would be to rename your foreign key to user_id. That is what Laravel expects, so you won't need to deal with extra arguments in your hasMany() functions.
If you can't do that I think this'll work: return $this->hasMany(Item::class, 'user_people_id');.
Please try to add all in your query to see if it will work:
Update
public function index()
{
$items = Item::all();
dd($items);
}

Deleting from One-to-Many relationship Laravel

I have the two following models in one to many relationship:
Category.php
public function post()
{
return $this->hasMany('App\Category', 'category_id');
}
And Post.php
public function category()
{
return $this->belongsTo('App\Post', 'category_id');
}
I delete thee category that has few blog post under it.
Open the blog post whose category is deleted
Gets error as the category doesn't exist anymore
What is the best way to delete the category without causing the error ? Should I set the category_id of post to null while deleting their category ?
Use withDefault for if any category doesn't exist it'll give you null.
Category.php
public function post()
{
return $this->hasMany('App\Post', 'category_id')->withDefault();
}
Post.php
public function category()
{
return $this->belongsTo('App\Category', 'category_id')->withDefault();
}
Maybe this is gonna be the late answer but I will answer for Google searches anyway.
You can handle relationship cascading on the database If you don't want any null error about deleting the models on your project. Write this code to your project table migration.
$table->bigInteger('category_id')->unsigned();
$table->foreign('category_id')->references('id')
->on('categories')->onDelete('cascade');

How to load a nested relationship in Laravel

I have a model called CallbackRequest the model has a relationship with Loan model and that is the only relationship for CallbackRequest model.
CallbackModel:
public function loan() {
return $this->belongsTo(Loan::class);
}
Now Loan model itself has a relationship with a third model called Applicant.
Loan Model:
public function applicant() {
return $this->belongsTo(Applicant::class);
}
My point:
When I load CallbackRequest I eagerload loan model with it, all fine! But now I am wondering if there is a way to eagerload applicant model when I do:
Right now I access it like:
$modelResults = PublicCallback::with('loan')->get();
I get all callbacks with loan eagerloaded, but my point is I want when I eagerload loans in this case I want applicant to be loaded also !
Is there any way how to do this, is it possible ?
You can do this with:
$modelResults = PublicCallback::with(['loan', 'loan.applicant'])->get();
Ref: https://laravel.com/docs/5.5/eloquent-relationships#eager-loading
Just for posterity, there's also another way of loading nested relationships that can be done against a returned model, provided you have set up the relationships correctly:
Posts model:
public function comments() {
return $this->hasMany('App\Comment', 'quote_id', 'id');
}
Comments model:
public function user() {
return $this->belongsTo('App\User');
}
Then you can actually infer the user via relationship to a comment by drawing the post but loading an array of relations, eg:
$post = \App\Post::find($post_id);
return $post->load(['comments','comments.user']);

Retrieving collection from linked eloquent models laravel

I am using laravel 5.3 and need a bit of help with Eloquent model queries. I have three models (UserDetails, Categories, Articles). I have a relationship between UserDetails->Categories (belongstoMany), and a relationship between Categories->Articles (belongstoMany) which work well. However how would I go about getting the relationship data between Userdetails->Categories->Articles.
Each individual relationship is working fine i.e. Userdetails::find(1)->categories and Categories::find(1)->Articles.
I have a feeling that scopes may be the answer but they don't seem to work when I've attempted it.
Relationships in models
UserDetails.php
public function Categories(){
return $this->belongstoMany('App\Categories', 'users_cats', 'user_id','cat_id');
}
Categories.php
public function articles(){
return $this->belongsToMany('App\Article', 'article_categories', 'categoryID', 'articleID');
}
Ive looked into HasManyThrough function but again, I'm having issues implementing it, as far as I can see it should be
return $this->hasManyThrough('App\Article', 'App\Categories', TertiaryForeignKey, FinalForeignKey, LocalForeignKey);
My tables are set up as
articles_categories pivot table
articleID – primary key of the article
categoryID – primary key of the category
users_cats pivot table
user_id – primary key of the userdetails
cat_id – primary key of the categories
Based on this it the hasManyThrough should look like this?
public function articles(){
return $this->hasManyThrough('App\Article', 'App\Categories', 'user_id', 'articleID', 'id');
}
however this returns the error
Column not found: 1054 Unknown column 'categories.user_id' in 'field list'
update
So if you want to have this kind of relationship
userdetails->categories->articles
then you need to make this:
Userdetail model:
public function categories()
{
return $this->hasMany(Category::class);
}
public function articles()
{
return $this->hasManyThrough(Article::class, Categories::class);
}
Category model:
public function userdetails()
{
return $this->belongsTo(Userdetails::class);
}
public function categories()
{
return $this->hasMany(Category::class);
}
Article model:
public function categories()
{
return $this->belongsToMany(Category::class);
}
Then you can call UserDetails::find(1)->articles->get(); directly
You just need to declare the relationship like this in the
UserDetails.php model:
public function categories()
{
return $this->hasMany(Categories::class);
}
in Categories.php model:
public function articles()
{
return $this->hasMany(Articles::class);
}
Then you can retrieve the collection of categories in your controller:
$userdetails = UserDetails::get();
pass that $categories variable into your View and display each record with an foreach loop (where the articles is the function in your model)
#foreach($userdetails->categories as $usercategories )
<div> {{$usercategories->name}} </div>
#foreach($usercategories->articles as $categoryarticles )
<div> {{$categoryarticles->name}} </div>
#endforeach
#endforeach
with the second foreach you will access the articles of the categories that belongs to the user.

Categories