Lets say there are three tables:
categories
id
image_categories
image_id
category_id
images
id
My idea was that an image has multiple categories so I made a cross reference table to attach a category to an image. In my cross table (image_categories) i create a reference with image_id to the image table and category_id to the category table
Now I need to find all images that belong to a category so in my class Category I add.
public function images(){
return $this->hasManyThrough('App\Image', 'App\ImageCategory');
}
But I get an error that the column is not found.
Unknown column 'image_categories.id' in 'on clause' (SQL: select `images`.*,
`image_categories`.`subcategory_id` from `images` inner join `image_categories`
on `image_categories`.`id` = `images`.`image_category_id` where
`image_categories`.`subcategory_id` = 29)
if I look at the docs it says:
Has Many Through
The "has many through" relation provides a convenient short-cut for
accessing distant relations via an intermediate relation. For example,
a Country model might have many Post through a User model. The tables
for this relationship would look like this:
It sounds ideal for situations like this but what am I doing wrong?
If the category has multiple images and image has multiple categories, here you have a many to many relationship, the name of your pivot table will be category_image (Eloquent will join the two related model names in alphabetical order) and it should contain a both ids of the two tables as foreign key (you can add more argument to the table if you need it).
So just follow instruction in laravel docummentation Many To Many and it will work smoothly.
Note : If you Need to find all images that belong to a category so in your class Category define the images() function like bellow :
public function images(){
return $this->hasMany('App\Image');
}
Related
I have 2 tables structured as such:
videos table
id
comments table
id
commentable_id
commentable_type
text
And each has their own model.
Video has the following relationship to comment:
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
Here's where it get's a bit interesting though, because comments can have comments under them at 1 level, so a top level comment can contain any number of child replies but the children cannot have replies on them.
That is represented by the following relationship on the Comment model:
public function replies()
{
return $this->morphMany(__CLASS__, 'commentable');
}
The problem
I need to now sort these by a combined sum between the comment AND comment replies count.
I've tried adding a hasManyThrough relationship on the parent (Video) model but that ends up failing because the table isn't aliased (since there are technically comments through comments to get to replies).
How would I represent this relationship in laravel on the video model? What I've tried seems fruitless
SQL
I thought maybe writing out the SQL might help, but since Laravel doesn't seem to alias table names, it seems almost impossible to convert this into a provided laravel relationship
SELECT replies.*
FROM comments
RIGHT JOIN comments AS `replies`
ON `replies`.commentable_id = `comments`.id AND `replies`.commentable_type = 'comment'
WHERE `comments`.commentable_id = 'VIDEO ID'
AND `comments`.commentable_type = 'video';
I have two tables as category and product. I have to count similar data from table product and display count in table category. I am using this query in laravel to display category detail.
$data = CategoryModel::orderBy('id','ASC')->get();
In core php I used the following query to display counted data in table 1.
SELECT tbl_category.*,(SELECT COUNT(*) FROM tbl_product
WHERE tbl_product.v_category = tbl_category.v_name) AS TOTAL FROM tbl_category
Now I want to implement above query in laravel. how can I do that ?
I need more details but I am assuming that a product is mapped to multiple categories so there would be a model file named Category mapped to table categories and there would be Product.php model file mapped to products table
Below snippet in your controlled would help
App\Product::withCount('categories')->get()
Please sure to have below in your Product.php (Model file)
public function categories()
{
return $this->hasMany('\App\Category');
}
Note the count of the categories associated with a product would be return as categories_count in the collection
I have a database schema that goes like this:
Section
id
name
Subsection
id
name
section_id
Category
id
name
subsection_id
SubCategory
id
name
category_id
Product
id
name
subcategory_id
As you can see, each table has a foreign key that references the previous table. The problem comes when I try to get, for example, the Section from the current product or get all products from one section. So far I have tried this:
Section::with('product')->find(1)->product;
But I get this:
SQLSTATE[42S22]: Column not found: 1054 Unknown column
'product.section_id' in 'where clause' (SQL: select *
from products where products.section_id in
(1))
1 - This makes me think I need to set up a section_id in the products table to make this work. Is this correct?
2 - Shouldn't the Laravel ORM automatically go up the table hierarchy from Product to Section and get the results?
3 - Is there a way to do this maintaining my current table structure, I mean, without adding extra fields in the tables for the foreign keys?
Thanks.
No that is one way to do it but it isn't the only way.
No, how would it know that automatically?
I believe so and you can always create a specific query when laravel relationships don't work for you.
Okay first this assumes you have relationships setup on all the models to access the one below it. If that isn't the case you will need to setup the relationships.
Section::with('subsection.category.subcategory.product')->get();
I've never tried such extreme nesting but I believe this will work. The Laravel Docs talk about eager loading and scroll to see the nested example.
Another item that comes to mind is the hasManyThrough relationship. You couldn't do it for this number deep but it may be something you want to look into.
A brief summary from the docs is taking the first three from your example, Section, Subsection, and Category and then in the section class you would have this relationship.
public function category()
{
return $this->hasManyThrough('Category', 'SubSection');
}
The laravel docs with more information.
I am making an e-commerce web application. The following are the things that I have planned.
products table to contain only few columns viz. id, name, code, SKU_no.
meta_information_products table containing columns viz. id, product_id [foreign key to products table], meta_title, meta_keywords, meta_description.
measurement_product table containing columns viz. id, product_id, width, height, weight, length
And similarly other tables in relation to products.
So my questions are:
Shall I create different Model for each of the points above and
then create the One-To-One relationship with products and
related table ? Or shall I create only one Model called Product and declare all the fields in just one table product.
If I create different models for Product, what should be the name of the method to be declared for creating the One-To-One relationship, and same with Product Model.
For example, consider the following: I have created two models called Product and MetaInformationProduct and I have created relationship with both the tables. Now how do I name the method for the following:
class Product extends Model {
...
public function methodName() {
$this->belongsTo('App\Product');
}
...
}
And for MetaInformationProduct:
class MetaInformationProduct extends Model {
...
public function methodName() {
$this->hasOne('App\Product');
}
...
}
I guess Stack Overflow is not the best place to ask questions of this kind, since your questions do not necessarily have right or wrong answers. There are multiple possible ways to go about constructing your app's data structure, and ultimately it all boils down to one's personal style of coding. So almost every developer would have an original 'right answer' to your questions.
Here's what I think. Why do you need three separate tables for all that data? As far as I can see, all three tables contain data related one-to-one to a single product. That means more complicated models and relations in development, and more resources and longer execution time in production. You could avoid all that if you create one products table with the following columns: id, code, SKU_no, name, title, description, width, height, length, weight. That will simplify your models significantly and reduce the number of queries trifold.
Additionally, I think I can spot a piece of bad practice in your table structure. In your current meta_information_products table you have a column named meta_keywords. I'm guessing that that field would contain multiple keywords of a product. This negates the benefit of relational database structure and will give you headaches down the road. Instead, I would create one products table as I described in the previous paragraph, then another table titled keywords, with the following columns: id, keyword. Lastly, you'd need a relational table titled keyword_product with the following columns: id, keyword_id, product_id. This gives you the ability for one product to have multiple keywords, and for one keyword to be assigned to multiple products. It's a well known 'Many to many' relation, and you can read more about it in the Laravel's official documentation.
In general, you should create one model for one database table, except for the relational tables. So in case you do as I would, you would then need two models: Product and Keyword. For its content, it's best that you refer to the link in the previous paragraph.
I have 3 DB tables tbl_categories, tbl_items, tbl_items_categories like this:
tbl_categories fields: id (category id - primary key), name (category's name)
tbl_items fields: id (item id - primary key), name (item name)
tbl_items_categories fields: id (primary key), item_id (id field value from tbl_items), category_id (id field value from tbl_category)
Please note that one item can be in multiple categories (tbl_items_categories is being used for this purpose)
I have created 3 models (in YII) - categories, items, itemMultiCategories for these tables.
Can anyone please let me know how to create relations in YII for following purpose:
If I have an item id, I should be able to get all its category names (good to have category ids)
If I have category id, I should get all item names in that category (good to have item ids as well)
Thanks in advance.
You are not creating relations in Yii, you are doing it in the database.
Take a look at this answer.
After you created the relations, go into the gii (http://yourhost.com/?r=gii), and create all the models again. Don't forget to check the checkbox for relation creation.
What you have here is a many to many relationship bridged by an associative table (tbl_items_categories). This should be easily handled by Yii's many to many relational active record.
http://www.yiiframework.com/doc/guide/1.1/en/database.arr
For instance, to have a relationship in your items model that gets you all categories, you could do something like this:
public function relations()
{
return array(
'categories' => array(self::MANY_MANY, 'categories','tbl_items_categories(item_id, category_id)'),
);
}
The foreign key, tbl_items_categories(item_id, category_id), is just the name of your associative table with the table fields that will match your linked tables, in parentheses. Your fields should be listed in order, such that the field that will link to the primary key of the current model is listed first. My understanding is if you want to get items by category, the foreign key in the relationship in your category model will look like this: tbl_items_categories(category_id, item_id).
A note on your associative table:
You might consider removing the "id" field, since the combination of item_id and category_id is probably unique. Also, because the table only needs to be referenced in these relationship declarations, you probably don't need to set up a separate model for it.