I have four very simple models. Offer, Employer, Employee and Response.
Offer hasOne Employer
Employer hasMany Offer
Response hasOne Employee
Employee hasMany Offer
And now when I make a find() on Offer, it nicely makes a JOIN query and returns Employer details.
But when I make a find() on Response, it doesn't attempt to retrieve Employee's data.
I reviewed the code many times, stripped the models off of any additional properties etc., and still nothing. Those models are now nearly identical, their SQL tables too, but Response behaves like it has no relation to Employee defined.
Any pitfall with this that I might be trapped in? I'm ready to report this as a bug at this moment.
I can post complete (which are short, anyway) model definitions here if it helps anything.
Check the class of your model instances
I.e.
debug(get_class($this->Response));
If it outputs AppModel - the reason your code doesn't appear to be being used, is because: it isn't being used. That being the case, check for typos in the filename/location of your model files - as CakePHP will silently use an AppModel instance if your model files don't exist.
Related
I'm in the process of structuring a databasemodel for my new project. For all the entities in my model (which is a cms, and the entities as such f.ex: page, content, menu, template and a bunch of others) they all have in common the same attributes on dates and names.
More specifically each entity contains the following for the dates: IsCreated, IsValidFrom, IsPublished, IsDeleted, IsEdited and IsExpired, and for names: CreatedByNameId, ValidFromByNameId, PublishedByNameId and so on...
I'm going to use EF5 for mapping to objects.
The question is as simple: What is the best way to structure this: Having all the fields in every table (which I am not obliged to...) or to have two separate tables which the other can relate to...?
Thanks in advance /Finn.
First of all - give this a read - http://www.agiledata.org/essays/mappingObjects.html
You really need to think about your queries/access paths. There are many tradeoffs between different implementations.
In reply to your example though,
Given the following setup:
COMMON
ValidFromByNameId
SPECIFIC1
FieldA
SPECIFIC2
FieldB
Querying by the COMMON attributes is easy but you'll have to work some magic when pulling up the subclasses (unless EF5 does it for you)
If the primary questions you're asking are about specific1 and specific2 then perhaps this isn't the right model. having the COMMON table doesn't really buy you much necessary as it will introduce a join to load any Specific1 object. In this case, i'd probably just have duplicate columns.
This answer is intentionally partial as a full answer is better handled by the numerous articles and blogs already out there. Search for "mapping object hierarchies to databases"
Looking at the tables (aros, acos) generated by the ACL component and for example the Favorites plugin by CakeDC I see the favorites table with the fields Favorite.user_id, Favorite.model and Favorite.foreign_key.
The last two combined are replacing the good old Favorite.post_id (presuming model has the value 'Post'). It is in a way a HABTM pivot table with a dynamic modelname on one side.
I can see the general and useful idea here but would like to know more about the application of it.
My question(s):
Does this pattern have a name?
How does this work code-wise? I can see the abstract principle, but what kind of model-code is needed to make this work? Does it involve a patchwork of queries, or does this allow for a smooth one-query implementention? E.g.: I'd like to fetch all marked-as-favorite Posts in the system and their related Users in one go.
And does this work both ways? (querying from both the Post model as well as the User model)
I'd like to work towards an abstraction where I put a behavior in place to take care of this pattern.
I did look into the CakeDC code but could not figure out the principle. It's a little too cryptic for my current knowledge. Hence my question here.
kind regards,
Bart
Does this pattern have a name?
http://en.wikipedia.org/wiki/Junction_table aka Join Table.
How does this work code-wise? I can see the abstract principle, but
what kind of model-code is needed to make this work? Does it involve a
patchwork of queries, or does this allow for a smooth one-query
implementention? E.g.: I'd like to fetch all marked-as-favorite Posts
in the system and their related Users in one go.
It is just a regular join table, that's all. You can simply rely on what CakePHP is building up when using the HABTM assocs or refine your query by using joins. See http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#joining-tables.
The model field is not needed in that "pattern" but allows you to have just one join table that can be used for many different tables/models. For example instead of having tags and users and posts associated by tags_posts and tags_users we simply use the same table and filter by the model field.
And does this work both ways? (querying from both the Post model as
well as the User model)
Yes if you set the HABTM association up in both models.
Thanks for using our plugins. ;)
I am working on a project (based in Django although that's not really relevant to my question) and I am struggling to work out the best way to represent the data models.
I have the four following models:
User,
Client,
Meeting,
Location
User and Client have a many-to-many relationship through the Meeting model. The Meeting model has a one-to-one relationship with the Location model.
Meetings will take place at either:
The address defined in the User (or UserProfile) model
The address defined in the Client model.
Some other location which has to be defined at a later date.
I'm struggling to work out the best way to store the Location data in order to make it as clean and reusable as possible.
I considered making Location as a field in the Meetings model rather than a model in its own right - although this could also lead to redundant data if lots of Meetings are created at the same location, so this is probably a non-starter.
I could automatically create Location records for each User and Client that gets created and use a generic relationship between the relevant records, however, I understand that this can lead to inefficient database performance. Also, not every Client / User would be able to hold meetings at their Location.
Can anyone see an tidier alternative?
Any advice appreciated.
Thanks.
I considered making Location as a field in the Meetings model rather
than a model in its own right - although this could also lead to
redundant data if lots of Meetings are created at the same location,
so this is probably a non-starter.
No, that's a really good thought, because it points you straight at the real problem.
The real problem is that there's a difference between a meeting and the parties that attend a meeting. A meeting has some attributes that have nothing to do with the attendees: it has at the very least a time and a place.
So I think you should change your thinking about the Meeting model.
Instead of users having a M:N relationship with clients through the Meeting model, they should have a M:N relationship through, say, an Attendance model. (A Registration or Reservation or MightAttend model might be more appropriate for you.) And the Meeting model should change to reflect the unique attributes of a real-world meeting: time and place.
I would expect Meetings and Locations to have a many-to-one relationship. Can't a location be used for more than one meeting? (at different times, of course)
It seems to me that a location has attributes that persist beyond its use for a single meeting. Example: seating capacity.
I have an app in which Users belong to many Categories. So I have a Users table, Categories and Users2Categories table. The Users2Categories table consists of a user_id and category_id. So I guess the question is: do I create a model for Users2Categories? Ultimately, I would like to be able to "find" User objects and have their respective categories attached.
Also, can I define this relationship via the baking console?
Read about HABTM in the cookbook. Rename 'Users2Categories' table to 'categories_users'.
You can bake the models from the console but you must have the correct tables first (see above).
HABTM is definitely the way to go.
Cake will handle the join table for you, provided you adhere to the Cake conventions.
Read the section in the Book linked to by bancer, then read it again. Then read this: http://mrphp.com.au/code/working-habtm-form-data-cakephp which will help you with realworld implementation.
So, you asked two questions and got some good information, but the answers are pretty straightforward:
do I create a model for Users2Categories?
You can, but I wouldn't. Cake will create a model for the join at runtime. Since this model/table exists solely to facilitate the join (i.e. it has no properties or methods of its own), just let Cake do that work for you. As stated by #bancer, though, you will need to name the table according to Cake's convention.
Also, can I define this relationship via the baking console?
No. You can create the model skeleton, but that won't include the definition of any associations. AFAIK, there's no way to do that. Bake the skeleton, flesh it out with associations, etc.
I could not have been more wrong. See comments. Thanks for the education, #bancer and #beporter.
I am relatively new to CakePHP, and I am writing a CakePHP application which currently has an Author model and a Book model. Author and Book both have a many-to-many relationship.
However, I would like to additionally, for every author-book relationship, have a corresponding link to that author's blog where they reflect upon their experiences writing that book.
If that was confusing, the following paragraphs try to elaborate to make my situation more clear:
For every author, there will be one article about their experiences for each book. To look at this relationship in reverse, this means that for every book, there will be one corresponding link, per author (given that books can have multiple authors), where that author describes his/her experience writing the book.
In other words, for every single (Author, Book) pair, I would like to be able to store a related URL.
In more fancy, abstracty math terms that I will use horribly and improperly: I have an undirected graph, where every vertex is an Author or a Book, and every edge has an Author for one vertex and a Book for the other. That sounds kind of confusing, but (I think) it describes my situation as precisely as I can make it.
Given the above description, I want to know if I can attach arbitrary data to any given edge of that relation, and retrieve it later.
Currently I have a third model, AuthorBook, which acts the graph edge.
Author has a hasMany relationship to AuthorBook.
Book has a hasMany relationship to AuthorBook.
AuthorBook has a belongsTo relationship with Author and Book, and additionally has a url field.
This solution works, but for some reason the fact that Book is not directly connected to Author is bothering me. Is there any way to achieve this same effect while also cutting the AuthorBook model out of the picture?
(Also, I realize I can have them directly related while keeping AuthorBook, but that seems ugly and also redundant.)
(Also, I realize that I would still have an author_book SQL table. This does not bother me in the slightest, I think it's impossible to do without anyway.)
Thank you for your time! And please don't flame me!!!
Yes, you can model the AuthorBook relation (or the 'edge' as you envision it).
class Author extends AppModel {
...
$hasAndBelongsToMany = array('Book', array('with' => 'AuthorBook'));
....
}
The "with" habtm option:
Defines the name of the model for the join table. By default CakePHP will auto-create a model for you. Using the example above it would be called RecipesTag. By using this key you can override this default name. The join table model can be used just like any "regular" model to access the join table directly.
This is the equivalent of RoR's "through", depicted quite nicely in this illustration