one to many relationship help in laravel 4 - php

I am trying to create a relationship between Category and Product but somehow I couldn't use the category to connect into the product table and prints out the product names and instead I get the category's name
in my database
Table Name: products
Columns: id, name, price, category_id, description
Table Name: categories
Columns: id, name, description
in products table
id: 1
name: product1
price: 10
category_id: 1
description: p1
---------------
id: 2
name: product2
price: 10
category_id: 1
description: p2
in categories table
id: 1
name: category1
description: c1
---------------
id: 2
name: category2
description: c2
Product.php inside models folder
class Product extends Eloquent
{
protected $product = 'products';
public function category()
{
return $this->belongsTo('Category');
}
}
Category.php inside models folder
class Category extends Eloquent
{
protected $category = 'categories';
public function product()
{
return $this->hasMany('Product', 'category_id');
}
}
ProfileController.php in controller folder
class ProfileController extends BaseController
{
public function user($username)
{
$user = User::where('username', '=', $username);
if ($user->count())
{
$user = $user->first();
$title = 'User Profile';
$category = Category::find(1);
$products = Category::find(1)->name;
return View::make('profile.user', compact('user', 'title', 'category', 'products'));
}
return 'User Not Found. Please Create an Account';
}
}
user.blade.php inside profile folder which is inside view folder
#extends('layouts.master')
#section('content')
{{ Auth::user()->username }}
<br>
{{ Auth::user()->email }}
<br>
<h1>{{ 'Category name: '. $category->name }}</h1>
<br>
<h3>{{ 'Category Description: ', $category->description }}</h3>
<br>
{{ $products }}
#stop
at first where the {{$products}} I used a foreach loop
#foreach($products as $product)
{{$product}}
#endforeach
but then I got this error
ErrorException
Invalid argument supplied for foreach() (View: J:\wamp\www\test\app\views\profile\user.blade.php)
so I tried var_dump($products) and realized $products gives out category1 which is the name of the category but what I want is printing the name of all the products which has category_id 1
Can someone give me a hand with this? Did I mess something up with the relationship or I did something stupid with the codes?

In your controller:
$category = Category::find(1);
$products = $category->product;
Then in your template you can use:
#foreach ($products as $product)
{{ $product->name }}
#endforeach
Better yet you could use eager loading and forget about assigning products manually:
Controller:
$category = Category::with('product')->where('id', 1)->first();
Template:
#foreach ($category->product as $product)
{{ $product->name }}
#endforeach
PS: Read more on eager loading here: http://laravel.com/docs/eloquent#eager-loading
in order to prevent the dreaded N + 1 query problem!

Related

Laravel Query Builder create looping data from category

I am quite new in Laravel. I've googled with this keyword but no luck.
I use Laravel 8. Currently I need to view data from each category, so it will be like this on blade:
cat A
product A1 <img src=(get from thumbnail)>
product A2 <img src=(get from thumbnail)>
cat B
product B1 <img src=(get from thumbnail)>
product B2 <img src=(get from thumbnail)>
etc...
Currently my controller is:
$categories = DB::table('tbl_categories')
->orderBy('name')
->get();
foreach($categories as $key) {
$data = DB::table('tbl_product')
->where('status','Enable')
->where('category_id',$key->id)
->get();
}
$thumbnail = DB::table('tbl_thumbnails')
->where('product_id',$data[0]->id)
->get();
return view('/products', ['categories' => $categories, 'data' => $data, 'thumbnail' => $thumbnail]);
in my blade:
#foreach($categories as $discover_category)
<div>
#foreach($data as $discover)
#foreach($thumbnail as $a)
<!-- product name and thumbnail in here-->
#endif
#endif
</div>
#endif
But the result is now show only last category_id. please help. GBU.
you need to use first() to get single value like this
foreach($categories as $category) {
$products = DB::table('tbl_product')
->where('status','Enable')
->where('category_id',$category->id)
->get();
foreach ($products as $product) {
$thumbnail = DB::table('tbl_thumbnails')
->where('product_id',$product->id)
->first();
// assign value to $product
$product->thumbnail = $thumbnail;
}
// assign value to $category
$category->products = $products;
}
then in view you can use like
#foreach($categories as $category)
<div>
#foreach($category->products as $product)
<div>
<p>{{$product->name}}</p>
<p>{{$product->thumbnail->id}}</p>
</div>
<!-- product name and thumbnail in here-->
#endif
</div>
#endif
You can use Eloquent ORM, Just simply use this kind of code on your category model like:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
/**
* Get the products for the category.
*/
public function products()
{
return $this->hasMany(Product::class);
}
}
On controller like
$categories = Category::all();
return view('products', ['categories' => $categories]);
On Blade like
#foreach($categories as $category)
<div>
<div>{{ $category->name }}</div>
#foreach($category->products as $products) // here this products object called form model
#foreach($products as $product)
<!-- product name and thumbnail in here-->
#endforreach
#endforreach
</div>
#endforeach
Note
Note: You must perfectly make the relationship between the products table and categories table. Products table must have a column named category_id

PHP Laravel how to sort by using two tables

I have two MySQL tables in my Laravel-application, one called categories and the other called employees. The structure of the categories-table is:
id
category
order
and the employees table also has columns called:
id
category
order
So, lets say I have categories like: Consultants, Programmers and Administration and when I create an Employee in the backend I can assign the new employee to one of these categories. Now in the frontend of my Laravel-application I want the Employees displayed by the categories, and also the categories by order they are given. Let's say Consultants has order of 2, Programmers order of 1 and Administration order of 3.
Right now my controller looks like this:
use App\Employee;
class EmployeesController extends Controller
{
public function index()
{
$employees = Employee::all()->groupBy('category');
return view('app.employee.index', compact('employees'));
}
}
and my blade view file:
#foreach ($employees as $category => $workers)
<div class="col text-center mb-6">
<h2>{{ $category }}</h2>
</div>
<div class="row px-4 px-xl-10">
#foreach($workers->sortBy('order') as $worker)
// content of the employee
#endforeach
</div>
#endforeach
This sorts the employees correctly by simply using the categories of the Employees-table but with this I'm not able to sort by categories like I want to as described above.
So, can someone help me out?
EDIT
As an example I want the output look like this:
Programmers (since this category has order of 1)
// employees with category "programmers" here
Consultants (2)
// employees with category "consultants" here
Administration (3)
// employees with category "administration" here
To me you column definitions are a bit confusing, may I suggest a change to your columns:
Table 'categories'
------------------
id
name
order
Table 'employees'
-----------------
id
category_id
Add a foreign key to the employees table:
$table->foreign('category_id')->references('id')->on('categories')
And then your models could be mapped to each other with relationship methods:
class Employee extends Model
{
public function category()
{
return $this->belongsTo(Category::class);
}
}
class Category extends Model
{
public function employees()
{
return $this->hasMany(Employee::class);
}
}
So with this in place we can simply query the database from the controller by:
use App\Category;
class EmployeesController extends Controller
{
public function index()
{
$categories = Category::orderBy('order')->get();
return view('app.employee.index', compact('categories'));
}
}
and display the results in your blade view:
#foreach ($categories as $category)
<div class="col text-center mb-6">
<h2>{{ $category->name }}</h2>
</div>
<div class="row px-4 px-xl-10">
#foreach($category->employees as $employee)
// content of the employee
#endforeach
</div>
#endforeach
I think you must change your query to :
$categories = Category::with(['employees'=>function($q){
$q->orderBy('order');
}])->orderBy('order')->get();

Laravel 5 get data other table

I have the next stucture: table menus(id, title, type, parent_id, page_id) and
pages(id, alias title,content)
Model Menu
class Menu extends Model
{
public function parent()
{
return $this->belongsTo('App\Menu', 'parent_id');
}
public function children()
{
return $this->hasMany('App\Menu', 'parent_id');
}
public function page()
{
return $this->belongsTo('App\Page', 'page_id');
}
}
I want get the next result:
-Item 1 (show name menu table)
-Item 2
-Subitem 1 and alias (show name **menu** table and show alias **page** table)
-Subitem 2 and alias
-Item 3
- Suitem 1 and alias
Eloquent query
$items = Menu::with(['children' => function($query){
$query->with('page');
}])->where(['parent_id' => null])->get();
view
#foreach($items as $item)
#if($item->children()->count() > 0)
#foreach($item->children as $child)
<li>{{$child->title}}</li>
#endforeach
#else
<li><a href="/page/{{$item->page->alias}}">{{$item->title}}
#endforeach
How get alias page nested in foreach ?
You can use:
{{ $child->page->alias }}
to display child menu page alias assuming you have page for each child.
Otherwise you can use:
{{ optional($child->page)->alias }}
if you are running Laravel 5.5 or:
{{ $child->page ? $child->page->alias : '' }}
if you are running Laravel < 5.5
Also you could improve eager loading and code a bit:
$items = Menu::with('children.page', 'page')->whereNull('parent_id')->get();

Don't show empty parent category in Laravel

I have parent and child categories on the page. What I'm trying to do is when there is no products and no sub-categories assigned in some parent category to not be shown on the page.
So I have this in Category model
public function item()
{
return $this->hasMany('Item','category_id');
}
public function children()
{
return $this->hasMany('App\Category', 'parent_id');
}
public function getCategories()
{
$categoires = Category::where('parent_id',0)->get();
$categoires = $this->addRelation($categoires);
return $categoires;
}
public function selectChild( $id )
{
$categoires = Category::where('parent_id',$id)->where('published', 1)->get();
$categoires = $this->addRelation($categoires);
return $categoires;
}
This in the controller
public function index()
{
$Category = new Category;
$allCategories = $Category->getCategories();
return view('frontend.home', compact('allCategories', 'unviewedMessagesCount'));
}
And this on the blade view
#foreach($allCategories as $category)
{!!$category->title!!} ({!! $category->itemCount!!})
<p class="card-text">
#foreach($category->subCategory as $subcategory)
{!!$subcategory->title!!} {!! $subcategory->itemCount !!}
#endforeach
</p>
View Category
#endforeach
This is sample of the records in category table there are column
id | title | parent
1 Main cat 0
2 Sub-Cat 1
3 Sub-Cat 2 1
4 Main cat 2 0
So each parent is 0 and each child(sub category) has the parent ID
item table has also reference to category table -> column category_id
I can't figured it out how to make the condition if no items and no childs to not show it on page.
In Controller
$allCategories = Category::where('parent_id', 0)->has('children.item')
->with(['children'=> function($query){
$query->withCount('item');
}])
->get()
->each(function($parentCategory){
// if you wants calculate sum child category item count and assign to parent category item_count.
$parentCategory->item_count = $parentCategory->children->sum(function ($child) { return isset($child->item_count)?$child->item_count:0;});
});
return view('frontend.home', compact('allCategories'));
In this query only one query will be executed and it return all of your needs.
And In Blade View file
#foreach($allCategories as $category)
{!!$category->title!!} ({!! $category->item_count!!})
<p class="card-text">
#foreach($category->children as $subcategory)
{!!$subcategory->title!!} {!! $subcategory->item_count !!}
#endforeach
</p>
View Category
#endforeach

Puling a specific item from a foreach loop in Laravel

I have a project with 2 tables(Categories and products). They have One to Many relationship. Many products have one Category. Am pulling products of a specific category(together with its price and description) and storing in one variable so that I can use in the view. In the view am having a foreach loop whereby I want to display each row from the products table of a specific category(a product with its price and description) but it fails,,please assist?
FrontController
public function itemOne() {
//Get all phones(Have category of 1 ) in categories table
$mobile = Category::find(1)
->products()
->whereNotNull("image")
->whereNotNull("name")
->whereNotNull("description")
->whereNotNull("price")
->whereNotNull("category_id")->get();
return view('front.products')->withItems($mobile);
}
Products.blade.php
#foreach($items as $item)
<img src="{{ asset('images/'.$item->image) }}">
<br> {{ $item->name}} <br> {{ $item->price }}
#endforeach
public function itemOne() {
//Get all phones(Have category of 1 ) in categories table
$mobile = Category::find(1)
->products()
->whereNotNull("image")
->whereNotNull("name")
->whereNotNull("description")
->whereNotNull("price")
->whereNotNull("category_id")->get();
return view('front.products',compact('items'));
}
use compact in return

Categories