Laravel Collection of Multiple relation items - php

I have a User that has many Shops, And a Shop has many Products
Now I'm wondering, Is there a way that I can get a Collection of all products for this User.
Without having to loop through the shops he has.
Current method, Which returns a Collection of Shops with Products instead of a Collection of Products
$products = \Auth::user()->shops()->with('products')->get();

You'll want to define a HasManyThrough relation
class User extends Model
{
...
public function products()
{
return $this->hasManyThrough('App\Product', 'App\Shop');
}
...
}

You can get all the products from multiple shops by using the pluck method.
public function products()
{
return $this->shops->pluck('products');
}
public function shops()
{
return $this->belongsToMany(Shop::class);
}
($this being an instance of your user model)
And on your shops model you must have a Laravel relationship to products
public function products()
{
return $this->belongsToMany(Product::class);
}

Related

Laravel: How to count data in database?

I want to make a list of students to know how many products each student buys. I have two tables : Member and Orders. In Orders table have column member_id and product_id. I want to count how many products each student buys. I can get list of student but i can't count how many products each student buys.
public function index()
{
$students = Member::getStudents();
$order = Order::where('member_id', $students->id)->count();
return view('admin.student.index', compact('students'));
}
But it appears an error:
Property [id] does not exist on this collection instance.
function getStudents()
public static function getStudents()
{
$members = Member::where('member_type_id', BaseModel::$student)->get();
for ($idxMember = 0; $idxMember < count($members); $idxMember++) {
if ( $members[$idxMember]->user_id ) {
$members[$idxMember]->username = User::find($members[$idxMember]->user_id)->username;
}
}
return $members;
}
I think it is because you get a collection on id.
so you should foreach your collection and get specific ids.
public function index() {
$students = Member::getStudents();
foreach($students as $student ) {
$order = Order::where('member_id', $student->id)->count();
}
return view('admin.student.index', compact('students'));
}
I suggest to use relationships in Database. It would be more easy and simple.
In orders table, there is a column called member_id which reference to id column in members table. (Keep attention to singular plural usage)
Refer Laravel Documentation for foreign key design and implementation.
You need 2 models, Member and Order. You should define the relationship as below.
Since this is One To Many Relationship,
In Member Model,
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Member extends Model
{
/**
* Get the orders for the member.
*/
public function orders()
{
return $this->hasMany('App\Order');
}
}
?>
In Order Model,
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
/**
* Get the member that owns the order.
*/
public function member()
{
return $this->belongsTo('App\Member');
}
}
?>
Now you can get order count per user using this code.
Member::find(MEMBER_ID)->orders->count();
This will return order count of the selected member.
Please refer the Laravel Documentation here.
Relationships | One To Many | One To Many (Inverse)
You can achieve this by simply using laravel relationship
In order to do this please follow below steps
First, create two relation in members model
public function orders()
{
return $this->hasMany('App\Models\Order', 'member_id', 'id);
}
Then retrieve the students details with orders
public function getStudents()
{
return Member::where('member_type_id', BaseModel::$student)->withCount('orders)->get();
}
Hope this helps
Thank you.
Sharing solution with explanation.
Objects are
Member (Student is also a member. But the Type is different)
Order (One order can have multiple products)
Product (Product will allocate with Orders and Members can place Orders)
Now If you are using Laravel. So the best way is to use Eloquent Relationships.
Model Member :
1 Define Query Scope
public function scopeStudents($query)
{
return $query->where('member_type_id', 1);
}
2 Define One to Many relation between Order and Member (One Student can have multiple orders. And I hope that other members can also have orders. So i am going to relate direct Member to Order)
public function orders()
{
return $this->hasMany('App\Order');
}
and
public function products()
{
return $this->hasManyThrough('App\Product', 'App\Order');
}
Model Order :
1 Define relation with Member Model for One to Many
public function member()
{
return $this->belongsTo('App\Member');
}
2 Define one to many between Order and Product
public function products()
{
return $this->hasMany('App\Product');
}
Model Product :
1 Define Order Product Relation
public function order()
{
return $this->belongsTo('App\Order');
}
Now the Model work is done. Only data fetching is remaining. Tell me in comments if you think below code is less and useful and easy to understand.
Controller Member :
1 Index Function :
// this will fetch all students with their orders and products
$data = Member::students()->with('orders', 'products')->get();
// this will fetch all students with their orders and order's products
$data = Member::students()->with('orders.products')->get();
// this will fetch all students with their orders count and products count
$data = Member::students()->withCount('orders', 'products')->get();

Laravel: 2nd level relationship only fetching single row

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');
}

Laravel eloquent querying with multiple relationships

I have four tables which is departments, users, items, items_inventories
The relationship is like this:
A user has a assigned department.
An item has a assigned department. item_inventories has many items.
Structure:
users
->id
->name
->password
->access_type (department_id)
departments
->id
->name
items
->id
->name
->department_id
items_inventories
->id
->item_id
->qty
My models:
class Item extends Model
{
public function department()
{
return $this->hasOne('App\Http\Models\Department', "id", "department_id");
}
}
class ItemsInventory extends Model
{
public function item()
{
return $this->hasOne('App\Http\Models\Item', "id", "item_id");
}
}
In my items_inventories how do I query all items that belongs to a specific department? Since items has already a relationship to departments, How do I query like: select all items in items_inventories where item department_id is equal to 3?
My goal is, I have a user who is logged in, and I can access the assigned department to him/her via access_type (department_id) when my page loads, I want to list only items in the items_inventories that is assigned to his/her department. I already checked: https://laravel.com/docs/5.4/eloquent-relationships#relationship-methods-vs-dynamic-properties but can't seem to find something that matches my requirement. Thanks
Your relationships are a bit confusing. The table structure says that items belong to departments and item inventories belong to items. I've based the relationship on your table structure and how you can achieve your desired result. You might want to check on your relationship once more to verify how exactly you want it to pan out. As for the current relationship, my models should give you an idea.
class User extends Model
{
public function department()
{
return $this->belongsTo('App\Http\Models\Department', 'access_type');
}
}
class Department extends Model
{
public function items()
{
return $this->hasMany('App\Http\Models\Item');
}
public function itemInventory()
{
return $this->hasManyThrough('App\Http\Models\ItemsInventory', 'App\Http\Models\Item');
}
}
class Item extends Model
{
public function department()
{
return $this->belongsTo('App\Http\Models\Department');
}
public function itemInventory()
{
return $this->hasMany('App\Http\Models\ItemsInventory');
}
}
class ItemsInventory extends Model
{
public function item()
{
return $this->belongsTo('App\Http\Models\Item');
}
}
Controller logic
$department_id = 3;
$itemInventory = ItemsInventory::whereHas('item', function ($query) use ($department_id) {
$query->where('department_id', $department_id);
})->get();
// With user:department relation and department:iteminventory 'hasManyThrough' relation.
$itemInventory = $user->department()->itemInventory;

How to setup laravel relationship

I'm using Larvel 5.3 and I have four tables I wish to set up relations with.
- Users
- Orders
- Products
- Brands
An order belongs to a user and a user has many orders.
A product belongs to many orders and additionally, to one brand.
A brand has many products.
I'm trying to find a way to get a user's order, with the products AND the brand of the products.
User.php
public function orders(){
return $this->hasMany('App\Order');
}
Order.php
public function user() {
return $this->belongsTo('App\User');
}
public function products(){
return $this->hasMany('App\Product');
}
Product.php
public function orders() {
return $this->belongsToMany('App\Orders');
}
public function brand(){
return $this->belongsTo('App\Brand');
}
Brand.php
public function products() {
return $this->hasMany('App\Flavour');
}
I wish to get back an array containing the users orders, along with each orders products and the products' brand.
Could anyone advise?
First, Products and Orders have a many to many relationship.
public function products(){
return $this->belongsToMany('App\Product');
}
Get a user's order first. Because users have many orders, you need to specify which order you want to view the products list from.
$order = $user->orders->first();
Then get all products and their brand
foreach($order->products) ...
For your super array, you can try Eager Loading
$arr = User::with('orders.products.brand')->get(); //Not tested

Eloquent many-to-many

Using Laravel, I'm having some trouble accessing my other tables, which are all many to many.
So basically, I start out with the user id and want to list the customers that user has.
public function customers()
{
return $this->belongsToMany('Customer', 'user_to_customer');
}
This works, assume my user id is 1:
User::find(1)->customers;
However now I want to say, for each of these customers, list their products. However this needs to be within the same result.
I guess I would need something within the Customer model, such as:
public function products()
{
return $this->belongsToMany('Product', 'user_to_customer');
}
I can't seem to work out how to access this within the same query? Something like:
User::find(1)->customers->products;
Not sure.. any suggestions?
You can look into eager loading to accomplish this behavior. Given the following model relationships:
class User extends Eloquent {
public function customers()
{
return $this->has_many( 'Customer' );
}
}
class Customer extends Eloquent {
public function products()
{
return $this->has_many( 'Product' );
}
}
class Product extends Eloquent {}
The following query will return all products belonging to customers belonging to a specific (in this case, first) user:
User::with(array('customers', 'customers.products'))->first();

Categories