Laravel Many to many to many sync - php

I've got a problem since several days in Laravel.
My database is like attached picture.database
User<->Role many-to-many-relationship works correctly.
In addition, I would like to add another many-to-many relationship in role_user pivot table. So I did:
user.php:
public function roles()
{
return $this->belongsToMany(Role::class);
}
public function role_users()
{
return $this->hasMany(RoleUser::class);
}
role.php:
public function users()
{
return $this->belongsToMany(User::class);
}
public function role_users()
{
return $this->hasMany(RoleUser::class);
}
And pivot roleUser.php:
public function user()
{
return $this->belongsTo(User::class);
}
public function role()
{
return $this->belongsTo(Role::class);
}
public function tags()
{
return $this->belongsToMany(Tag::class);
}
When I populate tables, I can get data: relations work.
Now I want to save data and let Laravel to populate tables automatically. At this moment and time, I save roles data in users.php with:
$this->Roles()->sync($roles);
($roles is an json array data from a form request..).
Pivot table get the user_id and role_id. Ok, cool.
Now, what should I write to get role_user_id and tag_id in role_user pivot table when I add a roles?
Thank you in advance!

I think you should use
$this->Roles()->attach($roles);
Rather than
$this->Roles()->sync($roles);
Because if I'm not wrong, sync will remove the pivot data. And you should pass the primary_key and foreign_key to your belongsToMany function. If you wanted to add data to the pivot column in your pivot table, try to add ->withPivot('column name');

Related

Many to Many Relationship with 2 FK referencing from same PK Laravel 8

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

1 to 1 and 0 to many relationship Laravel not working

I am struggling with an eloquent request. Let me explain what I want to do:
I have two models: User and Item
One User can have many Item and one Item belongs to One user.
I wrote the two method for this relation in my models as followed:
class Item extends Model
{
public function user() {
return $this->belongsTo(User::class);
}
}
class User extends Model {
public function items() {
return $this->hasMany(Item::class, 'items', 'user_id', 'user_people_id');
}
}
I try to access to the items from my controller its user's relation with:
public function index()
{
$items = Item::with('user')->get();
dd($items);
FYI: I seeded my items table with 10 items and my user table with 4 users:
items table:
users table:
My problem is that in the when I check my query with dd() here is what I get: Only the 4 first items get the relation, the others 6 return a null value
Relation working:
Relation returning null:
Thank you for helping me!
According to Laravel doc, hasMany relationship parameters are the following:
return $this->hasMany(Myclass::class, 'foreign_key', 'local_key');
So try to change your relationship in your User class like that
// change this
return $this->hasMany(Item::class, 'items', 'user_id', 'user_people_id');
// to this
return $this->hasMany(Item::class, 'user_people_id', 'id');
The easiest solution would be to rename your foreign key to user_id. That is what Laravel expects, so you won't need to deal with extra arguments in your hasMany() functions.
If you can't do that I think this'll work: return $this->hasMany(Item::class, 'user_people_id');.
Please try to add all in your query to see if it will work:
Update
public function index()
{
$items = Item::all();
dd($items);
}

Laravel pivot consultation

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.

Laravel: 2nd level relationship only fetching single row

I am using Laravel 5.6 and I have relation between 3 tables. Cart->cartItem->Images
Here is my controller code:
$cart = Cart::where('created_by_id', Auth::user()->id)->with('cartDetails')->first();
Here is my cart model:
public function CartItem()
{
return $this->hasMany('App\Http\models\CartItem', 'cart_id')->with('images');
}
Here is the model of cartItem:
public function images()
{
return $this->belongsTo('App\Http\models\ProductImage', 'item_id', 'product_id');
}
Now in result I am getting only single image even though I have multiple images in the database. It always picking up the last inserted image.
I want to get all images or at least the first one but not the last one.
Please help.
You should use hasMany() relation instead of belongsTo():
public function images()
{
return $this->hasMany('App\Http\models\ProductImage', 'item_id', 'product_id');
}
if you have multiple images in the database of items then you have to use hasMany() insted of belongsTo().
public function images()
{
return $this->hasMany('App\Http\models\ProductImage', 'item_id', 'product_id');
}
When use belongTo() ?
suppose you have post and comment model. Now you want post of comment . That is inverse of a hasMany relationship.To define the inverse of a hasMany relationship, define a relationship function on the Comment (child) model which calls the belongsTo method
public function post()
{
return $this->belongsTo('App\Post');
}

Displaying data from different tables in laravel

Have researched extensively eloquent relationships and laravel all afternoon and can't seem to find a solution.
I have a transaction table displaying User IDs in the From and To columns. I want to show the users emails that correspond to their IDs.
Here is my relationships:
Transaction model:
public function user()
{
return $this->belongsTo('App\User', 'id', 'email');
}
User model:
public function transaction()
{
return $this->hasMany(App\Transaction);
}
And heres the code from the controller. However I KNOW this just returns ALL the transactions. But I really can't find how I would display the emails instead of the IDs:
public function index()
{
$table = Table::create(Transaction::get());
return view('table', compact('table'));
}
Maybe you should try to get transactions with related model (user) or with join to users table?
$transactions = Transaction::query()->with(['user'])->get();
$table = Table::create(Transaction::get());
$table->addColumn('email', 'E-mail', function($model) {
return $model->user->email;
});
return view('table', compact('table'));

Categories