I'm curious why the Eloquent relationship for hasMany has a different signature than for belongsToMany. Specifically the custom join table name-- for a system where a given Comment belongs to many Roles, and a given Role would have many Comments, I want to store the relationship in a table called my_custom_join_table and have the keys set up as comment_key and role_key.
return $this->belongsToMany('App\Role', 'my_custom_join_table', 'comment_key', 'role_key'); // works
But on the inverse, I can't define that custom table (at least the docs don't mention it):
return $this->hasMany('App\Comment', 'comment_key', 'role_key');
If I have a Role object that hasMany Comments, but I use a non-standard table name to store that relationship, why can I use this non-standard table going one way but not the other?
hasMany is used in a One To Many relationship while belongsToMany refers to a Many To Many relationship. They are both distinct relationship types and each require a different database structure - thus they take different parameters.
The key difference is that in a One To Many relationship, you only need the two database tables that correspond to the related models. This is because the reference to the relation is stored on the owned model's table itself. For instance, you might have a Country model and a City model. A Country has many cities. However, each City only exists in one country. Therefore, you would store that country on the City model itself (as country_id or something like that).
However, a Many To Many relationship requires a third database table, called a pivot table. The pivot table stores references to both the models and you can declare it as a second parameter in the relationship declaration. For example, imagine you have your City model and you also have a Car model. You want a relationship to show the types of cars people drive in each city. Well, in one city people will drive many different types of car. However, if you look at one car type you will also know that it can be driven in many different cities. Therefore it would be impossible to store a city_id or a car_id on either model because each would have more than one. Therefore, you put those references in the pivot table.
As a rule of thumb, if you use a belongsToMany relationship, it can only be paired with another belongsToMany relationship and means that you have a third pivot table. If you use a hasMany relationship, it can only be paired with a belongsTo relationship and no extra database tables are required.
In your example, you just need to make the inverse relation into a belongsToMany and add your custom table again, along with the foreign and local keys (reversing the order from the other model).
Try to understand with text and a figure.
One to One(hasOne) relationship:
A user has(can have) one profile. So, a profile belongs to one user.
One to many(hasMany):
A user has many(can have many) articles. So, many articles belong to one user.
Many to many(BelongsToMany):
A User can belong to many forums. So, a forum belongs to many users.
Related
i have a table (piovt table) that links the invoice id and the service id, but the service id does not come from one table but comes from different tables. here is an example of that.
i tried use polymorphic relations but i only get the last recored not all recoreds related to the invoice
so how to get the services from invoice table?
You can check the Has One Through relationship.
Laravel documentation states "The "has-one-through" relationship defines a one-to-one relationship with another model. However, this relationship indicates that the declaring model can be matched with one instance of another model by proceeding through a third model."
You can read more and get code examples here
Laravel has one through relationship
Say I have four tables:
users
groups
activities
group_activities
Where a group can have any number of activities and an activity can belong to any number of groups through their intermediate table group_activities, and a user belongs to one group via users.group_id. I want to correctly model a relationship between users and activities so that a user can have any one activity, but only if the group that user belongs to has a relation to that activity.
HasOneThrough doesn't seem to work here, since the group the user is related through has multiple activities. HasManyThrough doesn't work since the user can only have one.
I want to properly model this relationship so that it can be picked up for selection automatically via a Nova relationship field, but I'm struggling to figure out exactly how I would do so. My first thought is a HasOneThrough relation with some set of subqueries, but I can't quite piece together where to start.
How would I do this, or conversely, is it possible via Eloquent's automatic relationship system at all?
To ensure we are on the same idea of your relationships:
The relationship between Groups and Activities is a Many To Many relationship (Many To Many - Larvel Documentation).
The group_activities table is the pivot table.
The relationship between users and groups is a One To Many relationship One To Many - Larvel Documentation and the inverse of it One To Many (Inverse) - Larvel Documentation.
To actually answer your question:
If you want to use a shortcut from users to their activities, the Has Many Through is the correct way. If a group can have arbitrary many activities, and a user belongs to one group, the user will be associated to these arbitrary many activities through the group -hence Has Many Through. Note that this is not really a separate relationship though, it's just a convient shortcut.
If you wan't to associate a user with a single Activity directly, you need to to this via a separate One to Many relationship between Users and Activities.
I'm not entirely sure if I interpret your question correctly, so the following is just an assumption, but do you want to ensure a user can only be associated to an activity thats also associated with the user group? So to restrict possible activites by group? If that is the case, you'd simply need to check if the selected activity is in the activities associated with the users group:
With your relationships set up like this:
class User {
public function activity(){
return $this->belongsTo('App\Activity');
}
public function possibleActivities(){
return $this->hasManyThrough('App\Activity','App\Group');
}
}
you can check and associate activities like this:
if( $user->possibleActivities()->contains( $activity ) ){
$user->activity()->associate($activity);
}
I have users and user_roles tables, and id of user_roles is used as foreign key in users. I fetched data from users using User::with('userRole')->find($user). In returned result userRole is present, however it is empty, instead it was supposed to have data from user_roles for the particular foreign key.
Please, share what can be the possible issues with the functionality or if anyone can explain working of laravel associations in brief.
/* User Model */
public function userRole()
{
return $this->belongsTo('App\UserRole');
}
/* UserRole Model */
public function user()
{
return $this->hasMany('App\User');
}
Thank You,
Many to many relationships in Laravel often require you to have 2 models and 3 tables. One to many relationships require you to have 2 models and 2 tables. One to one relationship also requires you to have 2 models and 2 tables.
Many to many relationship
Let's take User and Role models, since each User can have multiple roles and one Role can be assigned to different users, you will naturally want a Many to many relationship. Now, you will need to create an intermediate table in which you will store the results, why? Because you already defined both User and Role and since it is Many to many none of those objects will have any identifier of the other one inside of them, but rather will have their own identifier in the intermediate table, and this is how Laravel fetches the relationship, it connects Models primary key with foreign key inside of the intermediate table.
One to many relationships
Let's take User and Role models again and let's say that this time, one Role can be assigned to multiple users, but one User can ONLY have 1 Role. Naturally you will have a field role_id inside of your User model and you will connect role_id from users with id from roles.
One to one relationships
Lets take User and Role models again :D Let's say you want to create a separate Role for every user, then you will have 2 models and 2 tables where your users table will have all the users and your roles table will contain id, name, user_id and now when you try to retrieve the relationship, if you define one to one laravel will return only 1 result, no matter if you have multiple same user_id on the roles table, Laravel will return only 1 role because you told him explicitly it's 1-to-1 relationship.
EDIT:
Here is an example of one to one relationship:
/* User Model */
public function userRole()
{
return $this->belongsTo('App\UserRole', 'user_role_id', 'id');
}
#Tim and #Nikola
Thank you, for your efforts mates.
However, I found the reason behind the problem. It was because the wrong naming of userRole function in User model.
I was using foreign key of user_roles as user_roles_id in users table and defined function with name of userRole in User model. This leads to ORM not found the relevant column for attaching user_roles data.
The solution is either I have to change the name of user_roles_id to user_role_id or userRole function name to userRoles. And I choose the first one and it worked fine. :)
For reference on the naming conventions of laravel please refer to Laravel - Database, Table and Column Naming Conventions?.
I was wondering if there is a smart way of having several common columns to different tables in CakePhP. I could use a common table having relationships to these tables, but is there a behavior or similar mechanism for which I can have:
Users
Customers
CommonPersonalFields
And have some common fields in the third table, fetched automatically by cake. In this way you could also have common views for those fields, included in the other tables views.
This is done with Model Associations in CakePHP. In this scenario, your models would be User, Customer, and PersonalData, and your associations are User hasOne PersonalData, Customer hasOne PersonalData, and if you want the association to be linked from both directions, PersonalData belongsTo User and PersonalData belongsTo Customer.
I'm creating a project management system which projects are assigned to users
What's the difference between creating a Model ProjectsUser and defining 2 $belongsTo relationship and defining HABTM relationships in both Project and User models? What would be the most correct way, though? And how do I save the data in the projects_users table?
From my experience, if you want to be able to save or delete rows only from the join table (the one with 2 IDs), then it is much more simple using three models associated through both a hasMany and a belongsTo association.
You can also retrieve data from the join table directly and do the queries you want much more easily
This is what CakePHP documentation says refering to HABTM and saving data:
However, in most cases it’s easier to make a model for the join table and setup hasMany, belongsTo associations as shown in example above instead of using HABTM association.
Here you can find more the full text:
http://book.cakephp.org/2.0/en/models/saving-your-data.html#what-to-do-when-habtm-becomes-complicated
I have used this method for a "reads" table (with post_id and user_id) as well as for subscriptions and similar kind of relationships.
The first way is called "hasAndBelongsToMany" [details here].
The second is called "hasMany through" [details here].
The second link relating to "hasMany through" has details and a lengthy explanation about when and why you would want to use it.
Not sure about the specifics of cakephp, but in general defining the relation model explicitly gives you more control over it, for instance if you wanted to do some validation or add callbacks on creation of this relationship.