Laravel belongsToMany only works one way - php

I'm trying to make a many to many relation, in this example with user and role.
In User model I got this:
public function roles()
{
return $this->belongsToMany('App\Role', 'user_role', 'user_id', 'role_id');
}
In Role model I got this:
public function users()
{
return $this->belongsToMany('App\User', 'user_role', 'role_id', 'user_id');
}
And my pivot table user_role:
public function up()
{
Schema::create('user_role', function(Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->timestamps();
$table->foreign('role_id')->references('id')->on('roles');
$table->foreign('user_id')->references('id')->on('users');
});
}
Now when I do $user->roles()->attach(1); it makes a row in the user_role table. But the problem is when I want to access it: $user->roles; it returns nothing. It works with $role->users; but not the other way. What am I doing wrong?

Solved : Laravel 5.2.29
make sure the table name is role_user
$user = User::find(1);
$role = Role::find(2);
// In this example I am passing in a Role object but $role->id also works
$user->roles()->attach($role);
Hope this works for you.

You have to reload the relationship after attaching like so
$user->roles()->attach($role);
$user->load('roles');

Related

How to update data of pivot table in Many To Many relationship

I have a Many To Many relationshp between User Model & Wallet Model.
So at the User.php Model:
public function wallets()
{
return $this->belongsToMany(Wallet::class,'user_wallet','user_id','wallet_id')->withPivot('balance');
}
And at Wallet.php Model:
public function users()
{
return $this->belongsToMany(User::class,'user_wallet','wallet_id','user_id');
}
And also the table Migration of user_wallet table also goes here:
public function up()
{
Schema::create('user_wallet', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('usr_id')->on('users');
$table->unsignedBigInteger('wallet_id');
$table->foreign('wallet_id')->references('id')->on('wallets');
$table->integer('balance');
$table->timestamps();
});
}
And at the Controller, I added this:
$bal = Wallet::with("users")->whereHas('users',function ($query)use($wallet_id,$user_id){
$query->where('wallet_id',$wallet_id);
$query->where('user_id',$user_id);
});
dd($bal);
But now I need to update balance filed of this pivot table which has the same user_id and wallet_id:
So how to do this?
I would really appreciate any idea or suggestion from you guys...
Thanks in advance.
use updateExistingPivot
$wallet = Wallet::find($wallet_id);
$wallet->users()->updateExistingPivot($user_id,["balance"=>500]);
Ref:https://laravel.com/docs/8.x/eloquent-relationships#updating-a-record-on-the-intermediate-table
use something like this:
$bal->users()->sync([
$user_id => [
'balance' => 1
],
]);

Laravel 8: Trying to get property 'name' of non-object

I'm making a forum with Laravel 8. And I want to return a question and show the name of the user who has asked this question.
At the Model User.php I coded this:
public function questions()
{
return $this->hasMany(Question::class);
}
And also I put this at Question.php Model:
public function users()
{
return $this->belongsTo(User::class);
}
So in order to get the name of a user who has asked the question, I put this:
{{ $show->users->name }}
But now I get this error message:
Trying to get property 'name' of non-object**
So what's going wrong here? How can I fix this issue?
Note that this $show variable comes from this Controller Method and gets the question information:
public function showQuestion($slug)
{
$show = Question::where('slug', $slug)->first();
if(is_null($show)){
abort(404);
}
return view('questions.question',[
'show' => $show
]);
}
And also each question has stored the user_id of the user who has asked this question:
So if you have any idea or suggestion on this, please let me know, I would really appreciate that!
Update #1:
Here is the table users:
Update #2:
questions table migration:
Schema::create('questions', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->string('title');
$table->string('slug');
$table->text('body');
$table->string('category');
$table->string('private')->nullable();
$table->timestamps();
});
users table migration:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('phone')->unique();
$table->binary('image')->nullable();
$table->string('job')->nullable();
$table->string('location')->nullable();
$table->string('bio')->nullable();
$table->string('skills')->nullable();
$table->string('stackoverflow')->nullable();
$table->string('github')->nullable();
$table->string('instagram')->nullable();
$table->string('linkedin')->nullable();
$table->string('website')->nullable();
$table->rememberToken();
$table->timestamps();
});
}
Your relationship on Question to User should be named user instead of users. When you are letting Eloquent automatically figure out the fields for the belongsTo relationship it actually uses the name of the relationship method to help determine what the foreign key is.
If you don't want to follow that type of convention with naming the method like that you can explicitly set the foreign key used by the belongsTo method:
public function belongsTo($related, $foreignKey = null, $ownerKey = null, $relation = null)
You have to change the function name users to user in Question model. when you are letting Eloquent automatically figure out the relationship you have to name the function regarding to their relationships like one to one or one to many or many to many.
Try this
public function user()
{
return $this->belongsTo(User::class);
}
{{ $show->user->name }}
Use this for show function in controller
$student= Student::all();
return view('showData',['data' => $student]);
and for view to show data
#foreach($data as $stud)
<tr>
<td>{{$stud)->id}}</td>
<td>{{$stud)->name}}</td>
</tr>
#endforeach
return $this->belongsTo(User::class);
switch to like this, I switched to hasOne and it worked well
return $this->hasOne(User::class, 'id', 'user_id')
->withDefault(['name' => '']);

Eloquent many to many relationship is always empty

I know this question has been asked a lot but all answers didn't seem to work for me - or at least the questions I found were about the pivot table.
I have a many to many relationship (User - Appointment) which is joined by the pivot table "apointment_user", see migrations below.
Schema::create('appointment_user', function (Blueprint $table) {
$table->unsignedInteger('user_id')->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->unsignedInteger('appointment_id')->nullable();
$table->foreign('appointment_id')->references('id')->on('appointments');
$table->primary(['user_id','appointment_id']);
$table->timestamps();
});
Schema::create('appointments', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->dateTime('date');
$table->string('location');
$table->dateTime('departure');
$table->timestamps();
});
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->date('last_login')->nullable();
$table->rememberToken();
$table->timestamps();
$table->softDeletes();
});
class User extends Model {
protected $with = ['appointments'];
public function appointments() : BelongsToMany {
return $this->belongsToMany(Appointment::class);
}
}
class Appointment extends Model {
public function users() : BelongsToMany {
return $this->belongsToMany(User::class);
}
}
I have a user with the ID 1 and about 10 appointments, which I do attach to the relationship in a seeder. The pivot table has 10 records, as intended (User ID is always 1).
However, if I dump my User object using dd(User::find(1)), the relationship is always an empty collection. However, a 1:n relationship (between a role works well).
Does anybody see what I'm missing? Any help is appreciated.
Many thanks and kind regards
Edit
I just tried some other kind of dumping. I've simply returned my User-Object as JSON-response and there the relationship is filled with 10 appointments... strange.
Though it seems that your table and column names are as Laravel would guess, have you tried expliciting the names?
class User extends Model {
protected $with = ['appointments'];
public function appointments() : BelongsToMany {
return $this->belongsToMany(Appointment::class, 'appointment_user', 'user_id', 'appointment_id');
}
}
class Appointment extends Model {
public function users() : BelongsToMany {
return $this->belongsToMany(User::class, 'appointment_user', 'appointment_id', 'user_id');
}
}

Laravel seeds wrong id values in many to many relations

I currently learn Laravel 5.8 and created database where users can have two roles: admin or user stored in roles table. I tried to populate role_users intermediate table but Laravel doubles rows and seeds wrong data like this: Crazy ROLE_USER Table. role_id should be only 1 or 2. user_id should be unique. What did I do wrong?
User model:
public function roles() {
return $this->belongsToMany('App\Role', 'role_users')->withTimestamps();
}
Role model:
public function roles() {
return $this->belongsToMany('App\User', 'role_users')->withTimestamps();
}
create_role_users_table migration:
Schema::create('role_users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('role_id');
$table->unsignedBigInteger('user_id');
$table->timestamps();
});
RoleUsersFactory factory:
$factory->define(RoleUser::class, function (Faker $faker) {
return [
'role_id' => Role::all()->random()->id,
'user_id' => User::all()->random()->id,];
});
RoleTableSeeder seeder:
$role_user = new Role();
$role_user->role = 'user';
$role_user->save();
$role_admin = new Role();
$role_admin->role = 'admin';
$role_admin->save();
DatabaseSeeder seeder:
$this->call(RoleTableSeeder::class);
factory(User::class, 5)->create()->each(function($user) {
$user->roles()->save(factory(RoleUser::class)->make());
});
create a role then.
$role = Role::create(['role_name' => 'admin']);
use attach()
factory(User::class, 100)->create()->each(function ($user) use ($role ) {
$role ->users()->attach($user);
});
Try the above code.
This will create 100 different users with admin as role.
you can add other roles like this.
hope this suite for you.
You have the wrong relationships (you state that you want all the users to have a single role, which should be a BelongsTo / HasMany).
On the User model, have this method:
public function role() {
return $this->belongsTo('App\Role');
}
Create this method on the Role model:
public function users() {
return $this->hasMany('App\User');
}
Delete the migration you made where the role_users table is created and create a new migration with the following code:
Schema::table('users', function(Blueprint $table) {
// remove the nullable if a user HAS to have a role at all times
$table->unsignedBigInteger('role_id')->nullable();
}
Now, as a last step, the seeders. Your Role-seeder is correct. You shouldn't change that. Change your User-seeder to the following:
factory(User::class, 100)->create(['role_id' => Role::all()->random()->id]);
This will create a database with 100 users, where each has a role of admin or normal user. You can get all the users attached to a role with $role->users and get the role of a user with $user->role.

Laravel one to many relationship results

Hello i am trying to create one to many relationship. One user from user table could have many companies, on other side company could have only one user.
my migration for company table is
public function up()
{
Schema::create('companies', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('address');
$table->string('city');
$table->string('state');
$table->string('contact_person');
$table->string('phone');
$table->string('industry');
$table->string('website');
$table->integer('id_user')->unsigned();
$table->foreign('id_user')->references('id')->on('users')->onUpdate('cascade')->onDelete('cascade');
$table->timestamps();
});
}
my user model is
/**
* Get the posts for the user.
*/
public function companies()
{
return $this->hasOne('App\Company','user_id');
}
my company model is
public function users()
{
return $this->belongsTo('App\User','id');
}
i am trying to get all companies for specific user
try with whereHas but no data in relation object
$results = Company::whereHas('users', function ($query) {
$query->where('users.id',1);
})->get();
Where is my error?
First thing you should change is companies() relation. It has to be hasMany, not hasOne:
public function companies()
{
return $this->hasMany('App\Company');
}
Then get user with all his companies:
$result = User::where('id', $id)->with('companies')->first();
Or, if you want to use Company model like in your example and get only companies:
$result = Company::where('user_id', $id)->get();
Also, you're using id_user in migration. Change it to user_id.

Categories