I have two tables
product: id|category ...
category: id|name ...
product.category is a foreign key linked to category.id . I am building a basic CRUD and I would like to display all Products in the the product table as well as the name of the category they belong to rather than their category ID. TO do this, while searching the laravel documentation I came across the query builder and I achieved my goal.
public function index()
{
$products = \DB::table('products')
->join('categories', 'products.category', '=', 'categories.id')
->select('*')
->get();
return view('product' ,compact('products'));
}
Under my models for product and category I have created the appropriate relationships.
product.php :
public function category()
{
return $this->belongsTo('App\Category');
}
category.php :
public function products()
{
return $this->hasMany('App\Product');
}
I keep hearing about the power of Eloquent and was wondering how I could achieve a similar result with eloquent and if eloquent is designed for such operations or if the query builder is the right way to go.
Every tutorial online seems to only use the post and comments scenario of getting all comments belonging to a post.
You can use this code
public function index()
{
$products = Product::with('category')->get();
return view('product' ,compact('products'));
}
In blade
#foreach($products as $product)
{{$product->name}}
{{$product->category->name ?? ''}}
//or
#if ($product->category)
$product->category->name
#endif
#endforeach
Also if in project table foreign key is not equal category_id. In your case
public function category()
{
return $this->belongsTo('App\Category', 'category');
}
Related
I have looked through the forum, but the solutions I have seen so far, aren't aligning with the issues I'm getting, so, I was hoping someone more informed would help out.
So I have a Category modem and A post model and there relationship is as follows;
on post model:
public function postcategory(){
return $this->belongsTo(PostCategory::class);
}
on category model:
public function posts(){
return $this->hasMany(Post::class)->where('approved', 'true');
}
and I am using slugs to retrieve all the posts that belongs to a certain category slug, using this function:
public function cats($category){
$posts = PostCategory::where('category_slug', $category)->first()->posts;
$category = PostCategory::where('category_slug', $category)->first();
return view('posts', compact('posts', 'category'));
}
Now, I am trying to get the name of the category with the category id stored in the posts table. for example, if I have a category id of 1 and on the category table, if the id number 1 is PHP, how do I return the name PHP instead of the id 1?
Secondly, if I wanted to paginate the view where posts is being compacted to, how do I do that? I switched the code in the controller to this:
$posts = PostCategory::with('posts')->where('category_slug', $category)->paginate(15);
when I dd that line of code, it returns some values (with relations), but when I pass that to the view, I get errors.
Hopefully, someone see this and help me out. :D
on Category Model :
public function posts()
{
return $this->hasMany(Post::class);
}
On Controller :
public function cats($slug)
{
$category = PostCategory::whereSlug($slug)->firstorFail();
$posts= $category->posts()->where('approved', 'true')->paginate(15);
return view('category.show', compact('posts', 'category'));
}
On View :
#foreach($posts as $post)
$post->title
....
#endforeach
{{ $posts->links() }}
I've spent two days trying to solve this but I can't figure how.
I have five tables
Product
Category
Category_Product
Order
Order_Product
From the view,clicking on a category button I have to fetch all his ordered products with the relative category.
I have the current models:
Product Model
class Product extends Model
{
public function categories() {
return $this->belongsToMany('App\Category');
}
public function orders() {
return $this->belongsTo('App\Order');
}
}
Category Model
public function products() {
return $this->belongsToMany('App\Product');
}
Order Model
public function products() {
return $this->belongsToMany('App\Product');
}
Now the problem is that I can't figure how to fetch the data from the current tables.When I press a button I'm able to fetch the category from the Product Table,but I want to fetch from the Ordered_Products. I really can't figure how.
With this I'm able to fetch all the categories from Product
if (request()->category) {
$products = Product::with('categories')->whereHas('categories', function ($query) {
$query->where('slug', request()->category);
})->get();
}
With this instead,I'm able to fetch the ordered products.
$products = DB::table('order_product')
->join('products', 'order_product.product_id','=', 'products.id')
->where('order_product.user_id','=',$user_id)
->get();
For the latter, there's a better way to do it, that's for sure. I'm sorry if it's a dumb question but I'm rather new with this framework. I am using Laravel 7.2.
Basically Eloquent Model doesn't encourage joining tables to retrieve data. It should be joined only for filtering results (So you need to drop field of other table using ->select('original_table.*'))
In this case, you should simply retrieve categories at first. Then retrieve related data using relation property accessing.
e.g.
$categories = Category::query()
->with('products')
->where('slug', request('category'))
->get();
$products = $categories->flatMap->products;
$pivots = $products->map->pivot;
Solved using whereHas two times:
$products = Product::with('categories')->whereHas('categories',function($query){
$query->where('slug',request()->category);
})->whereHas('orders',function($query){
$query->where('orders.user_id',Auth::id());
})->get();
I have three models: products, category, product_category. A product may have many categories, and some categories may have a parent. You can find related relations below. I could show all categories with a foreach() loop, but I don't want to do that. I wish only to show the category, and it must be the latest. Is there a way to show only the last category of a parent category of the current product?
<div class="row">
#foreach ($products as $product)
#foreach ($product->categories as $cat)
{{ $cat->title }}
#endforeach
#endforeach
</div>
Product model
public function categories()
{
return $this->belongsToMany(Category::class);
}
Category model
public function products()
{
return $this->belongsToMany(Product::class);
}
public function subcategories()
{
return $this->hasMany('\App\Category', 'parent_id');
}
public function parent()
{
return $this->belongsTo('\App\Category', 'parent_id');
}
Categories schema
$table->increments('id');
$table->string('title');
$table->integer('parent_id')->nullable();
Category_product schema
$table->increments('id');
$table->integer('category_id')->unsigned();
$table->integer('product_id')->unsigned();
You can use query builder on the relationship like so:
$product->categories->orderBy('id', 'desc')->first();
That will order from most recent to oldest and you can just take the first record.
You can simply use
$product->categories()->orderBy('id', 'DESC')->first();
Or you can also try
public function categories()
{
return $this->belongsToMany(Category::class)->orderBy('id','DESC');
}
Then you can use
$product->categories()->first();
Using specific methods on your model
Your categories definition would be something like this, right?
public function categories() {
return $this->belongsToMany(Category::class);
}
So, just create another method to retrieve only the latest.
public function latestCategory() {
return $this->categories()->latest();
}
If you need the oldest category, the same approach is applied.
public function oldestCategory() {
return $this->categories()->oldest();
}
Using only the categories relationship definition
You could also apply a different approach if you do not intend to create new methods:
$this->categories()->latest();
or
$this->categories()->oldest();
Hope it will help you.
Have a great day.
You can use latest() method
$product->categories->latest()->first();
Or,
$product->categories->orderBy('id', 'desc')->first();
I have categories and products tables. They are related with Many to Many relationships.. I want to get products by categories and selected price range but whereHas clause dosen't work
$products = Product::whereHas('categories',function ($query) use ($slug){
$query->where('category_slug',$slug);
})->whereBetween('price',[100,200])->get();
Category Model;
public function products(){
return $this->belongsToMany('App\Product','category_product','category_id','product_id');
}
Product Model;
public function categories() {
return $this->belongsToMany('App\Category','category_product','product_id','category_id');
}
So, what is my mistake in here ?
I have two tables, say Products and Biddings where one product can be bid by many users. Naturally I have two models:
class Product extends Model
{
public function biddings()
{
return $this->hasMany('App\Bidding');
}
}
class Bidding extends Model
{
public function product()
{
return $this->belongsTo('App\Product');
}
}
So, say I want to get all products along with the highest priced bidding I did something like this.
$productBidding = DB::table('biddings')
->select('*', DB::raw('max(price) as price'))
->join('products', 'products.id', '=', 'biddings.product_id')
->groupBy('product_id')
->get();
That works well BUT I kinda want to do it Eloquent way. So how do I convert Query Builder way to Eloquent? I am currently on this but do not know how to put the "max" condition in.
$productBidding = Products::with('biddings')
->get();
$productbinding=Bidding:with('product')
->get();
foreach($productbinding as $productbind)
{
echo $productbind->product->name; // example
}
I would extract the highest bid to a separate function on the Product model, like so:
public function highestBid() {
return $this->biddings()->max('price');
}
Then fetch the products and get the highest bid:
$products = Product::get();
foreach ($products AS $product) {
echo $product->highestBid();
}