Laravel hasManyThrough in depth - laravel

I have been looking at documentation regarding the hasManyThrough relationship in Laravel, and fro some reason I am struggling with it as the documentation makes it look simple (maybe I am overthinking it)....
I have three Models tables at the moment:
-User (extends authenticatable)
id,
name,
surname,
email,
password.
-Order
id,
user_id,
name,
unit,
qty
-Product (i need to add a qty table to show how many is ordered).
id,
order_id,
name,
unit,
description,
family
My Products model is used by Admin to CRUD products.
Please can someone explain to me how I will be able to display to admin which user made an order, and what does the order consist of.
I also want to display to the user a 'order history'..
Please will anyone be able to assist..
UPDATE
-order_product
id,
order_id,
product_id
quantity
product controller:
public function orders()
{
return $this->belongsToMany('App\Order')->withPivot('quantity');
}
order controller:
public function products()
{
return $this->belongsToMany('App\Product')->withPivot('quantity');
}

I think you need create one more table like order_details
-User (extends authenticatable)
id,
name,
surname,
email,
password.
-Order
id,
user_id,
name,
unit,
qty
-Product (i need to add a qty table to show how many is ordered).
id,
name,
unit,
description,
family
-Order_detail(Store product_id, order_id (You can put qty to this table))
id,
order_id,
product_id

It is many to many to relationship show you'll have to create one another pivot table named
order_product with fields
-id
-order_id
-product_id
-quantity
and in your Order table Model define relationship as
public function products()
{
return $this->belongsToMany('App\Product')->withPivot('quantity');
}
and in your Product table Model define relationship as
public function orders()
{
return $this->belongsToMany('App\Order')->withPivot('quantity');
}
to Retrieve data
$order= App\Order::find(1);
#foreach ($order->products as $product)
echo $product->pivot->quantity."<br>";
#endforeach

Related

Creating a "through" relationship when both foreign keys are on the same table

I have a products table. A product belongs to a category and a country.
I would like to find out what countries a category has by leaning on this relationship.
I've considered hasManyThrough and https://github.com/staudenmeir/belongs-to-through but this is sort of a belongsTo relationship, with both foreign keys on an intermediate table, I suspect the products table is sort of acting like a pivot.
I would like to know how I can set up a relationship that relates categories to countries through the products table - is this possible?
Tables:
Categories
id
title
Countries
id
title
Products
id
title
category_id
country_id
Relationships:
A product belongs to a country / A country has many products.
A product belongs to a category / A category has many products.
You've pretty much described a Many to Many relationship with Product being the pivot table.
# Category model
public function countries()
{
return $this->belongsToMany(Country::class, 'products')
->withPivot(['id', 'title']); // optional
}
# Country model
public function categories()
{
return $this->belongsToMany(Category::class, 'products')
->withPivot(['id', 'title']); // optional
}

Invalid argument supplied for foreach() in laravel when use Eloquent: Relationships

I wanna get the class name of a user via the user ID. When I input the ID of a user so I will wanna get the class name. I have three tables such as users table, classes table, and class_users table. The class_users table is born from two users table and classes table.
A users table has an id, name, email, password.
A classes table has an id, class_code, class_name.
A class_users table has an id, class_id, user_id
And this problem relates to Eloquent Relationships.
Thank you for help.
My Route:
Route::get('/find_classes/{id}','StudentController#find_classes');
My Controller function:
public function find_classes($id)
{
$users = User::find($id);
foreach($users->classes as $class)
{
echo $class->name . '<br';
dd($class);
}
}
My User Model:
public function classes()
{
return $this->belongsTo('App\Classes','class_users','user_id','class_id');
}
Looks like you might have the wrong relationship set up on your User model. You have a one to many set up, but your DB is setup to handle a many to many. I suggest you change your User model relationship:
public function classes()
{
return $this->belongsToMany('App\Classes');
}
Note, you may need to name the FK on that relation, as I see you have class_id on the table, but your actual class is named 'Classes'. Check through your relationships to ensure this is explicit on the FK where it doesn't follow Laravel convention exactly.
With this relationship, your foreach loop should work. It would be a good idea for efficiency, as mare96 noted, to eager load the classes on the $users collection when you query:
$users = User::with('classes')->find($id);

Laravel has-many-through with multiple intermediate tables

I am trying to develop multiple-shop eCommerce platform.
So the following tables created:
shops: id, name, ...
products: id, shop_id, ...
orders: id, ...
order_details: id, order_id, product_id, ...
And this is the summery of my models' relationships:
Shop->products: Shop hasMany Product
Product->shop: Product belongsTo Shop
Order->details: Order hasMany OrderDetail
OrderDetail->order: OrderDetail belongsTo Order
OrderDetail->product: OrderDetail belongsTo Product
Product->orders: Product hasMany OrderDetail
Now, 1: Is it possible to define Shop->orders relationship?(It seams has-many-through not works in this case due to multiple intermediate tables)
2: If it is possible, could the shop->orders->details contains only the records related to shop products?
It should be note that each Order may contain products from multiple shops but the shop->orders->details relation should contains only the shop products.
There is no native relationship for this case.
I created a HasManyThrough relationship with support for BelongsToMany: Repository on GitHub
After the installation, you can use it like this:
class Shop extends Model {
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
public function orders() {
return $this->hasManyDeep(Order::class, [Product::class, 'order_details']);
}
}

(Laravel / Eloquent) How to join 4 tables to make 1 query

I'm new at Laravel and I want some help with a Query. Here is my situation. I have 4 tables:
users (id, email, password.....)
user_profile (id, first_name, last_name,........, user_id)
companies (id, name,.......)
policies (id, policy_num, exp_date,........., user_id, company_id)
The table user have 5 users and every user have 10 policies. The table company have 3 companies.
$user_data=User::select('*')
->with('profile','policies')
->where('id', '=', $userId)
->first();
This code is working good, it retrieves the all the users and user_profile fields and all the policies(10) of this user with as you can see in this image, and I can show the user the details of the products on a home page.
I want to instead of appear the company_id from the policies table appears the name of the company from the company table.
Any help is appreciated.
Thank you for your answer ceejayoz, i already did.
User
public function profile()
{
return $this->hasOne('UserProfile');
}
public function policies()
{
return $this->hasMany('Policy');
}
Policy
public function company()
{
return $this->hasOne('Company');
}

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