CakePHP: HABTM Multiple times - php

I have the current models:
Categories
SubCategories
Items
Each can have many of the others. For example, an item might belong to subcategory id 1, but the same item might also belong to subcategory id 2. Then subcategory id 1 might belong to category id 1, as well as subcategory id 2 belonging to category id 1.
Currently I have a HABTM relationship between each models, using a table called Categories_Sub_Categories or Items_Sub_Categories to link them. However I'd like to know is there a more efficient 'cake' way of doing this?

Categories and SubCategories could be combined into a single "Category" model and use the Tree Behavior to keep track of which is is the parent/child of each. That also allows you to keep more than 2 levels of Categories without need for changing your code.
Then, you can just do a HABTM between Category and Item.

Related

Yii : Products with MANY_MANY categories and categories may or not has parent. Get all products

I Have the following SQL schema:
tbl_products:
- id
- id_category
tbl_categories:
- id
- id_parent
tbl_products_categories: - id_product - id_category
My question is: In my categories model, what kind of relation I have to declare to get all products from this category and from it's childs ? Can I get all products from a relation or will I have to make a method to loop for each child-category and later merge all products and return it?
Anyone have any idea ?
Nested relationships, such as among categories or menu items, are notoriously tricky. The case is a bit simpler when you have constraints, such as a maximum number of children. In that case, your Product's criteria would contain as many joins as you have possible relationships (I wouldn't use Yii's relational active record in this case; would it make it too complicated in my opinion).
Otherwise, yes, your best bet is to loop recursively through each relationship and return a merged array. NOTE: this can be incredibly performance intensive, so you'll probably want to do some sort of caching on pages where this action is performed.
Since it is many to many, each product can be associated with the current desired children and all its parents, so when you query a parent, all children products will also be parent products.

database management to goods to store their categories

I have to create a web site witch contain goods. these goods have their own categories.for a
example a good can be categorized in many categories or sub categories.
I already have a item table witch contain their properties. and can anyone say how to keep it`s categories in database without duplicating data
Ok. In this case an Item may have many categories and a category may have many Items. So its a many to many relationship. Try as follows,
Your Item table may look like this,
Item(id, description, amount, ... )
In your Category table,
Category(id, name, description, ... )
And there will be another table to assign categories to items,
ItemCategoryAssignments(itemId, categoryId)
And there will be two foreign keys at ItemCategoryAssignments table. That,
itemId references id in the Item tabel
and
categoryId references id in the Category tabel
Like that. There will be no duplicated rows. Hope this will help.

Should the father know about the children or vica versa?

Should the father know about the children or vica versa?
That is, in a situation where I have two kinds of objects (items and categories), each has its own characteristics and fields and we have a relation between them that every item has a category he is in.
I want to ask in two ways about what should happen, in theory and in php + mysql.
Should the categories know about all the items that are in it, or should every item know about its category?
In php + mysql the exact question is should I for every item in its row save its category's id, or should I create a special table for this relation (each row contains a category id and an item id)?
Best practice is the children know about the parents (ex: parent_id). The alternative is not scalable, and very taxing to your system. You could easily run a query to FIND the children though - SELECT * FROM items WHERE item_category = x. The reason for this is when you add or delete items, the category is not affected. It doesn't become a different category because you assign an item to it or remove an item from it, so it shouldn't care either way which items are assigned to it.
This is different from a tagging setup. In the one-to-many category assignment method, items would fall into a single "category" but might have many "features". Tagging features is a many-to-many relationship and would require the mapping table you mentioned. Assigning parent categories requires only a single "parent" field in the items table.

How to tie products to categories?

The first time I tried to do this, I created a field in the category table called query. That contained strings like:
brand = "Burberry" AND type != "Watch"
Which I then inserted into the WHERE clause of a query to find a category's products.
That probably wasn't the best design.
My second attempt was to use a tagging system. I would create a tag table with tags like Burberry and Watch. I had a table tying the tags to the products (HABTM). I also had a table tying the tags to the categories.
The table tying tags to categories had an extra field called include which if it was a 1 then all products selected must also have that tag. Or if it was a 0 then all products selected must NOT have that tag.
This seemed to be a better design then my original, but it required some pretty complex joins.
Now I need to approach this problem once again.
One difference is I am now using the CakePHP (1.3) framework.
Before I try reinventing the wheel again. I was wondering if there are any known patterns/solutions I could use?
Probably you've already done that somehow by now, but here are my 2cents:
I'd drop Categories<->Tags, because I feel that you're unnecessarily duplicating data with it.
I.e. tables should be just categories, categories_products, products, products_tags and tags.
This way:
you wouldn't have to bother about changing category tags when products are added or removed from category
your searches would become more uniform (since there's only one tagging table)
and your tags still would be no more than 3 JOINS away - which is quite comfortable :)
From what I can understand you should have 5 tables:
Categories
Products
Tags
Categories_Tags
Products_Tags
UPDATE: When the user defines what should be selected, the HABTM tables are updated so that the tags/categories link to the products they should be linked to only.
So the query will look something like:
SELECT * FROM products WHERE ID in (SELECT product_id from tag list to include) AND ID NOT IN (select product_id FROM tag list to NOT include)
Maybe I'm missing what you're trying to accomplish here, but this sounds like you're making it more complicated than it needs to be.
Create three tables: Product, Category, and ProductCategory. Product and Category each have an id. Then ProductCategory includes ProductId / CategoryId pairs.
Like:
Product
ProductId Name
1 Lamp
2 Carpet
3 Drill
4 Power cord
5 3/8" bolt
Category
CategoryId Name
1 Electrical
2 Home decor
3 Hardware
ProductCategory
ProductId CategoryId
1 1
1 2
2 2
3 1
3 3
4 1
5 3
Then if you want, e.g., to know all the "Hardware" items:
select product.*
from category
join productcategory using (categoryid)
join product using (productid)
where category.name='Hardware'

Articles and Categories - The efficient way

I want to add categories to my website - but with more complex sorting.
Lets say I have article a. now, I want a to be under main category a, but also on category c thats its parent is b.
I thought of doing it like this:
An article would have a main category field, and also parent_ids
parent_ids would be every category this item is belong to.
my problem is: lets say i have: parent_ids: |1|5|2|7|.
now i am in category id - 7.
how would my select query look like?
select * from categories where parent_ids LIKE '%|7|%'
is it efficient? is there a better idea?
Never store multiple values in one column. All column values in a normalized database should be atomic (single-valued).
The relationship between articles and categories is many-to-many. That means you should have a separate table, such as article_category (article_id, category_id) containing one row for each category each article is in.

Categories