Laravel 8 eloquent querying with relations - php

I want to display all the products that have at least one image, then I display one of the image as the card's cover. But the query I made is displaying cards as many as images in the database.
Models
class Product extends Model {
public function getAllData()
{
$data = DB::table('product')
->select('product.*', 'product_images.img')
->join('product_images', 'product_images.product_id', '=', 'product.id')
->paginate(9);
return $data;
}
}
class ProductImage extends Model
{
public function product()
{
return $this->belongsTo(product::class);
}
}
Controller
public function index()
{
$img = ProductImage::find(1);
$data = [
'card' => $img->product->getAllData(),
];
return view('view', $data);
}
View
#foreach ($card as $item)
<div class="card shadow m-3" style="width: 18rem; heigth:24rem">
<div class="inner">
<img class="card-img-top" src="{{$item->img}}" alt="Card image cap">
</div>
<div class="card-body text-center">
<h5 class="card-title">{{$item->name}}</h5>
<p class="card-text">{{$item->description}}</p>
Check them out...
</div>
</div>
#endforeach
So I want to retrieve all Product instances with ProductImage instances in single array $card. What is the right way to do this?
Thanks in advance.

What I understand from you're requirement is you want to display all the products which have atleast 1 image against a product.
public function index()
{
$products = Product::has('image')
->with('image')
->get();
$data = [
'card' => $products,
];
return view('view', $data);
}
This will return all the products which has 1 image and the image can be used via image relation
#foreach ($card as $item)
<div class="card shadow m-3" style="width: 18rem; heigth:24rem">
<div class="inner">
<img class="card-img-top" src="{{$item->image->img}}" alt="Card image cap">
</div>
<div class="card-body text-center">
<h5 class="card-title">{{$item->name}}</h5>
<p class="card-text">{{$item->description}}</p>
Check them out...
</div>
</div>
#endforeach
Product Model
class Product extends Model
{
public function image()
{
return $this->hasOne(ProductImage:class);
}
public function images()
{
return $this->hasMany(ProductImage:class);
}
}
I have only used Laravel Eloquent, so the way I've shown the rendering of the products in view might be wrong

Related

My show function is not working in Laravel. URL shows the particular id, but in the page data won't come

When I click on a particular product on the products page, it directed me to the single product page. Particular product ID also showing in the URL. But data won't be passed. My single product page doesn't show the particular product data.
This is my Controller.
SingleProductController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Product;
use App\Category;
class SingleProductController extends Controller
{
public function index(Product $product)
{
$arr['product'] = $product;
return view('singleproducts')->with($arr);
}
public function create()
{
//
}
public function store(Request $request)
{
//
}
public function show($id)
{
$product = Product::find($id);
return view ('singleproducts')->with(['product'=>$product]);
}
public function edit($id)
{
//
}
public function update(Request $request, $id)
{
//
}
public function destroy($id)
{
//
}
}
This is my blade file.
singleproducts.blade
#extends('layouts.singleproducts')
#section('content')
<h2 class="font-size-25 text-lh-1dot2">{{ $product ['prod_name'] }} </h2>
<div class="mb-4">
<div class="d-flex align-items-baseline">
<ins class="font-size-36 text-decoration-none">{{ $product ['prod_price'] }}</ins>
<del class="font-size-20 ml-2 text-gray-6">$2,299.00</del>
</div>
</div>
#endsection
This is my route.
web.php
Route::get('/singleproducts', 'SingleProductController#index')->name('singleproducts');
Route::get('/singleproducts/{id}', 'SingleProductController#show')->name('eachproduct');
Why my show function is not working?
route.php
Route::get('/singleproducts', 'SingleProductController#index')->name('singleproducts');
Route::get('/eachproduct/{id}', 'SingleProductController#show')->name('eachproduct');
Product List Page
#if (isset($products) && count($products) > 0)
#foreach ($products as $product)
<div class="blog_box_inner" style="cursor: pointer;" >
<h1 class="blog_inner_heading">
<a href="/eachproduct/{{$product['id']}}" class="blog_readmore_link">
{{$product['prod_name']}}
</a>
</h1>
</div>
#endforeach
#endif
Single page
<h2 class="font-size-25 text-lh-1dot2">{{ $product['prod_name']}} </h2>
Controller
public function index() {
$products = Product::orderBy('id', 'DESC')->get();
return view('')->with(compact('products'));
}
public function show($id) {
$product = Product::find($id);
return view('')->with(compact('product'));
}
Hope fully it will help to you easily.
Use like this
return view('singleproducts',compact('product'));
In your view use like this
<h2 class="font-size-25 text-lh-1dot2">{{ $product->prod_name }} </h2>
<ins class="font-size-36 text-decoration-none">{{ $product->prod_price }}</ins>
Try this
public function show(Product $product)
{
return view ('singleproducts', compact('product'));
}
and pass in route
Route::get('/eachproduct/{product}', 'SingleProductController#show')->name('eachproduct');
and in your view page get product data as
singleproducts.blade
#extends('layouts.singleproducts')
#section('content')
<h2 class="font-size-25 text-lh-1dot2">{{ $product->prod_name }} </h2>
<div class="mb-4">
<div class="d-flex align-items-baseline">
<ins class="font-size-36 text-decoration-none">{{ $product->prod_price }}</ins>
<del class="font-size-20 ml-2 text-gray-6">$2,299.00</del>
</div>
</div>
#endsection
It will auto find your product on base of id.

Laravel Collection get one of values by key

I'm new to Laravel and I'm trying to get one of the values in one collection by one ID retrieved from another collection.
My function returns 2 Collections:
public function index()
{
$category = BlogCategory::all(['id', 'name']);
$post = BlogPost::orderBy('id', 'desc')->take(14)->get();
return view('blog.index', ['posts' => $post], ['categories' => $category]);
}
In a foreach loop I'm getting values from collections:
#foreach($posts as $post)
#if($loop->iteration > 2)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $categories->get($post->category_id) }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
#endif
#endforeach
I'm partially getting the result as you can see in the image below, but I want to get only the name.
Here is the code that I'm trying to figure out
{{ $categories->get($post->category_id) }}
If there is a better or correct way to do it, let me know.
Blog Posts migration:
public function up()
{
Schema::create('blog_posts', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('title');
$table->longText('content');
$table->mediumText('slug');
$table->bigInteger('author_id')->unsigned();
$table->bigInteger('category_id')->unsigned();
$table->timestamps();
$table->foreign('author_id')->references('id')->on('blog_authors');
$table->foreign('category_id')->references('id')->on('blog_categories');
});
}
You should put in place the relationships between BlogPost and BlogCategory models, seen that you already have a category_id field in BlogPost model, i.e.:
in BlogPost Model:
public function category(){
return $this->belongsTo(\App\BlogCategory::class);
}
in BlogCategory Model:
public function posts(){
return $this->hasMany(\App\BlogPost::class);
}
Next you can eager load categories with the $posts in your controller with only two queries:
public function index()
{
$posts = BlogPost::with('category')->orderBy('id', 'desc')->take(14)->get();
return view('blog.index', compact('posts'));
}
Then in your view you can access each $post->category object directly because eager loaded in the controller:
#foreach($posts as $post)
#if($loop->iteration > 2)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $post->category->name }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
#endif
#endforeach
It could be optimized, first, you need to make relation one to many from categories to posts
first: make sure that you have in posts migrations category_id column
Second: Open Category Model and write this method this will allow you to fetch posts that belong to the category
public function posts(){
return $this->hasMany(\App\Post::class);
}
Third: open shop model and write this method this will allow you to fetch category that belongs to the post
public function catgeory(){
return $this->belongsTo(\App\Category::class);
}
Finally: you will edit your view like this one
#foreach($posts as $post)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $post->category->title }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
#endforeach
and of course, you wouldn't call categories in your controller anymore
public function index()
{
$post = BlogPost::orderBy('id', 'desc')->take(14)
->with('category')->get();
return view('blog.index', ['posts' => $post]);
}
Maybe it better use a relation to drive this situation. You can load in the controller the data in this way.
In the Model Post:
function categories(){
return $this->belongsToMany('App\BlogCategory')->select(array('id', 'name');
}
Maybe is hasOne -> the relationship if you don't have a table pivot...
In the Controller:
public function index()
{
$data['posts'] = BlogPost::orderBy('id', 'desc')->take(14)->with('categories')->get();
return view('blog.index', $data);
}
In the View:
#foreach($posts as $post)
#if($loop->iteration > 2)
<div class="col-sm-6 col-md-3 d-flex justify-content-center other-post">
<a href="#">
<img src="#" alt="">
<p class="post-category">{{ $post->categories->name }}</p>
<h5 class="post-title">{{ $post->title }}</h5>
</a>
</div>
#endif
#endforeach
this line $categories->get($post->category_id) return for you an array of category, so the solution for you here is just like bellow:
{{ $categories->get($post->category_id)['name'] }}

Query AncestryOf with Laravel-nestedset in Laravel 5.8

I am using Laravel-nestedset and am having a hard time querying the ancestrosOf my category model.
This is what I am trying to do:
Works
http://carnival-experts.test/categories (this gives me a list of all categories)
http://carnival-experts.test/categories/carnival-games (this gives me a list of all Carnival Games)
Does Not Work
http://carnival-experts.test/categories/carnival-games/large-scale-games (this shows me a list of Carnival Games and not the Large Scale Games category)
I am sure this is just my lack of understanding--any help appreciated.
web.php
...
Route::get('/', 'CategoryController#index')->name('categories');
Route::get('/{category}/{slug?}', 'CategoryController#show')->name('show');
...
CategoryController.php
...
class CategoryController extends Controller
{
public function index()
{
$categories = Category::get()->toTree();
return view('categories.index', compact('categories'));
}
public function show(Category $category, $slug = null)
{
if (!is_null($slug)) {
$categories = Category::ancestorsOf($category);
return view('categories.show_subcategory', compact('categories', 'category', 'slug'));
} else {
return view('categories.show', compact('category'));
}
}
}
show_category.blade.php
...
#foreach($category['children']->chunk(3) as $chunk)
<div class="row">
#foreach($chunk as $category)
<div class="col-md-4" style="margin-bottom: 2rem">
<div class="feature-box center media-box fbox-bg">
<div class="fbox-media">
<a href="/categories/{{$category->slug}}">
<img class="image_fade"
src="https://*****.s3-us-west-1.amazonaws.com/{{ $category->photo }}"
alt="Featured Box Image"
style="opacity: 1;"></a>
</div>
<div class="fbox-desc">
<h3>{{$category->name}}</h3>
<span>Learn More</span>
</div>
</div>
</div>
Products
#if(count($category->products) > 0)
#foreach($category->products as $product)
{{$product->title}}
#endforeach
#endif
#endforeach
</div>
#endforeach
...

Display posts belonging to category in laravel

I am trying to get the posts that belong to each category, i had this working before but i can't seem to find what i have done wrong here.
I have a Post Table and a Categories Table
ROUTE
Route::get('articles/category/{id}', ['as' => 'post.category', 'uses' => 'ArticlesController#getPostCategory']);
CONTROLLER
public function getPostCategory($id)
{
$postCategories = PostCategory::with('posts')
->where('post_category_id', '=', $id)
->first();
$categories = PostCategory::all();
// return view
return view('categories.categoriesposts')->with('postCategories', $postCategories)->with('categories', $categories);
}
VIEW
#foreach($postCategories->posts as $post)
<div class="well">
<div class="media">
<a class="pull-left" href="#">
<img class="media-object" src="http://placekitten.com/150/150">
</a>
<div class="media-body">
<h4 class="media-heading">{{ substr($post->title, 0, 50) }}</h4>
<p class="text-right">By Francisco</p>
<p>{{ substr($post->body, 0, 90) }}</p>
<ul class="list-inline list-unstyled">
</ul>
</div>
</div>
</div>
#endforeach
POST MODAL
public function postCategory()
{
return $this->belongsTo('App\PostCategory');
}
POSTCATEGORY MODAL
class PostCategory extends Model
{
// connect Categories to Posts tables
protected $table = 'post_categories';
// Category belongs to more than 1 post
public function posts()
{
return $this->hasMany('App\Post', 'post_category_id');
}
}
I can't see what i am doing wrong every time I go to a category it shows
Trying to get property of non-object
Any help will be much appreciated thanks
replace your lines:
$postCategories = PostCategory::with('posts')
->where('post_category_id', '=', $id)
->first();
with:
$postCategories = PostCategory::find($id)->posts;
Change your line in your PostCategoryModel to:
return $this->hasMany('App\Post', 'post_category_id','post_category_id');

How I use relationship in blade template (hasOne) || Laravel

Okay i'm trying get "likes" and "users" in Posts by relationship hasOne.
here is my Post.php Model
class Posts extends Model
{
protected $table = 'posts';
public function User()
{
return $this->hasOne(User::class, 'id', 'user_id');
}
public function Like()
{
return $this->hasOne(Like::class, 'post_id', 'id');
}}
My Blade template
#foreach ($showdeals as $deal)
<div class="tab-pane active" id="home" role="tabpanel">
<div class="card-body">
<div class="profiletimeline">
{{$deal->like->status}}
<br>
{{$deal->user->email}}
<div class="sl-item">
<div class="sl-left"> <img src=" {{asset( '/assets/images/users/2.jpg')}}" alt="user" class="img-circle"> </div>
<div class="sl-right">
<div> {{$deal->user->username}} || {{$deal->subject}} <Br> <span class="sl-date">{{$deal->created_at}}</span>
<div class="m-t-20 row">
<div class="col-md-3 col-xs-12"><img src="{{$deal->image}}" alt="user" class="img-responsive radius"></div>
<div class="col-md-9 col-xs-12">
<p> {{$deal->body}} </p> עבור למוצר </div>
</div>
<div class="like-comm m-t-20"> 2 תגובות <i class="fa fa-heart text-danger"></i> 5 לייקים </div>
</div>
</div>
</div>
</div>
<hr></div>
</div>
#endforeach
And there is my Controller
class PostsController extends Controller
{
public function showdeals()
{
$showdeals = Posts::with( 'User', 'Like')->get();
return view('posts.show', compact('showdeals'));
}
public function helpnewview(){
return view('posts.anew');
}
public function helpnew(Request $request){
//User pick link
$userlink = $request['userlink'];
return \Redirect::route('newdeal', compact('userlink'));
}
public function new(Request $request)
{
//Emdeb user link
$link = Embed::create($request['userlink']);
$linke = $request['userlink'];
return view('posts.new', compact('link', 'userlink', 'linke'));
}
public function create(Request $request)
{
$posts = New Posts;
$posts->user_id = Auth::User()->id;
$posts->subject = $request['subject'];
$posts->body = $request['body'];
$posts->link = $request['link'];
$posts->price = $request['price'];
$posts->image = $request['image'];
$posts->tag = $request['tag'];
$posts->save();
return back();
}
}
Now if I do something like {{$deal->user->email}} its will work,
if I go to something like this {{$deal->like->status}} its does not work,
am I missing something ?
If you want multiple relationships to be eagerly loaded you need to use an array of relationships: Model::with(['rl1', 'rl2'])->get();
public function showdeals()
{
...
$showdeals = Posts::with(['User', 'Like'])->get();
...
}
EDIT:
From that json in the comments that I see, there is no attribute named status in your Like model so thats probably the root of the problem
Controller edit this code
public function showdeals()
{
$showdeals = Posts::all();
return view('posts.show', compact('showdeals'));
}
And blade file code
#foreach ($showdeals as $deal)
<div class="tab-pane active" id="home" role="tabpanel">
<div class="card-body">
<div class="profiletimeline">
{{ $deal->Like->status }}
<br>
{{ $deal->User->email }}
#endforeach
I think everything is good except
{{$deal->like->status}} {{$deal->user->email}}
Please try as
{{$deal->Like()->status}}
<br>
{{$deal->User()->email}}

Categories