I have spent two days trying to solve this issue but no luck.
I have 3 tables, categories, items and related items, every item is under one category and category can have many items, this part working fine, now the issue is in related item, I have in the table realteditems 3 fields, id(just autoincrement), ritemf_id,riteml_id those refers to item_id in items table.
What I want to do is to display item with its details and related items to this item, means if item1 have many realted items,such item2,item3,item4 .. so need to display like this
item_title: item1
related item:
item2
item3
item4
controller
$items = Item::orderBy('category_id', 'asc')->with('category')->get()->groupBy('category_id');
$categories = Category::orderBy('category_id', 'asc')->get();
return view('home',['items' => $items,'ritems' => $ritems,'categories' => $categories]);
items modal
public function category()
{
return $this->belongsTo('App\Category', 'category_id');
}
public function relateditems()
{
return $this->belongsTo('App\Relateditem', 'ritemf_id');
}
relateditems modal:
class Relateditem extends Model
{
protected $table="relateditems";
protected $fillable=['ritemf_id','riteml_id'];
protected $primaryKey='id';
public $timestamps=false;
public function items()
{
return $this->belongsTo('App\Item', 'item_id');
}
}
showing items with its category in blade(working fine)
#if (!empty($categoryItems->first()->category))
{{ $categoryItems->first()->category->category_name }} #else {{$category_id}} #endif
#foreach($categoryItems as $item)
{{$item->item_title}}
${{$item->item_price}}
#endforeach
#endforeach
relateditems()definition looks incorrect to me in Item model, Item may have more than one related items then this should be hasMany/beongsToMany association.
Assume its hasMany then update your item model as
public function relateditems() {
return $this->hasMany('App\Relateditem', 'ritemf_id');
}
And eager load your related items for each item
$items = Item::orderBy('category_id', 'asc')
->with(['category', 'relateditems'])
->get()
->groupBy('category_id');
I assume the groupBy method is used from collection class to group retrieved data not on database side
You need to fix both relations in Item Model and RelatedItem model. relateditems should be hasMany because an item can have many related item.
You also need to define belongsTo relation in RelatedItem to Item using riteml_id key
Item modal
public function category()
{
return $this->belongsTo('App\Category', 'category_id');
}
public function relateditems()
{
return $this->hasMany('App\Relateditem', 'ritemf_id');
}
Relateditem modal:
class Relateditem extends Model
{
protected $table="relateditems";
protected $fillable=['ritemf_id','riteml_id'];
protected $primaryKey='id';
public $timestamps=false;
public function item() //i have change it to item instead items, because belongsTo always return single record
{
return $this->belongsTo('App\Item', 'riteml_id');
}
}
Fetch Data
$items = Item::orderBy('category_id', 'asc')->with('category','relateditems', 'relateditems.item')->get()->groupBy('category_id');
foreach($items as $categoryId => $groupItems){
echo $groupItems->first()->category;
foreach($groupItems as $item) {
echo $item->item_tile;
...
foreach($item->relateditems as $relatedItem){
if ($relatedItem->item){
echo $relatedItem->item->item_tile; //this will show you related item title
}
}
}
}
For Single Item
$item = Item::with('category','relateditems', 'relateditems.item')->find(1);
foreach($item->relateditems as $relatedItem){
if ($relatedItem->item){
echo $relatedItem->item->item_tile; //this will show you related item title
}
}
Related
I have been working on two tables Category & Product.
In Category Model I have a relationship like
class Category extends Model
{
use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
public function products(){
return $this->hasManyJson(Product::class,'category_ids[]->id');
}
}
In Products Model I have a relationship like
class Product extends Model
{
use \Staudenmeir\EloquentJsonRelations\HasJsonRelationships;
protected $casts = [
'category_ids'=>'json',
];
public function products(){
return $this->belongsToJson(Category::class,'category_ids[]->id');
}
}
Now in my controller when I'm doing trying to get count of each categories product, it is giving me Empty results, below is my controller code.
public function two_category()
{
$list = Category::where('home_status', true)->get();
foreach($list as $ls){
echo $ls->name.' '.count($ls->products).'<br>';
}
dd('ended');
}
This is giving -
Category1 0
Category2 0
And finally this is how my column in product table looks like.
I have database relation like below
I want to get shop data with their products which each product has their category. If we define it using Eloquent ORM in Laravel, shop hasMany products belongsTo productCategory.
I can get the data of shop with their products using hasMany, but I can't get the productCategory of each products. Does anyone know how to get the productCategory of each product?
Shop model:
class Shop extends Model
{
public function products() {
return $this->hasMany('App\Product');
}
}
Procuct model:
class Product extends Model
{
public function shop() {
return $this->belongsTo('App\Shop');
}
public function category() {
return $this->belongsTo('App\ProductCategory');
}
}
Product category model:
class ProductCategory extends Model
{
public function products() {
return $this->hasMany('App\Product');
}
}
Shop controller to get the data:
class ShopController extends Controller
{
public function show(Shop $shop)
{
$products = $shop->products()->get();
return view('pages.shop-detail.index')->with('shop', $shop)->with('products', $products);
}
}
On One To Many (Inverse) Relationships:
Eloquent determines the default foreign key name by examining the name of the relationship method and suffixing the method name with a _ followed by the name of the primary key column. However, if the foreign key on the Product model is not category_id, you should pass the custom key name as the second argument to the belongsTo method:
class Product extends Model
{
public function category() {
return $this->belongsTo('App\ProductCategory', 'product_category_id');
}
}
Then in the view, loop over shop products an show the name of the product and the name of the product category:
<h3>Shop: {{ $shop->name }}</h3>
#foreach ($shop->products as $product)
<p>Product: {{ $product->name }}</p>
<small>Category: {{ $product->category->name }}</small>
#endforeach
But...
Doing the query in the way you had it in the question you'll have an N + 1 problem when you loop on products in the view.
Avoid the model binding in your controller to eager load the relationships and return just the shop, the products and category will be eager loaded on the Shop object:
class ShopController extends Controller
{
public function show($id)
{
$shop = Shop::with('products', 'products.category')->find($id);
return view('pages.shop-detail.index')->with('shop', $shop);
}
}
I'm showing all sub categories under main category. On each sub-category there is a counter of how many items are assigned there.
Main Category
- Sub Category (1)
- Sub Category (3)
- etc
Current problem is that one item can be published and unpublished. When the item is not published yet I don't want to show it on counter. Column in items table is published and accept 1 for published and 0 for unpublished.
This is what I have to show them on page
HomeController.php
$allCategories = Category::where('parent_id', 0)->has('children.item')
->with(['children'=> function($query){
$query->withCount('item');
}])
->get()
->each(function($parentCategory){
$parentCategory->item_count = $parentCategory->children->sum(function ($child) { return isset($child->item_count)?$child->item_count:0;});
});
My Item.php model
public function category()
{
return $this->belongsTo('App\Category');
}
My Category.php model
public function item()
{
return $this->hasMany('App\Item','category_id');
}
public function parent()
{
return $this->belongsTo('App\Category', 'id', 'parent_id');
}
public function children()
{
return $this->hasMany('App\Category', 'parent_id', 'id');
}
I've tried to directly add it to the query but doesn't make any difference
$query->withCount('item')->where('published', 1);
You have to add the where condition in the relationship function item of Category.php model.
Here is the code:
public function item()
{
return $this->hasMany('App\Item','category_id')->where('published', 1);
}
I have category and subcategory table with many to many relationship
class Category extends Model {
protected $table='categories';
protected $fillable=['name'];
public function subcategories() {
return $this->belongsToMany('App\Modules\Subcategory\Models\Subcategory', 'categories_subcategories', 'category_id', 'subcategory_id');
}
}
Subcategory
class Subcategory extends Model {
protected $table='subcategories';
protected $fillable=['name'];
public function categories()
{
return $this->belongsToMany('App\Modules\Category\Models\Category', 'categories_subcategories', 'subcategory_id', 'category_id');
}
}
in controller
public function catSubList()
{
$subcategories = Subcategory::with('categories')->get();
return view('Subcategory::category_subcategory',compact('subcategories'));
}
But in view when i tried to access the data with following view
#foreach($subcategories as $row)
<td>{{$i}}</td>
<td>{{$row->name}}</td>
<td>{{$row->categories->name}}</td>
#endforeach
I got the error like :
ErrorException in Collection.php line 1527: Property [name] does not exist on this collection instance.
How do i access $row->categories->name ? anyone with the suggestion please?
You have to make another foreach() loop Because your subcategories belongsToMany categories. row->categories returns a collection, not an object. Thus the error.
<td>{{$row->name}}</td>
<td>{{$row->categories->name}}</td>
#foreach($row->categories as $category)
<td>{{$category->name}}</td>
#endforeach
Update
Getting a category with all subcategories. Simply invert your query
$category = Category::with('subcategories')
->where('name', '=', 'cars')
->first();
//will return you the category 'cars' with all sub categories of 'cars'.
Without eager loading
$category = Category::find(1);
$subacategories = $category->subcategories;
return view('Subcategory::category_subcategory', compact('category', subcategories));
In my project I have orders which have many products and customers who have many orders. I am confused because I want to get all orders that a certain customer has and the products of each order. I messed up something somewhere and I am not sure if I set my relationships correctly. Here is my products table:
Here is my customers table:
And here is my orders table:
Here are my models:
Product:
class Product extends Model
{
public function orders()
{
return $this->belongsToMany('App\Order');
}
}
Order:
class Order extends Model
{
public function products()
{
return $this->hasMany('App\Product', 'id');
}
public function customer()
{
return $this->belongsTo('App\Customer');
}
}
Customer:
class Customer extends Model
{
public function orders()
{
return $this->hasMany('App\Order', 'id');
}
}
I get all customers from my database with App\Customer::all() in my CustomersController and pass the data in my customers.blade.php.
<h1>Customers:</h1>
#foreach($customers as $customer)
<h3>{{$customer->name}}</h3>
#foreach($customer->orders as $order)
<p>Order ID: {{$order->id}}</p>
#foreach($order->products as $product)
<p>Product title: {{$product->title}}</p>
#endforeach
#endforeach
<hr>
#endforeach
Here is the output:
If someone could explain why it doesn't output everything and give some advice if this is the way to go with the relationships, I would be very thankful.
Your products should belong to an order, rather than have a many-to-many relationship.
class Product extends Model
{
public function orders()
{
return $this->belongsTo('App\Order');
}
}
I found a solution by making a pivot table for products and orders called products_orders which holds the product_id and the order_id and making a many to many relationship between Product and Order. That is because an order may have multiple products and products may exist in multiple orders.
My pivot table products_orders:
class Product extends Model
{
public function orders()
{
return $this->belongsToMany('App\Order');
}
}
class Order extends Model
{
public function products()
{
return $this->belongsToMany('App\Product', 'products_orders');
}
public function customer()
{
return $this->belongsTo('App\Customer');
}
}
I made a one to many relationship (customer_id in orders table) for Customer and Order and now everything works fine.
class Customer extends Model
{
public function orders()
{
return $this->hasMany('App\Order');
}
}