I have a prolem here with 2-level far relations between models. It's classic eCommerce website with expected structure where you have a product table, galleries and images. Product and Image has gallery_id so every gallery has potencialy many Images. This is my solution which doesn't work. Returns "Trying to get property 'images' of non-object".
VIEW Product.blade.php
<ul>
#foreach ($product->gallery->images as $image)
<li><img src="{{ asset($image->path) }}" alt="" data-image="{{ asset($image->path) }}"></li>
#endforeach
</ul>
MODEL Product.php
public function gallery()
{
return $this->belongsTo('App\Gallery');
}
MODEL Gallery.php
public function images()
{
return $this->hasMany('App\Image');
}
Why I can't access images from product view by $product->gallery->images?
Related
I wrote a relation belongsToMany between products and photos and now I want to show products in the home page. I did it like so:
#foreach ($latestProducts as $product)
<img src="{{$product->photos()->path}}">
#endforeach
homeController:
public function index()
{
$latestProducts = Product::orderBy('created_at' , 'desc')->limit(10)->get();
return view('front.layouts.index' , compact('latestProducts'));
}
photo model:
public function products() {
return $this->belongsToMany(Product::class);
}
product model:
public function photos() {
return $this->belongsToMany(Photo::class);
}
I got Undefined property: Illuminate\Database\Eloquent\Relations\BelongsToMany::$path .And when I write {{$product->photos[0]->path}} , the error changes to "Undefined array key 0. Also when I write {{$product->photos->path}} ,I get an error as "Property [path] does not exist on this collection instance."
I believe you got a photo attribute/field in the Photo model. Because photos is a collection of photos, you might want to write:
#foreach ($latestProducts as $product)
#foreach ($product->photos as $photo)
<img src="{{$photo->path}}">
#endforeach
#endforeach
And only the first photo:
#foreach ($latestProducts as $product)
<img src="{{$product->photos->first()->path}}">
#endforeach
// Or to be safe
#foreach ($latestProducts as $product)
<img src="{{optional($product->photos->first())->path}}">
#endforeach
// Or this in php 8
#foreach ($latestProducts as $product)
<img src="{{$product->photos->first()?->path}}">
#endforeach
You have to use
{{ $product->photos->path }}
cause when you deal with relations in blade you deal with it as a property of class of the father class unlike when you deal with it in eloquent ORM you can use photos()
Basically the error is saying that there is no property photos in the $products. Assuming that the table name is correct and the foreign keys too
you can just do:
public function index()
{
$latestProducts = Product::with('photos')->orderBy('created_at' , 'desc')->limit(10)->get();
return view('front.layouts.index' , compact('latestProducts'));
}
And in blade file try to remove the (), because it will load the relationship.
#foreach ($latestProducts->photos as $product)
<img src="{{$product->path}}">
#endforeach
How to convert Database Query Builder to Database Eloquent?
$products = DB::table('carts')
->join('products','.carts.product_id','=','products.id')
->where('carts.user_id',$userID) ->select('products.*')
->get();
As you've provided very little information to assist you with, some assumptions are going to be made such as naming conventions and relationship types.
Product.php
Add a carts relationship to your Product model. This assumes a Product can belong to many Carts.
public function carts()
{
return $this->belongsToMany(Cart::class);
}
Cart.php
Add a products relationship to your Cart model. This assumes a Cart can have many Products.
public function products()
{
return $this->belongsToMany(Product::class);
}
Create a pivot table which will maintain the relationships between Carts and Products:
php artisan make:migration create_cart_product_table
Then add your relationship foreign keys to the migration:
public function up()
{
Schema::create('cart_product', function (Blueprint $table) {
$table->id();
$table->foreignId('cart_id')->constrained();
$table->foreignId('product_id')->constrained();
$table->timestamps();
});
}
To add Products to a Cart, you can use the attach or sync methods, for example:
$products = Product::inRandomOrder()->take(5)->pluck('id');
Cart::create(['user_id' => 1])->products()->attach($products);
The above will get 5 Products (at random) from your products table, then create a new Cart with the given user id and attach those Products to the Cart.
To retrieve a Cart and it's associated Products, you would do the following:
$cart = Cart::where('id', $id)->with('products');
The $cart variable can be passed to a view or in a json response where after you can iterate over the Products in the Cart.
$cart = Cart::where('id', $id)->with('products');
return view('cart', compact('cart'));
blade view
<ul>
#foreach ($cart->products as $product)
<li>{{ $product->name }}</li>
#endforeach
</ul>
If you want to get all the Cart records for a given User, you would do the following:
$carts = Cart::where('user_id', $id)->with('products')->get();
return view('carts', compact('carts'));
blade view
#foreach ($carts as $cart)
{{ $cart->id }}
<ul>
#foreach ($cart->products as $product)
<li>{{ $product->name }}</li>
#endforeach
</ul>
<hr />
#endforeach
Or something to that effect.
Ok, so here is my problem : I have'nt found a proper solution to 'merge' (not sure if it is the right word for it) two collections in laravel. I'll show you my code, it'll explains itself.
So here is my crappy way-arround code, but I'm pretty sure there is a better way to do it :
Here is my controller :
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Product;
use App\ProductPhoto;
class ProductController extends Controller
{
public function index() {
$products = Product::all();
$photos = ProductPhoto::all();
return view('/products')->with([
'products' => $products,
'photos' => $photos
]);
}
}
and my view looks like this ;
#foreach($products as $product)
#foreach($photos as $photo)
#if($photo->product_id = $product->id)
<img src="/products/{{ $product->id }}/{{ $photo->filename }}">
#endif
#endforeach
#endforeach
But I'd like to have all the photos related to the product in the product collection. I'd like to have a simple view as :
#foreach($products as $product)
#foreach($product->photos as $photo)
<img src="/products/{{ $product->id }}/{{ $photo->filename }}"
#endforeach
#endforeach
Or another way simpler than that. I've been trying merge, but I don't think this is the one I need, I don't know. Or maybe the way I do it is the correct one, but I doubt it.
Thanks for reading !
I'd recommend using eloquent relationships for this. To do this you would want to create a relationship on the product class called photos. This would look something like this:
class Product extends Model
{
...
public function photos()
{
return $this->hasMany(ProductPhoto::class);
}
...
}
Once you have done this, you can update your controller as you no longer need to fetch the photos from the model. For performance, you could eager load the photos.
public function index() {
$products = Product::with('photos')->get();
return view('/products')->with([
'products' => $products
]);
}
Finally, you can update your view to use the photos relationship instead.
#foreach($products as $product)
#foreach($product->photos as $photo)
<img src="/products/{{ $product->id }}/{{ $photo->filename }}"
#endforeach
#endforeach
I hope that helps.
I don't usually like when people ignore the proposed example and tell you that there's a better way to do that... but there is a better way to do that:
for the Products Eloquent add a method called photos
Class Products extends Model{
...
public function photos(){
return $this->hasMany(Photos::class);
}
}
for the Photos Eloquent add a method called product
Class Photos extends Model{
...
public function product(){
return $this->belongsTo(Product::class);
}
}
now for the photos migration you need to add a column called product_id in case you're using this photos table only for products and not anything else like users.
if you want to be able to assign photos to multiple models like Users can have photos, then you need to consider using Morphs Polymorphic Relationships
when you want to add photos to the product you can then do
Product::find(1)->photos()->create(['filename'=>'....']);
That should add photos row assigned with the product.
Then in your view you can do something like:
#foreach(Products::all() as $_product)
<div>
{{$_product->title}
<div class="product_photos">
#foreach($_product->photos as $_photo)
<img .../>
#endforeach
</div>
</div>
#endforeach
I'm just showing you the correct way to achieve that instead of comparing photos with id and so on, your way will make it much slower.
Look up Laravel Relationships. That will take a bit of time like few minutes to convert your models to use Relationships but will save you days of coding later.
In Laravel 5.6 i have a polymorphic relationship .
I have many products in db and avatars for each product .
When i send products data to view i want to send avatar for every product .
I write a polymorphic relationship between avatars table and products table and i can access avatar of each product using this code easily :
$avatar = Product::find(id)->avatars()->first();
But when db result is NOT one product and is a array of products how i can access each avatar ?
If i have result like this how can i find avatar of each product in view file ? :
$products = Product::all();
return view('frontend/home')->with([
'products'=>$products,
]);
And in View i have something like this :
#foreach($products as $product)
<li>
#include('items.product')
</li>
#endforeach
You should be able to use with():
$products = Product::with('avatars')->get();
Then in your blade file you would have something like:
#foreach($products as $product)
<img src="{{ $product->avatars->first()->url }}" alt="" />
#endforeach
I have a hasmany relationship on my model and I'm trying to output just the one result, i have a product category which can display only one product image.
I have two tables.
1 = Product
2 = ProductPhotos
I've tried outputting the one photo like
#foreach($products as $product)
<img src="{{ $product->photos->first() }}">
#endforeach
I have the following relationship setup in my product model
public function photos()
{
return $this->hasMany('App\ProductPhoto', 'product_id');
}
but this doesnt work.
You're just missing the parenthesis for the method. It should be:
$product->photos()->first();
Which will allow Eloquent to access the photos method in the Product model.