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.
Related
Say I have two query types, they both have a key column (as it happens, I'm querying an SCCM database by its views) called ResourceID.
The way I read the documentation this may not be possible since a Query Type cannot be the principal end of a relationship.
Can anyone confirm/deny this?
I don't think specifics are required for this question, but if you feel they are I can add some.
Yes! You cannot create one-to-one between two query types because query type cannot be principal end of a relationship whereas in between one-to-one principal end of a relationship is a must.
I have 2 tables ATable and AATable where both have a shared Primary Key - ATable.aKey and AATable.aKey to represent a one-to-one relationship. For my Fluent mapping I have a HasOne Relationship defined within my Fluent ATableMapping, all of which works fine. However I have noticed that querying for ATable generates a 2nd query (N+1) for the child Table AATable. My understanding is that Hasone eager loads by default, and I had assumed this would be part of the query for ATable, but I may well have this wrong?
I have researched various solutions including using .Not.LazyLoad().Fetch.Join(), PropertyRef, ForeignKey but I cannot seem to resolve the n+1 so that either it is Eager loaded with 1 query, or Lazy loaded and I can fetch the child with my queries.
Has anyone had any issues with this or have an example they know to work with no n+1? Grateful for any advice.
You have two options:
Not.LazyLoad() which disables possibility to provide lazy loaded related entity and it would enforce NHB to provide corresponding subselect within original query
Use component mapping so both entities point to the same table. This is better approach as once you decided to fetch both entities together, generated queries hit only one table - not two like within first option. This is definitely better for performance.
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.
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
I have a trip (primary: idTrip), where I can link more packages (primary: idPackage), so, I got a relationship table to link trips with packages (primary: idRelTripPackage). (relationship n-to-n)
And next I got a registrations table (primary: idRegistration). How do I best link those (1-to-1 relationship)?
I add two columns in the registrations table (idTrip, idPackage)?
I add a relationship table where i link idRegistration, idTrip, idPackage?
I add a relationship table where i link idRegistration, idRelTripPackage?
Am I right in thinking the relation from Registrations is to RelTripPackage, and its definitely one-to-one. There are a couple of options:
1: As it really is a one-to-one there's not really anything to stop you putting the Registrations data directly onto RelTripPackage, or doing the vice-versa and putting idPackage and idTrip straight onto Registrations as FKs, with a unique key across the two FK columns to ensure there aren't duplicates.
2: If do want the two separate tables then just add idRetTripPackage to Registrations as an FK, and then add a unique constraint on it - again to ensure uniqueness.
There's no need for a separate relationship table as its a 1-1 relationship - They only really become relevant when you are using an n-n. The rest of the time FKs should be placed directly on the child table.
If you follow that logic, you will
add tables and Relations every time you need to add Relations
end up with confusing or duplicate Relations (multiple paths between any two tables)
However the problem (limiting factor) is that the tables you are starting with are not actually normalised. Since the starting position does not have a good basis, you will end up with far more Relations (in tables) than there actually are between the Entities. So the best advice is, the Best practice is, before you attempt this current extension, step back and normalise the data, the existing tables. Then the extension will be much easier, and you will end up with less tables.
if you provide info re the tables (Person, Trip, Package, etc); what exactly is a Registration, etc ... I can provide more explicit answers.
Generally any attribute that is 1::1 with the PK of an Entity should be an attribute in that entity. Any attribute that is 1::0-1 with the PK of an Entity should be in a separate table.
ER Diagram
Based on the information provided, this is your ▶Entity Relation Diagram◀. As long as you use Relational Identifiers, all the Relations you have identified thus far are supported directly (otherwise, if you use IDs, you will need more Relations and tables).
Readers who are unfamiliar with the Relational Database Modelling standard may find ▶IDEF1X Notation◀ useful.