there are two tables products and categories, that I created by PHPMyAdmin.
In the products table, it has a column name prd_category that has the foreign key of table categories named cat_id(primary key of categories table).
i am quite new in laravel
i want return all data from product table with category name(cat_name) from another table
//here is my controller
use App\Models\product;
class items extends Controller
{
public function sample(){
return product::all();
}
}
//route
Route::get('/',[items::class,'sample']);
//model for products table
class product extends Model
{
use HasFactory;
function category(){
return $this->hasOne('App\Models\category','cat_id','prd_id');
}
}
//model for category
class category extends Model
{
protected $table='categories';
use HasFactory;
}
pls help and thanks in advance..
you can use this code:
$products = product::whereHas('category',function($q)use($cat_name){
$q->where('name',$cat_name)
})->get();
or :
$categories = Category::where('name',$cat_name)->get()->pluck('id')->toArray()
$products = product::whereIn('category_id',$categories)->get();
Are you sure that one-to-many relation is correct? If a product can belong to many categories, you need to use many-to-many relations. Furthermore, if something else belongs to categories you should use many-to-many polymorphic relations. But let's go with one-to-many.
First, the relation function in Product.php looks incorrect. I think products should belong to a category.
function category(){
return $this->belongsTo('App\Models\Category','cust_name','name');
}
Then you need to define reverse relation in Category.php
function products(){
return $this->hasMany('App\Models\Product','cust_name','name');
}
When you define the relations properly, all you need yo do is to fetch data in controller:
use App\Models\Category
...
Category::with('products')->get();
you can use relationship with forign key like pro_id
function category(){
return $this->belongsTo('App\Models\Category','pro_id');
}
function products(){
return $this->hasMany('App\Models\Product','id');
}
$cat = Category::with('products')->all();
in Blade :
{{ $cat->products->cat_name; }}
Related
This is my tables structure:
Attribute.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Attribute extends Model
{
protected $guarded = [];
public function products()
{
return $this->belongsToMany('App\Product');
}
}
Product.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $guarded = [];
public function attributes()
{
return $this->belongsToMany('App\Attribute');
}
}
I want to get the value column for each row.
What code should I write in my controller to access this value?
Laravel version: 6.9.0
Thanks
You can solve this problem by adding the following method of your end of the relationship
withPivot(['value']);
public function attributes()
{
return $this->belongsToMany('App\Attribute')->withPivot(['value']);
}
And also
public function products()
{
return $this->belongsToMany('App\Product')->withPivot(['value']);
}
When we implements Many To Many relationship,it default create a intermediate table
In your case that table is attribute_product table, we might reference this table as Pivot
table.
This tables value was retrieve by those model by pivot attribute name as follows:
$product = App\Product::find(1);
foreach ($product->attributes as $attribute) {
echo $attribute->pivot->product_id;
}
To add Extra column in (Pivot table)
By default, only the model keys [$attribute_id,$product_id] will be present on the attribute_product table. If your pivot table contains extra attributes, you must specify them when defining the relationship:
return $this->belongsToMany('App\Attribute')->withPivot('column1', 'column2','value');
To change pivot Attribute Name to your given name
you may wish to rename your intermediate table accessor to values instead of pivot.
return $this->belongsToMany('App\Attribute')
->as('values')
Then you will retrieve by $attribute->values->product_id instead of $attribute->pivot->product_id
I am using laravel 5.3 and need a bit of help with Eloquent model queries. I have three models (UserDetails, Categories, Articles). I have a relationship between UserDetails->Categories (belongstoMany), and a relationship between Categories->Articles (belongstoMany) which work well. However how would I go about getting the relationship data between Userdetails->Categories->Articles.
Each individual relationship is working fine i.e. Userdetails::find(1)->categories and Categories::find(1)->Articles.
I have a feeling that scopes may be the answer but they don't seem to work when I've attempted it.
Relationships in models
UserDetails.php
public function Categories(){
return $this->belongstoMany('App\Categories', 'users_cats', 'user_id','cat_id');
}
Categories.php
public function articles(){
return $this->belongsToMany('App\Article', 'article_categories', 'categoryID', 'articleID');
}
Ive looked into HasManyThrough function but again, I'm having issues implementing it, as far as I can see it should be
return $this->hasManyThrough('App\Article', 'App\Categories', TertiaryForeignKey, FinalForeignKey, LocalForeignKey);
My tables are set up as
articles_categories pivot table
articleID – primary key of the article
categoryID – primary key of the category
users_cats pivot table
user_id – primary key of the userdetails
cat_id – primary key of the categories
Based on this it the hasManyThrough should look like this?
public function articles(){
return $this->hasManyThrough('App\Article', 'App\Categories', 'user_id', 'articleID', 'id');
}
however this returns the error
Column not found: 1054 Unknown column 'categories.user_id' in 'field list'
update
So if you want to have this kind of relationship
userdetails->categories->articles
then you need to make this:
Userdetail model:
public function categories()
{
return $this->hasMany(Category::class);
}
public function articles()
{
return $this->hasManyThrough(Article::class, Categories::class);
}
Category model:
public function userdetails()
{
return $this->belongsTo(Userdetails::class);
}
public function categories()
{
return $this->hasMany(Category::class);
}
Article model:
public function categories()
{
return $this->belongsToMany(Category::class);
}
Then you can call UserDetails::find(1)->articles->get(); directly
You just need to declare the relationship like this in the
UserDetails.php model:
public function categories()
{
return $this->hasMany(Categories::class);
}
in Categories.php model:
public function articles()
{
return $this->hasMany(Articles::class);
}
Then you can retrieve the collection of categories in your controller:
$userdetails = UserDetails::get();
pass that $categories variable into your View and display each record with an foreach loop (where the articles is the function in your model)
#foreach($userdetails->categories as $usercategories )
<div> {{$usercategories->name}} </div>
#foreach($usercategories->articles as $categoryarticles )
<div> {{$categoryarticles->name}} </div>
#endforeach
#endforeach
with the second foreach you will access the articles of the categories that belongs to the user.
In my Laravel application, I have a category listing page. When the user clicks on a certain subcategory, I'd like to list all the products and use pagination on that result. I'm already listing all the products related to that subcategory, for now, with the help of a subcategory ID:
public function subcategoryListing($slug){
$products = Subcategory::find($idofSubcat)->products;
return view('pages.subcategorylisting')
->with(array(
'products' => $products,
));
}
There are three classes involved in this structure: Category, Subcategory and Products. They were declared as follows:
Category
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Relation;
use App\Subcategory;
class Category extends Model
{
protected $table = 'category';
public $timestamps = false;
public function subCategory(){
return $this->hasMany('App\Subcategory', 'category_id');
}
}
Subcategory
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Subcategory extends Model
{
protected $table = 'subcategory';
public $timestamps = false;
public function products(){
return $this->hasMany('App\Products');
}
}
Products
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Products extends Model
{
protected $table = 'products';
}
For each model class I have one table, with this structure:
Category
- id
- category_name
SubCategory
- id
- category_id
- subcategory_name
Products
- id
- subcategory_id
- product_title
- description
- price
What I want is to paginate the results retrieved from the query in my page. Is there any better way to fetch the products associated to the subcategory and paginate them?
In Eloquent (Laravel's ORM) when you call a relation as a property ($subCategory->products), it returns the related object or a collection of objects depending on the relation type (belongs to, has many, ...). Instead, if you call it as a function ($subCategory->products()), you get a QueryBuilder instance.
Refer to http://laravel.com/docs/5.1/eloquent-relationships#querying-relations, under section Relationship Methods Vs. Dynamic Properties for more details on that.
Anyway, using the relationship method, you can call paginate() for your collection. Then, with that in mind, you can change your code slightly to get what you want:
public function subcategoryListing($slug) {
// I'm supposing here that in somewhere before
// run the query, you set the value to $idofSubcat
// variable
$products = Subcategory::find($idofSubcat)->products()->paginate();
return view('pages.subcategorylisting')
->with(array(
'products' => $products,
));
}
I think, that create two categories table not so correctly, it will be better to use next:
table categories
id category_name parent_id(nullable)
and Products
id category_id product_title description price
It's more usefull, you can remove one Subcategory model and do all in Category.
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $table = 'category';
public $timestamps = false;
public function subCategory(){
return $this->belongsToMany('App\Category', 'categories', 'id', 'parent_id');
}
public function products(){
return $this->hasMany('App\Products');
}
}
and products model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Products extends Model
{
protected $table = 'products';
public function category() {
return $this->belongsTo('App\Category')
}
}
then, you can get the query result
public function subcategoryListing($slug){
$products = Category::find($idofSubcat)->products;
return view('pages.subcategorylisting')
->withProducts($products); // it's a magic))
}
But, existing one not pretty thing. Do you really sure, that products will be only in one category?)
I couldn't really understand some of your initial function:
// $slug is not being used anywhere within the function
public function subcategoryListing($slug){
// $idOfSubcat isn't passed to this function so will throw an error
$products = Subcategory::find($idofSubcat)->products;
return view('pages.subcategorylisting')
->with(array(
'products' => $products,
));
}
If all you're trying to do is paginate the Products that belong to a specific subcategory_id, given you have the subcategory_id then the following code will work:
$products = Product::where('subcategory_id', $idofSubcat)->paginate();
Then you can return this paginated collection to your view as you're already doing:
return view('pages.subcategorylisting')
->with(compact('products'));
We work on a database where table names are named locally.
table.product
-- id
-- picture
-- category_id
table.category
-- id
-- caterory_name
-- category_directory
There are some products in table. product.category_id should point category.id so system will understand that product belongs to desired table.
We could do this by using INNER JOIN but we can't do it with Laravel. We probably need to configure our models with has/belongs_to etc.
This is where we struggle.
//Controller
$products = Product::all();
return View::make('theme-admin.product_list')
->with('products', $products);
//View (in foreach)
{{ URL::to('uploads/categories/[NEED_CATEGORY.CATEGORY_DIRECTORY_HERE]/' . $products[$k]->picture) }}
We can't get Category.category_directory info in our views since we pass Product::all() only.
How can we make it so the $products array also contains category.category_directory for each value and we can access it like; $products[$k]->category_name?
Thanks!
Create a category relation in your Product model:
class Product extends Eloquent {
private $table = 'myProductsTableName';
public function category()
{
return $this->belongsTo('Category', 'myCategoryColumnID');
}
}
class Category extends Eloquent {
private $table = 'myCategoriesTableName';
}
Unless you need to select all products from a particular category, you don't need to create a hasMany relation on your Category model.
And you just need to use myCategoryColumnID if your products table doesn't follow the singular_table_name_id rule (product_id).
Then just use it:
//View (in foreach)
{{ URL::to('uploads/categories/'.$products[$k]->category->category_directory.'/' . $products[$k]->picture) }}
I would setup a relationship...
class Product extends Eloquent {
public function category()
{
return $this->belongsTo('Category');
}
}
class Category extends Eloquent {
public function product()
{
return $this->hasMany('Product');
}
}
The name you use in the realtionship is the Model name.....so be sure if you're using a different table name than your model name, that you set that in your model
protected $table = "yourtablename";
Then use it like so...
{{ URL::to('uploads/categories/'.$products[$k]->category->category_directory.'/'
You still end up querying the database multiple times this way... This is called the N+1 effect. Example, if you have 5 products, one query will be executed to get those products. Then in the loop we are executing a query to get the category. This results in 6 total queries.
To solve this problem, use eager loading, which reduces those 6 queries in our example down to 2.
$products = Product::with('category')->get();
Then send that to your view, where you can do your foreach loop..
foreach($products as $val){
//To output the directory
echo $val->category->category_directory;
}
Or in blade...
#foreach($products as $val)
{{URL::to('uploads/categories/'.$val->category->category_directory.'/'.$val->picture)}}
#endfor
I am setting up several Models an want to know the correct approach to table structure and Model relationships.
Let's assume we have a shop containing products, each with properties size and color.
Table products
id
size_id
color_id
price
Table sizes
id
name
Table colors
id
name
Models
class Product extends Eloquent {
public function size() {
return $this->hasOne('Size', 'id');
}
public function color() {
return $this->hasOne('Color', 'id');
}
}
class Size extends Eloquent {
public function products() {
return $this->belongsTo('Product', 'size_id');
}
}
class Color extends Eloquent {
public function products() {
return $this->belongsTo('Product', 'color_id');
}
}
This way I can easily echo the color/size of a product using {{ Product->size['name'] }}. Also, I want to pass Eloquent the size's foreign key size.id like Product::where('size_id', '5') rather than its name size.name.
Problem: Doing $products = Product::has('size', '=', '5')->get() does not give me any results, yet doing $products = Product::where('size_id', '5')->get() does.
I am pretty confused, what went wrong?
I think that the problem is that your ::has() method is looking for products with exactly 5 different sizes on each specific product, which would assume that you would be using $this->hasMany('Size') in your Product model. Where as the ::where() method is returning results where the size of the product is 5.
In the documentation they use an example of comments. A post will have a list of comments. You can find posts that have at least one comment (ie. Post::has('comments')->get()) or you can find posts that have more than 3 comments (ie. Post::has('comments', '>=', '3')->get()).
http://laravel.com/docs/eloquent#querying-relations