I'm brand new to Laravel and Eloquent (and I have minimal experience with ORM in general).
Let's say I have three database tables:
Widgets
Actions
Users
I have modelled one junction table that has columns for:
widget_id
action_id
user_id
timestamp
The point of the junction is to keep a log of interactions--take a timestamp every time a user performs an action on a widget. I see how to model a simple many-to-many relationship using Eloquent and have this working fine, but I'm not sure how to model a more complicated three-way relationship.
For that matter, even if I had a simply many-to-many relationship (say widget to action so there would be a table called action_widget), how can I add an explicit model for the action_widget table in Eloquent, for the purpose of keeping track of extra data about each relationship (e.g. a timestamp, a comments field, etc). Or, am I just going about this in a totally wrong way?
Being new to ORM, I feel very confined as to what I can do! Does this feeling go away? :p
pivot work fine when you have 2 way relation like Categoty<->Article.
but if you have 3 way relation i think it's better to have a model called WidgetUserAction.
Edit : For these cases the new "hasManyThrough" works fine.
Laravel can create the intermediate model automatically. They're called "pivot tables".
I suggest you read this section in the documentation.
Related
There are 3 initial tables, Product, User, and Tag. (Not really a product table but it makes for a simpler example)
There's a many-to-many relationship between a User and Product, as well as between a User and Tag. So, I created 2 association tables for this relationship -> UserProduct and UserTag
Now, a user can create multiple tags, and add those tags to a product. From my knowledge, this can be achieved by creating another association table, UserProductTag, between the association tables UserProduct and UserTag.
I wasn't able to find many examples of this use case on the internet. That made me wonder, is this the correct approach? Or am I overdoing normalization?
This gets further complicated by the fact that I've to achieve this in SQLAlchemy as well and I've no idea (but I guess that's a different question).
I believe what you are looking for is what is often called "ternary relationship".
Please see these two SO questions and answers to give you implementation ideas:
How to three-way many-to-many relationship in flask-sqlalchemy
Inserting relationships into a table which connects 3 tables with many to many relationships with SQLALchemy - python
I have a design problem with regards to Entity Framework model relationship
I have this model in the edmx
Business Rule:
A Participant can have multiple Roles so I create a relationship table ParticipantRoles that has 1-to-Many relationship on the Participant and the Role table
The Problem:
In order to get the Participant's Role value, I have to drill down through Participant->ParticipantRole->Role (see JSON output below)
The Question:
In EF, how to design the table relationship to bypass the ParticipantsRole table. I want to access the Role in something like this Particant.Role and not Participant.ParticipantsRole.Role
You say A Participant can have multiple Roles. And of course, a Role can have multiple Participants. So basically this is a many-to-many association.
Entity Framework will only map pure many-to-many associations (without connecting class) when the junction table only has two foreign keys. In your case, if the table ParticipantsRole only would have had a primary key consisting of ParticipantId and RoleId at the time of generating the model the class ParticipantsRole would not have been created. You would have had Participant.Roles and Role.Participants as navigation properties.
However, the model has been generated with ParticipantsRole and you want to get rid of it. (Or not, I'll get back to that).
This is what you can do:
Remove ParticipantRoles from the class diagram.
Modify the database table ParticipantRoles so it only has the two FK columns, that both form the primary key.
Update the model from the database and select ParticipantsRole in the Add tab.
This should give you a model with a pure many-to-many association.
However, think twice before you do this. M2m associations have a way of evolving into 1-m-1association (as you've got now). The reason is that sooner or later the need is felt to record data about the association, so the junction table must have more fields and stops being a pure junction table. In your case I can imagine that one day participant's roles must have a fixed order, or one marked as default. It can be a major overhaul to change a m2m association into 1-m-1 in a production environment. - Something to consider...
I have an initial migration that sets up two tables (users and projects), with a relationship (innoDB).
$table->foreign('user_id')->references('id')->on('users');
I have two Eloquent models set up, blank except for the relationship:
return $this->has_many('Project');
Do I definitely need to tell eloquent about the relationship in the models and the database? I'd assumed something as comprehensive as Laravel would infer it from the Schema? Is there something I'm missing?
You're right, you have to define the relationships in your Models.
Laravel doesn't analyze the schema, foreign key indexes are actually not mandatory to use.
This bootstraping may could be avoided, but it also allows you to use non-conventional table and column names or use the Fluent Query Builder to modify the relationship queries.
Less magic, more control for now.
I am trying to layout a database with multiple tables of a similar type. Consider a simplified veterinarian system. I have the following tables:
Dogs
Cats
Birds
Owners
My one constraint is that each Owner can have exactly 1 pet. I would like to keep referential integrity, but do not want to have my Owners table have three columns dedicated to foreign keys (seeing as I may need to add further pet species at some point).
Furthermore, when working with Entity Framework, I would like to have the entities setup to link as simple as Owner.Pet and have the underlying mechanisms handle deciding which table it needs to pull from.
I have come up with a way to do the second portion, but it is messy, at best. Has anyone tried something like this and had good luck coming up with a somewhat elegant solution?
For TPT inheritance, you'd make one table called Pet with an ID PK.
You'd then make a second table called Cat with a PK which is both a PK and a FK to Pet.
Having done this, you can now create a TPT model using these steps.
This is more or less a general question and not about any specific ORM or language in particular: this question comes up regardless of your ORM preference.
When mapping a many-to-many relationship it is possible to obscure the intermediary table or to make the intermediary table a part of your model. In the case that the intermediary table has valuable data beyond the relationship, how do you handle the mapping?
Consider the following tables:
CaseWorker (id, first_name, last_name)
CaseWorkerCases (case_worker_id, case_id, date_opened, date_closed)
Case (id, client_id, field_a, field_b)
As a programmer I would really rather be able to do:
CaseWorker.Cases
than
CaseWorker.CaseWorkerCases.Cases
On the one hand, the table CaseWorkerCases contains useful data and hiding the intermediary table makes accessing that data less than convenient. On the other, having to navigate through the intermediary table makes the common task of accessing Cases seem awkward.
I supose one solution could be to expose the intermediate table in the model and then give the CaseWork object a wrapper property could work. Something like:
public IEnumerable<Case> Cases
{
get{return (from caseWorkerCase in this.CaseWorkerCases
select caseWorkerCase.Case);}
}
But that also seems wrong.
I regard many-to-many mappings as just a notational abbreviation for two one-to-many mappings with the intermediate table, as you call it, enabling simplification of the relationships. It only works where the relationships do not have attributes of their own. However, as understanding of the particular domain improves, I usually find that many-to-many mappings usually need to be broken down to allow attributes to be attached. So my usual approach these days is to always simply use one-to-many mappings to start with.
I don't think your workaround is wrong. The complexities of these models have to be coded somewhere.
I have a blog post about this exact topic: Many-to-many relationships with properties