For my recipe-sharing website, I want to create a database and CakePHP models for the recipes and their ingredients.
I created two tables: recipes and ingredients. The third table is a HABTM table for ingredients_recipes, which also stores the amount of ingredients needed for the recipes. How do I create a model for the third table?
The third table would look something like this:
recipe_id
ingredient_id
amount
measurement_unit
I also thought of adding another table for measurement_units to store all possible units (ex. tablespoon, tea spoon, cup, etc.). Would that be too much?
HABTM, within Cake's ORM, is actually an abstraction of the following two model association structures (using your example):
Recipe
-> hasMany IngredientsRecipe
-> belongsTo Ingredient
and
Ingredient
-> hasMany IngredientsRecipe
-> belongsTo Recipe
The IngredientsRecipe model is inferred, and used only to link the two first-class models, Ingredient and Recipe.
However, in your case, you actually want IngredientsRecipe to be a first-class model, which breaks the HABTM abstraction. In fact, what you need to do is explicitly define the two association structures above, so that Cake treats the IngredientsRecipe model as a first-class citizen, allowing you to query against it, save records to it, etc.
Also, no, I don't think it's too much to create an additional MeasurementUnit model. It will provide you much more flexibility down the line.
Think of it like this then treat it one chunk at a time:
`Recipe` (1)--(n) IngredientsRecipe (n)--(1) Ingredient
In Recipe, create the association to IngredientsRecipe
In Ingredient, create the association to IngredientsRecipe
In IngredientsRecipe create the association to Recipe
Still in IngredientsRecipe create the association to Ingredient
While you're doing it, forget about HABTM and think instead about hasMany and belongsTo
Incidentally, you are not bound to call the model IngredientsRecipe, that is just the default/convention.
When you're done, treat it like hasMany, belongsTo or HABTM as appropriate.
Related
I am trying to create a proper relationship on Hibernate and I have the following relationship between Recipe and Ingredients entities:
I thought that:
One recipe can have multiple ingredients
One ingredient can also be part of different recipes
In this situation, I would create many to many relationship.
However, by considering the unit and amount fields in the Ingredient entity, I think the amount of ingredient for a specific recipe may be changed later. In this situation, each ingredient should be belonging to a specific recipe. As a result, I create one to many relationship as shown on the image.
1. Is the approach (one to many) explained above true?
2. I also think that for a Category entity (that describes recipe categories e.g. vegetarian, diabetic, ...), I should use many to many relationship as the category is not identical for a specific recipe and when updating any category, all the related recipes should be affected. Is this true?
If you want to map a many to many relationship, then you need a relationship table.
So your database tables will be
recipe <-> recipe_ingredient <-> ingredient
As you want to have attributes on the relationship amount and unit will then go to the recipe_ingredient table.
This will also result in three classes. Recipe, RecipeIngreident and Ingredient.
The answer to both of your questions is yes. However, you should still consider many-to-many according to #Simon Martinelli's answer in this situation as you will eventually have many duplicate entries and data for Olive Oil across many different recipes which will only have unique IDs/Amounts/Units. However, this is just a suggestion and you are free to write your code however you wish.
I need a data-filter based on a child model HABTM relation condition.
My table structure is as following:
Project hasMany TaskGroup hasMany Task hasAndBelongsToMany User.
I need my find function to get only the Projects with specific TaskGroups that contain Tasks assigned to some User.id. In other words, I need my Tasks filtered by User.id, and structured as Project -> TaskGroup -> Task. Is there a way Cake model bindings handle this, or do I need to write the joins manually?
You'll need to use Joins - see link for how to build joins in CakePHP:
http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#joining-tables
I have a bunch of models that I'm going to be creating, and these models will have different types of categories that they can belong to. For example, one model will HABTM one set of categories, another model will HABTM another set.
I've come up with one idea - creating a model called Category, and having a categories table with a 'model' field, that contains the name of the model that this category has a HABTM relationship with. Then the other models would have something like this:
public $hasAndBelongsToMany = array(
'Category'=>array(
'conditions'=>array(
'Category.model'=>'Modelname'
)
)
)
This seems OK but
this code will be repeated in every model which seems silly and
some categories will apply to several models, so there would be duplicate database entries for those categories.
Is there a better way? Thanks for your help!
You can use one category model and add a model field to the category model to specify the related model. So you can use different models with one category model... Like you said...
I think this is a good idea.
I was wondering if this is possible to do with a has many through
contents orgs folders
id id id
name name title
link
join table - folder_elements
id
element_id
order
contents has many folders through folder_elements
orgs has many folders through folder_elements
So my question is, is it possible to use element_id to store the content.id or the org.id ?
Alex
What you're describing is a sort of HABTM (HasAndBelongsToMany) association. You could define the inter-model associations as you suggest, but there's a pretty significant design flaw: how would you account for a situation where the same ID is used for an orgs record and a contents record, and wish to associate them with the same folder record? It would be impossible to differentiate between the two in your joining table.
There are a number of ways to work around this, but they require more program logic or a more disorganised database schema that presents challenges in maintainability.
The more elegant, robust solution is to rationalise your database structure. If there's no pressing need to have One Join Table to Rule Them All, you could design your model associations like this:
Content hasMany ContentsFolder belongsTo Folder
Folder hasMany ContentsFolder belongsTo Content
Org hasMany OrgsFolder belongsTo Folder
Folder hasMany OrgsFolder belongsTo Org
This is the internal structure of a HABTM association defined explicitly so you can define fields in the joining table. Your contents and folders tables would remain the same, but your two joining tables would look like:
contents_folders
-> id
-> content_id
-> order
orgs_folders
-> id
-> org_id
-> order
Unfortunately, yes, this would require defining five models instead of three, but such are the limitations of CakePHP's object-relational modelling.
I have checked out the cookbook web site of cakephp that there are four types Model relationship:
http://book.cakephp.org/view/79/Relationship-Types
Since the one I am more familiar with is belongsTo,
I am not sure when I need to use hasManay and HABTM.
What will be the result to my web site if I used a wrong Model relationship type?
Please advise.
belongsTo and hasMany are a pair and express a one-to-many relationship. One model belongs to another (i.e. it has a other_model_id field), while the other way around that other model has many records in the model that belongs to it. It's two sides of the same coin.
hasAndBelongsToMany is Cake's term for a many-to-many relationship. Here's a primer on this type of relationship. You use this when both models can have many of the other model, e.g. People-People friend relationships. A many-to-many relationship between two models entails three tables: model_a, model_b and model_a_model_b. If you're trying to use this type of relationship without the third table, you'll probably just get a bunch of errors.