Many to Many saving data - laravel

I have the following schema
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('userName')->default('');
$table->string('userEmail')->default('');
$table->tinyInteger('active')->default(1);
$table->timestamps();
});
Schema::create('user_groups', function(Blueprint $table)
{
$table->increments('id');
$table->string('groupName')->default('');
$table->timestamps();
});
Schema::create('users_user_groups', function(Blueprint $table)
{
$table->integer('userId')->unsigned()->index();
$table->foreign('userId')->references('id')->on('users')->onDelete('cascade');
$table->integer('groupId')->unsigned()->index();
$table->foreign('groupId')->references('id')->on('user_groups')->onDelete('cascade');
$table->timestamps();
});
Essentially, a User can be apart of many Groups, and a Group can have many Users.
class User extends Model
{
protected $table = 'users';
protected $guarded = [];
public function groups()
{
return $this->belongsToMany('App\Group', 'users_user_groups')->withPivot('userId', 'groupId');
}
}
class Group extends Model
{
protected $table = 'user_groups';
protected $guarded = [];
public function user()
{
return $this->belongsToMany('App\User', 'users_user_groups')->withPivot('userId', 'groupId');
}
}
I think the Models are ok. I then have an updateUsers function in my controller
public function updateUsers()
{
$users = Helper::returnUsersFromLdap();
DB::table('users')->update(array('active' => false));
foreach($users as $userName => $userData) {
$user = User::firstOrNew(['userName' => $userName]);
foreach ($userData as $userEmail => $userDepartment) {
$user->userEmail = $userEmail;
$user->active = true;
$userGroups = Helper::returnGroupsFromLdap($userEmail);
foreach($userGroups as $group) {
$user->groups()->sync($group);
}
}
$user->save();
}
Session::flash('flash_message', 'Users updated');
Session::flash('flash_type', 'alert-success');
return Redirect::route('users.index');
}
I essentially get a user list from Active directory, loop this, and add the my users table. For each user, I call returnGroupsFromLdap passing the users email as a parameter. For each user, this will return the groups that user is in like so
array:3 [▼
0 => "Group1"
1 => "Group2"
2 => "Group3"
]
My question is how can I link the user groups to a user? So I loop each group and then add it to my user_groups table? But then where do I populate the pivot table I created?
Any advice on this matter appreciated.
Thanks

You can use the sync method to update the user groups from the user model:
$user->groups()->sync([1, 2, 3]);
Where [1, 2, 3] is an array with group ids. Laravel will know to save this relation in the table that you specified in the belongsToMany() relatiotnship in the model.
But you might have to specify the column names because by default Laravel uses another naming convention:
return $this->belongsToMany('App\Group', 'users_user_groups')->withPivot('userId', 'userGroupsId');
Check the documentation for more details: https://laravel.com/docs/5.2/eloquent-relationships#many-to-many

Try:
public function up()
{
Schema::create('users_user_groups', function(Blueprint $table)
{
$table->increments('id');
$table->integer('userId')->unsigned();
$table->integer('userGroupsId')->unsigned();
});
Schema::table('users_user_groups', function(Blueprint $table) {
$table->foreign('userId')->references('id')->on('users');
$table->foreign('userGroupsId')->references('id')->on('user_groups');
});
}

Related

How to get just one user data in Laravel with eloquent?

I use Laravel 8. I want to get the user proccess course, but I get all users proccess.
In User.php
public function courses()
{
return $this->belongsToMany(Course::class);
}
Course.php
public function progresses()
{
return $this->hasMany(Progress::class);
}
Progress.php is empty.
Course table
Schema::create('courses', function (Blueprint $table) {
$table->id();
$table->string('title');
...
$table->timestamps();
});
Progress table
Schema::create('progress', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->foreignId('course_id')->constrained()->onDelete('cascade');
$table->integer('percent');
$table->timestamps();
});
CourseController
public function index()
{
$userCourses = User::where('id', 1)->with('courses.progresses')->first();
return $userCourses;
}
And this return:
But I only wanted proccess where user_id = 1.
With() method can constrain eager loads with a specific array annotation. This is also described in the documentation.
$userId = 1;
$userCourses = User::where('id', $userId)
->with(
[
'courses.progresses' => function ($query) use ($userId) {
$query->where('user_id', $userId)
},
]
)->first();

In Laravel many-to-many relationship, is there a way to update data in a pivot table?

I built two models User and Institution.
How do I update the pivot data between them, after adding additional Pivot columns?
<?php
class User extends Authenticatable
{
public function institutions()
{
$pivots = ['id', 'program_choice', 'session'];
return $this->belongsToMany('App\Institution')
->withPivot($pivots);
}
}
class Institution extends Authenticatable
{
public function users()
{
$pivots = ['id', 'program_choice', 'session'];
return $this->belongsToMany('App\User', 'institution_user')
->withPivot($pivots);;
}
}
Here are the migrations
class CreateUsersTable extends Migration
{
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->integer('user_id')->unsigned();
$table->rememberToken();
$table->timestamps();
});
}
class CreateInstitutionsTable extends Migration
{
public function up()
{
Schema::create('institutions', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name')->unique();
$table->string('city')->nullable();
$table->string('state')->nullable();
$table->string('country')->nullable();
$table->string('address')->nullable();
$table->string('user_id')->nullable();
$table->string('postal_code')->nullable();
$table->timestamps();
});
}
}
This is the what the pivot table looks like
I am able to attach the information to the pivot table
public function storeInstitution(Request $request)
{
$user_id = auth()->user()->id;
$user = User::find($user_id);
$institution_id = $request->input('institution_id');
$user_program_choice = $request->input('program_choice');
$user_session = $request->input('session');
$user_inst = array(
'program_choice' => $user_program_choice,
'session' => $user_session,
'user_id' => $user_id,
'institution_id' => $institution_id
);
$user->institutions()->attach($institution_id, $user_inst);
return 'success';
}
But unable to update the attached pivot E.g I can't change the program_choice, particle physics to something like digital art
Here's my current code
public function updateInstitutions(Request $request, $pivot_id)#TODO id is pivot_id
{
$user_id = auth()->user()->id;
$user = User::find($user_id);
$institution_id = $request->input('institution_id');
$pivot_attributes = array(
'user_id' => $user_id,
'institution_id' => $institution_id,
'session' => $request->input('session'),
'program_choice' => $request->input('program_choice'),
);
$user->institutions()->updateExistingPivots($institution_id, $pivot_attributes, false);
return 'success';
}
How do I update my pivot data, using the pivot id?
Check the documentation regarding this aspect.
Updating A Record On A Pivot Table
If you need to update an existing row in your pivot table, you may use
updateExistingPivot method. This method accepts the pivot record
foreign key and an array of attributes to update:
$user = App\Models\User::find(1);
$user->roles()->updateExistingPivot($roleId, $attributes);

Need to save foreign key manually on belongsTo relationship with withDefault()?

it seems that I need to save the original model on the newly generated model in order to save the relation correctly.
I hope the below test case illustrates my problem:
// migrations
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->bigInteger('user_id')->nullable();
$table->timestamps();
});
//models
class User extends Model
{
public function posts()
{
return $this->hasMany(Post::class);
}
}
class Post extends Model
{
public function user()
{
return $this->belongsTo(User::class)
->withDefault(['name' => 'Guest User']);
}
}
//test
public function test_foreign_key()
{
$post = factory(Post::class)->create();
$user = $post->user; // created from ->withDefault()
$user->save();
$this->assertNotNull($post->user);
$this->assertNotNull($post->user_id);
}
With additional association of the original model the test passes:
public function test_foreign_key_associates()
{
$post = factory(Post::class)->create();
$post->user->save();
$this->assertNotNull($post->user);
$post->user()->associate($post);
$this->assertNotNull($post->user_id);
}
edit: what I'm doing right now is the following for the withDefault relationship:
class Post extends Model
{
public function user()
{
return $this->belongsTo(User::class)
->withDefault(function (User $user, Post $post) {
$user->name = "Guest User";
$user->save();
$post->user_id = $user->id;
});
}
}

Relationships retrieve user emails

I'm trying to understand how I can join the tables users and teams to members in fact ?
Users Table:
id | name | email | password
1 alain alain#gmail.com *****
2 eric eric1#gmail.com *****
Teams Table:
id | name
1 R.O.S
2 Stephanois
Members Table:
id | user_id (email) | team_id (name)
1 1 1
2 2 1
DataBase:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function up()
{
Schema::create('members', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('team_id')->unsigned()->nullable();
$table->foreign('team_id')->references('id')->on('teams');
$table->timestamps();
});
}
public function up()
{
Schema::create('teams', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
}
User Model:
protected $fillable = [
'name', 'email', 'password',
];
public function team(){
return $this->hasOne('App\Team', 'user_id', 'id'); ?
}
public function member(){
return $this->hasOne('App\Member', 'user_id', 'id'); ?
}
Team Model:
protected $fillable = [
'user_id', 'name'
];
public function member(){
return $this->hasMany('App\Member', 'team_id'); ?
}
public function user(){
return $this->belongsTo('App\User', 'id', 'user_id'); ?
}
Member Model:
protected $fillable = [
'id', 'user_id', 'team_id'
];
public function team(){
return $this->belongsTo('App\Team', 'team_id');
}
public function user(){
return $this->belongsTo('App\User', 'id', 'user_id'); ?
}
I thank you in advance for your help
Edit: when I log in with the user 'alain#gmail.com' I don't retrieve the information for the user 'alain#gmail.com' ? ie user_id and team_id.
public function index(Request $request)
{
$user = $request->user();
$members = Member::query()
->when($user->hasRole('admin') !== true, function (Builder $query) use ($user) {
$query->where('id???', $user->email); ????
})
->when($request->has('search'), function (Builder $query) use ($request) {
$query->where('name??', 'like', '%' . $request->input('search') . '%');
})->with('team:id,name')
->paginate(5);
return view('admin.members.index', compact('members'))
->with('display_search', $user->hasRole('admin'));
}
Which one is you're trying to achieve is not enough clear. If I guess, you want to find out which user is in which team then, in this situation you can go through -
User.php model -
protected $fillable = [
'name', 'email', 'password',
];
public function member(){
return $this->belongsTo('App\Member', 'user_id', 'id');
}
Member.php model -
protected $fillable = [
'id', 'user_id', 'team_id'
];
public function team(){
return $this->belongsTo('App\Team', 'team_id');
}
public function user(){
return $this->belongsTo('App\User', 'user_id', 'id');
}
Team.php model (keep as it is for now)-
class Team extends Model
{
protected $fillable = [
'name'
];
}
And finally call your members those are already in a team in your controller method-
$members = Member::with('team', 'user')->get();
return view('your-blade-file-name', compact('members'));
And, in your blade file -
#foreach($members as $member)
<p>Name: {{ $member->user->name }} , Email: {{ $member->user->email }} , Team - {{ $member->team->name }}</p>
#endforeach
Output:
Name: alain, Email: alain#gmail.com , Team - R.O.S
Name: eric, Email: eric1#gmail.com , Team - R.O.S
If you want a user can belong to a single team, then you don't need an intermediate table. Just add a column in the user table like team_id that will hold the value of which team the user belong.
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->unsignedInteger('team_id'); //make it nullable or anything based on your need
$table->rememberToken();
$table->timestamps();
});
Schema::create('teams', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
And now make the relationships in the models:
User Model
protected $fillable = [
'name', 'email', 'password','team_id'
];
public function team()
{
return $this->belongsTo('App\Team', 'team_id');
}
Team Model
protected $fillable = [
'name'
];
public function users()
{
return $this->hasMany('App\User', 'team_id');
}
In the above relationships a user belongs to a single team and a team has many users. I am pretty sure you are trying to achieve this. Feel free to ask if you find anything hard to understand.
Look you don't need the intermediate model Member. If you want a many to many relationship then you need to use an intermediate table.

Laravel - Many to many not pulling back results

I have a User class with the following:
public function school()
{
return $this->belongsToMany('School');
}
I have a School class with the following:
public function user()
{
return $this->belongsToMany('User');
}
I create my pivot table use the pivot generator, here is the migrate for it:
public function up()
{
Schema::create('school_user', function(Blueprint $table) {
$table->increments('id');
$table->integer('school_id')->unsigned()->index();
$table->foreign('school_id')->references('id')->on('schools')->onDelete('cascade');
$table->integer('user_id')->unsigned()->index();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->boolean('admin');
$table->timestamps();
});
}
There is only one item in the user table, the school table, and the pivot table. When I do
$user = User::where('email', '=', Input::get('email'))->first();
$schools = $user->schools;
return Response::json([
'success' => true,
'user' => $user->toArray(),
'schools' => $schools
]);
It returns a null for the schools. Am I missing something?
You have declared:
public function school()
{
return $this->belongsToMany('School');
}
But using $user->schools, you should change the function declaration to schools:
public function schools()
{
//...
}
Also make sure that, you are using the right relationship, I'm confussed because one user may belongs to only one school (logically).

Resources