Category relationship in laravel Undefined property: stdClass:: - laravel

Hi i'm working on a laravel training project . i'm having an issue with models and relationships when i'm trying to get the each product category name .
Here is my Product Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
public function category()
{
return $this->belongsTo('App\Category');
}
}
and my Category model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $table = 'categories';
public function products()
{
return $this->hasMany('App\Product');
}
}
when i try to get the category name for each product like this
#foreach($products as $product)
<tr>
<td>{{ $product->id }}</td>
<td>{{ $product->name }}</td>
<td>{{ $product->category->name }}</td>
</tr>
#endforeach
while i run the page i get this error
Undefined property: stdClass::$category (View: /var/www/html/projectname/resources/views/my/products/index.blade.php)
can anyone tell me what's causing this error ?
update
here is the table structure
Products : id , name , category_id->unsigned()
Categories : id , name
and here is the code i use to get $products
$user_id = Auth::user()->id;
$products = DB::table('products')->where('user_id', $user_id)->paginate(5);
return view('my.products.index')->withProducts($products);

Your issue is that you're using Laravel's query builder instead of Eloquent, but you're treating the result as if it was Eloquent.
When you do:
$products = DB::table('products')->where('user_id', $user_id)->paginate(5);
The $products variable will contain a Paginator instance, which contains your items as instances of stdClass. If you want to be able to do this with Eloquent, you should try something like this:
$products = Product::with('category')->where('user_id', $user_id)->paginate(5);
This will ensure that the items returned in the paginator are instances of your Product Eloquent model, with the category relationship eager loaded (I.e. it will load the category relationship for each Product returned using one query, rather than 5 queries, one for every Product).
You should then be able to access $product->category->name.

Related

Hot to show the posts that have same category id in laravel livewire?

the livewire component is route bonded as:
Route::get('/post/{post}', Bycategory::class)->name('posts.by-category');
in-home view I want to click on the category name and get all posts with same category:
#foreach($post->categories as $category)
{{ $category->name }}
#endforeach
this is bycategory livewire class:
public Post $post;
public function render()
{
Post::with('categories')->where(function ($q){
$q->where('category_id', $this->post->categories()->id);
})->get());
return view('livewire.post.bycategory', compact('posts'))->layout('layouts.app');
}
the post and categories have many to many relations with the category_post table
but I get an error that there is not category_id in Post model;
the $this->post->categories()->id show the category id of that post;
As you mentioned that the the error above, it is clear that posts table does not have the category_id column and that is why you get this error. I think this is the right way to do this query
Post::with('categories' , function ($query) { $query->where('categories.id', $this->post->categories()->id);} )->get());

get value from another table based on id laravel

i have two tables ( Factories , Products )
Factories table has two columns ( id , factory_name )
and Products table has three columns ( id , factory_id , product_name )
i want to display factory_name column in Factories table in blade.php based on factory_id in Products table
the code in Factory Model :
public function products()
{
return $this->hasMany('App\Product');
}
and the code in Product Model :
public function factories()
{
return $this->belongsTo('App\Factory');
}
the code in ProductsController :
public function index()
{
$data['Products'] = Product::with('factories')->orderBy('created_at', 'desc')->get();
return view('all_products')->with($data);
}
and the code in view :
#foreach ($Products as $Product)
<tr>
<td>{{$Product->id}}</td>
<td>{{$Product->factory_name}}</td>
<td>{{$Product->product_name}}</td>
</tr>
#endforeach
and this not work ... so how i get factory_name
It's always a good idea to add {{dd($data)}} to blade file to see what you have.
I think the relation between products and factories is one-to-many. In this case, it would be better if you make the function name factory instead of factories.
public function factory()
{
return $this->belongsTo('App\Factory');
}
Unless it's a correct syntax that I'm not familiar with, the problem should be $data['Products'] and with($data). Let's change them:
public function index()
{
$data = Product::with('factory')->orderBy('created_at', 'desc')->get();
return view('all_products')->with('Products', $data);
}
Now, you have $Products on your blade file.
Since you get factory_name through relation, factory info is associated with a key. You need this:
<td>{{$Product->factory->factory_name}}</td>
its easily like this :
#foreach ($Products as $Product)
<tr>
<td>{{$Product->id}}</td>
<td>{{$Product->factories->factory_name}}</td>
<td>{{$Product->product_name}}</td>
</tr>
#endforeach
since you already have a relationship called factories between your two models
As you have shown that you are trying fetching Products along with factories
Product::with('factories')->orderBy('created_at', 'desc')->get();
So the result that you will get from this query will be in the following format
{
id: product_id,
factories: {
id:factory_id,
factory_name: factory_name,
...
}
}
So in order to fetch the factory name in products list you need to use:
<td>{{$Product->factories->factory_name}}</td>
instead of
<td>{{$Product->factory_name}}</td>
Hope this solve your problems

Show many products from a category from many-to-many relationship in laravel

So I’m making a catalogue using Laravel 7.* and I have a problem.
I have many products and many categories. I have created a many-to-many relationship so a product can be in many categories.
Now, what I am trying to do is to show in a page each category with related products, but obviously I am doing something wrong.
Below you may see some code:
Product.php:
public function categories()
{
return $this->belongsToMany(Category::class);
}
Category.php:
public function product()
{
return $this->belongsToMany(Product::class);
}
Show.blade.php
#php
$products = \App\Product::with('categories')->find(1);
#endphp
#foreach ($products as $id)
{{ $id->name }}<br>
#endforeach
Any help please?
Fixed it.
I fetched categories in controller and send to view. Then for each category displayed each product.
Get all the categories and show products related to them.
#php
$categories= \App\Category::all();
#endphp
#foreach($categories as $category)
#foreach($category->product as $product)
{{$product->name}}
#endforeach
#endforeach
You need also Id of category that you want to show products related to it.
According To This answer
Try this:
$category_id = 1; // Desired Category Id
$products = \App\Product::whereHas('categories', function($query) use ($category_id) {
$query->where('category_id', $category_id);
})->paginate();
I also added pagination.

Laravel Eloquent get data where comparison is true

I am creating a mini inventory stock for a fashion store. I am using Laravel/Voyager with BREAD and everything fine. I have 2 tables Sizes and Products with a column in common product_code.
I would like to get the results from Sizes where column product_code = Product 'product_code'.
I have this query in the controller:
$product_code = Product::all();
$allSizes = Size::where('product_code', ($product_code->product_code));
and in browse.blade.php I have:
#foreach ($allSizes as $size)
<tr>
<td align="right">{{$size->size_name}}</td>
<td align="right">{{$size->stock}}</td>
</tr>
#endforeach
I guess the where statement is not working as supposed to.
I want to get the corresponding stock based on product_code for each size from table Sizes
Try This
$product_code = Product::pluck('product_code')->toArray();
$allSizes = Size::whereIn('product_code', $product_code)->get();
and in browse.blade.php:
#foreach ($allSizes as $size)
<tr>
<td align="right">{{$size->size_name}}</td>
<td align="right">{{$size->stock}}</td>
</tr>
#endforeach
I think you're going about this the wrong way. Your tables are related in some way and you need to define a relationship to access the data Eloquently.
If I were building such a database, I think that the relationship between Product and Size is a many to many. I.e. a Product can have many Sizes, and you can also shop for many Products in a certain Size. Thus, your models should have a belongsToMany() relationship to each other.
// Product.php
protected $with = ['sizes']; // eager load product sizes
public function sizes() {
return $this->belongsToMany(Size::class);
}
// Size.php
public function products() {
return $this->belongsToMany(Product::class);
}
Then you can do
// ProductsController.php
public function show(Product $product) {
return $product;
}
You missed to run the query
$product_code = Product::all();
# ::all() will return collection, and you can't access a property of it directly
$allSizes = Size::where('product_code', ($product_code->first()->product_code))->get();
Notice the ->get();

Laravel - Populating view with info from single row (with pivot data)

I currently have a form/view that allows a User to save an Order. This also updates a pivot table with the respective Products and qtys. What I am trying to do, is after this information is inputted and saved into the database, I want to send the user to a checkout page that shows all the information they inputted for that Order.
Relationships
User hasMany Order
Order belongsToMany Product
Product belongsToMany Order
checkout.blade.php
#foreach ($orders as $order)
#foreach ($order->products as $product)
<tr>
<td>{{ $product->name }}</td>
<td>{{ $product->pivot->qty }}</td>
</tr>
#endforeach
#endforeach
OrderController.php
public function checkout($id)
{
$user = Auth::user();
$user->load("orders.products"); //eager load pivot table
$orders = $user->orders->where('order_id', $id);
return view('orders.checkout', compact('orders', 'user'));
}
I know I am calling the order incorrectly, because if I change
$orders = $user->orders->where('order_id', $id);
to
$orders = $user->orders;
It displays correctly, except of course, it populates with every Order's detail.
Or is there some elegant way for me to pass the data from the checkout function without this additional query? (I understand about moving data in Sessions, but I am working with a pivot table, and that complicates things.
If on the checkout page, you want to use just the latest order that the user has made, then you can just load that order using route model binding
Route::get('checkout/{order}', 'OrdersController#checkout');
Then in your controller:
public function checkout(Order $order)
so from here, you can pass this order to the view, and list all the products from this order, and also in your Order model you should have a reference to the user that this order belongs to:
public function user()
{
return $this->belongsTo(User::class);
}
Accessing columns from the pivot table will be:
#foreach($order->products as $product)
<div> {{ $product->pivot->column }} </div>
#endforeach

Resources