I am creating a bunch of models in my laravel project. There are four models, meaning four tables in my database. Namely the models are User, UserInfo,UserAddress,UserContact. The user table is the master table and the structure of the columns are as below:
users -> id , email, password,....other unimportant stuff.
user_info -> id, name, identity num, ......
user_address -> id, user_id, address1, address2,address3, shipping address,....
user_contact-> id, user_id, mobile_num,emergency_num,......
As you can see, the id column is the key identifier to know the entire information for any user. I am trying to define an eloquent relationship between them four and couldn't know if I am correct. This is what I have so far:
User Model:
public function user_info(){
return $this->hasOne('App\Models\UserInfo');
}
public function user_address(){
return $this->hasOne('App\Models\UserAddress');
}
public function user_contact(){
return $this->hasOne('App\Models\UserContact');
}
UserInfo Model:
public function user(){
return $this->belongsTo('App\Models\User');
}
public function user_address(){
return $this->hasMany('App\Models\UserAddress');
}
public function user_contact(){
return $this->hasMany('App\Models\UserContact');
}
UserAddress Model:
public function user(){
return $this->belongsTo('App\Models\User');
}
public function user_info(){
return $this->belongsTo('App\Models\UserInfo');
}
public function user_contact(){
return $this->hasMany('App\Models\UserContact');
}
UserContact Model:
public function user(){
return $this->belongsTo('App\Models\User');
}
public function user_info(){
return $this->belongsTo('App\Models\UserInfo');
}
public function user_address(){
return $this->belongsTo('App\Models\UserAddress');
}
So the question is that I am unsure for example, is user contact the child of user address or the other way round?
Is user contact the child of user info?
Can anyone shed some light on this?
Appreciate it.
Hi just keep all relations in User model and access them through it. In other Model just relation back to User Model. I am your structure modifying little bit, let user add multiple address check box for default shipping address, also multiple contacts if you want you can keep just one contact also.
users -> id , email, password,....other unimportant stuff.
user_info -> id,user_id ,name, identity num, ......
user_address -> id, user_id, address,shipping address,....
user_contact-> id, user_id, mobile_num,emergency_num,......
User Model
public function user_info(){
return $this->hasOne('App\Models\UserInfo');
}
public function user_address(){
return $this->hasMany('App\Models\UserAddress');
}
public function user_contact(){
return $this->hasMany('App\Models\UserContact');
}
in you all other user related models just add this
public function user(){
return $this->belongsTo('App\Models\User');
}
you can access relation through user model
$user_info = UserInfo::with('user')->first();
$user_info->user->user_contact();
if just user Model
$user = User::with(['user_info','user_contact','user_address'])->first();
echo $user->user_info->name;
update
user_id is the foreign key in each table other than user table, if you want to test the relations create User db seed and 4 factories (user, user_address, user_contact, user_info) to fill fake data, after creating models and data in database fetch first User and call its relations, do the same thing for other models fetch first record and call user relation from this model.
this is my UserTableSeeder class run method
public function run()
{
factory(App\User::class, 10)->create()->each(function ($user) {
$user->user_address()->save(factory(App\Models\UserAddress::class)->make());
$user->user_contact()->save(factory(App\Models\UserContact::class)->make());
$user->user_info()->save(factory(App\Models\UserInfo::class)->make());
});
}
Related
Hello I am working on a Laravel project, that i have to assign for one Mentorship «Mentoria», one Mentor «Mentor» and one student «Mentorando». The data of the student and the mentor, came from the Users table (i assigned them roles, using Spatie) , and the other table is called «Mentoria» Since there exists a many to many relation i created the pivot table that is called «utilizador_mentoria» and has ID_Mentor, ID_Mentorando (both are FKs coming from the users table),and ID_mentoria (coming from Mentoria table). I defined both models as this:
User Model:
protected $casts = [
'email_verified_at' => 'datetime',
];
public function interesses(){
return $this->belongsToMany(AreaInteresse::class, 'utilizador_interesse', 'id_utilizador', 'id_interesse');
}
public function mentorias(){
return $this->belongsToMany(Mentoria::class, 'utilizador_mentoria', 'id_mentoria', 'id_mentorando', 'id_mentor');
}
ps: I have interesses function with other model, that is working properly. my problem is with the «mentorias»
Mentoria Model:
public function users(){
return $this->belongsToMany(User::class, 'utilizador_mentoria','id_mentor','id_mentorando','id_mentoria');
}
With this, i am trying to get the data from all Mentorias, and the data of the Mentor that is assigned to that that Mentoria, however when i am doing this code on the controller, the data coming from the user appears empty, despite i have the DB filled with data. I tried a echo for testing, and it only shows the data of the Mentoria, and where it should appear the data of the Mentor assigned to that MEntoria, it is empty
the code from the controller:
public function mentorias(){
$mentorias = Mentoria::with('users')->get();
echo $mentorias;
return view('admin/mentorias/admin_mentorias', ['mentorias' => $mentorias]);
}
the output of the echo
[{"id":2,"titulo":"teste","titulo_en":"test","descricao":"fe","descricao_en":"ewfwe","created_at":"2021-12-28T01:32:10.000000Z","updated_at":"2021-12-28T01:32:10.000000Z","users":[]}]
Since as i already said, i already used data from 2 tables with Many to Many relation, however with only 1 FK per PK, and it is working properly, i have no idea why it is not working this way . I already checked for similar questions, however with no luck
Edit:
For testing purposes, i removed the column of one of the two FK that reference from the same PK, and i managed to work, however with this aditional FK i am not managing to make it work . I believe that the problem is with the relation, in the models but i have no idea how to make it work
I rearranged the funcitons in the models as they are now
User Model:
public function mentorias(){
return $this->belongsToMany(Mentoria::class, 'utilizador_mentoria', 'id_mentor', 'id_mentorando', 'id_mentoria');
}
Mentoria Model:
public function users(){
return $this->belongsToMany(User::class, 'utilizador_mentoria','id_mentoria','id_mentorando','id_mentor');
i also tried to took out,example «id_entorando» from the main () and put it after with the «withPivot» method, but it still didn't worked
I don't know if I properly understood the problem but your relationship is not a single "many to many", but two "one to many". In the end I'll show why it's convenient to consider them as two separated relationships.
First: If a user can have multiple mentorships but a mentorship can have only 1 mentor (which I suppose is what's happening), then you should use the "hasMany/belongsTo" pair:
User Model:
public function mentorias(){
return $this->hasMany(Mentoria::class);
}
Mentoria Model:
public function user(){
return $this->belongsTo(User::class);
}
Second: Complete the scenario with the other relationship bewteen the mentorship and the students:
User Model:
public function mentorias(){
return $this->hasMany(Mentoria::class);
}
public function mentoria(){
return $this->belongsTo(Mentoria::class);
}
Mentoria Model:
public function user(){
return $this->belongsTo(User::class);
}
public function mentorandos(){
return $this->hasMany(User::class);
}
There should be a user_id column in the mentorias table that represents the Teacher which the mentorships belong to:
Schema::table('mentorias', function (Blueprint $table) {
$table->unsignedInteger('user_id')->nullable();
});
And there should also be a mentor_id column in the users table that represents the mentorship which the students belong to:
Schema::table('users', function (Blueprint $table) {
$table->unsignedInteger('mentoria_id')->nullable();
});
Third: This double representation of the User Model could lead to confusion, since two different objects (teacher and student) are using the same model but are not meant to have both relationships simultaneously: A teacher shouldn't be mentored and a student shouldn't lead mentorships.
In order to roperly manage Teachers and Students and prevent confusion, you could create additional models that inherit the User Model and define the relationships for them (instead of the User Model), so you can limit the fields and the relationships for each one of them.
User Model:
// No relationships
Teacher Model:
// Extending from User allows you to have all the User Model functionality
class Teacher extends User
{
public function mentorias(){
return $this->hasMany(Mentoria::class)->with('students');
}
}
Student Model:
// Extending from User allows you to have all the User Model functionality
class Student extends User
{
public function mentoria(){
return $this->belongsTo(Mentoria::class)->with('teacher');
}
}
Mentoria Model:
public function teacher(){
return $this->belongsTo(Teacher::class);
}
public function students(){
return $this->hasMany(Student::class);
}
In the end, you'll have all the info you need from the mentorship when you call objects like this:
Teacher::with('mentorias')->get();
// This will show the Teacher's mentorias and the students in each one
Student::with('mentoria')->get();
// This will show the Student's mentoria and its teacher
Mentoria::with(['teacher', 'students'])->get();
// This will show the teacher and the students for each mentoria
I want to retrieve data using Eloquent, however I have several relationships between my models. I have four database tables (with the first three also having models):
- users (user_id, username, email ...)
- account (account_id, ...)
- entry (entry_id, account_id, ...)
- account_users (user_id, account_id)
In entry, account_id is a foreign id and the relationship has been implemented in both models.
account_users is an intermediate table for account and users. I have created a many-to-many relationship between account and user by adding the belongsTo-method in each respective model.
In Entry.php:
public function account(){
return $this->belongsTo('App\Account', 'account_id');
}
public function category(){
return $this->belongsTo('App\Category', 'category_id');
}
In Account.php:
public function entry(){
return $this->hasOne('App\Entry', 'account_id');
}
public function users(){
return $this->belongsToMany('App\User', 'account_user', 'account_id', 'user_id');
}
In User.php:
public function accounts(){
return $this->belongsToMany('App\Account', 'account_user', 'user_id', 'account_id');
}
In EntryController I have the method index(), where I am trying to show just the entries belonging to the currently logged in user, however I'm not sure how to structure the select query. I've read in the Laravel documentation about using pivot when structuring a query, however I'm still unsure.
Assuming a variable $user exists, you may do this to retrieve entries:
$user->load('accounts.entry');
$entries = $user->accounts
->flatMap(function ($account) {
return $account->entry;
})
->unique('entry_id');
It will get entries from every account and merge them into a 1-dimension array, and finally remove the duplicates.
I need advice about my model relationships,
Logic
Group has many users
Group has many admins
User has many groups (as user)
User has many groups (as admin)
Database Structure
Group Table
User Table
Group_Users table (save id of user and id of group)
Group_Admins table (save id of user and id of group)
Relationship Code
User model
public function groupsUser() {
return $this->hasMany(GroupUser::class);
}
public function groupsAdmin() {
return $this->hasMany(GroupAdmin::class);
}
Group model
public function users() {
return $this->hasMany(GroupUser::class);
}
public function admins() {
return $this->hasMany(GroupAdmin::class);
}
GroupUser model
public function group() {
return $this->belongsTo(Group::class);
}
public function user() {
return $this->belongsTo(User::class);
}
GroupAdmin model
public function group() {
return $this->belongsTo(Group::class);
}
public function user() {
return $this->belongsTo(User::class);
}
Help wanted
Basically as the relationships between users and groups is many to many normally I shouldn't need models of GroupUser and GroupAdmin and then just using sync() function in order to add/remove users and group id's from those tables.
What is my concerns then?
Normally I use that type of connection when I want input bulk ids into database (let say adding tags to posts, suddenly relate 10 tags id to 1 post) that moment using sync() and removing GroupUser and GroupAdmin models makes sense but in my case as users joins/adds to groups one by one, what do you suggest for this relationships?
Is my current approach makes sense?
Is is better if I remove those GroupUser and GroupAdmin models and add them to user, group model like:
public function users()
{
return $this->hasMany(User::class, 'group_users', 'user_id', 'id');
}
and such so?
What do you think is the best practice?
users and groups is many to many
your tables like this?
users, user_group , groups ?
How about use 'belongsToMany' relation?
Laravel many to many relation
// User model
public function groups() {
return $this->belognsToMany(Group::class);
}
// Group model
public function users() {
return $this->belognsToMany(User::class);
}
And use like.
User::find(1)->groups; // return user 1 groups
User::find(1)->groups()->sync($groupIds); // relate user and groups
Group::find(1)->users; // return group 1 users
If you have role column in your users table, you cold add relation like.
// Group model
public function users() {
return $this->belognsToMany(User::class)->where('role', 'the role of normal user');
}
public function admins() {
return $this->belognsToMany(User::class)->where('role', 'the role of admin user');
}
Hope it helps you.
I have three table in database. one is users and second one is role and other is user_role.
in role table has id and name.
in user_role table has user_id and roll_id.
now I want to set session when user will log in to app. llike Auth::user()->roll
Create relationship in User model
public function roles()
{
return $this->belongsToMany(Role::class);
}
Create relationship in Role model
public function users()
{
return $this->belongsToMany(User::class);
}
Then you can attatch a role to a user like this:
Auth::user()->roles()->attach(id_of_the_role_from_roles_table);
and that will create a new entry in pivot table role_user and then you can make a function in user model
public function hasRole($role)
{
return $this->roles->contains('id', $role);
}
and you can call it where ever you want in your code. For example:
Auth::user()->hasRole(1);
That will return true or false and then you can do something with that info.
I have four tables:
Users: id, username
Roles: id, name
Domains id, title
DomainsAssignedRolesUsers id, role_id, user_id, domain_id
I want to get all user roles for a domain.
I do:
User::find(1)->domains->first()->roles
But i get all domains roles, not only for my user. Help me to get user roles only for the selected domain/
My relations:
// User model:
public function rolesDomain() {
return $this->belongsToMany('Role', 'domainsAssignedRolesUsers', 'user_id', 'role_id');
}
public function domains() {
return $this->belongsToMany('Domain', 'domainsAssignedRolesUsers');
}
// Role model:
public function domains() {
return $this->belongsToMany('Domain', 'domainsAssignedRolesUsers');
}
// Domain model:
public function roles() {
return $this->belongsToMany('Role', 'domainsAssignedRolesUsers', 'domain_id', 'role_id');
}
public function users() {
return $this->belongsToMany('User', 'domainsAssignedRolesUsers', 'domain_id', 'user_id');
}
You want to get all the roles, from a specific domain, in relation with an user?
So this should do the trick:
User::find(1)->rolesDomain()->where('domain_id', $specificID)->get()
But if you want to only get the roles from the first domain for an user.
User::find(1)->domains()->first()->roles()->get();
And if you only want to retrieve the roles for a user.
User::find(1)->rolesDomain()->get()
And if you only want to retrieve all the roles from each domain in relation with an user.
User::find(1)->domains()->with('roles')->get()
Even if Eloquent documentation has a few example, This orm is really intuitive.
Check out Eloquent Triple Pivot (also on Packagist), it sounds like it does exactly what you want.
You'd set up your Models as User, Domain and Role (a User has many Domains and can have a Role in each). Then look at the docs on the Github page (particularly step 6), and you'd define this on your Domain model:
class Domain extends Eloquent {
...
public function getRolesAttribute() {
return $this->getThirdAttribute();
}
}
Then you can simply call
$user = User::find(1);
$domain = $user->domains->first();
// or
$domain = $user->domains->find(73);
$roles = $domain->roles;
// Or the above can be condensed into just...
$roles = User::findOrFail( 1 )
->domains()
->findOrFail( 73 )
->roles;