Rizki Hadiaturrasyid
Rizki Hadiaturrasyid

Reputation: 448

Eloquent whereHas is looking for 'user_id' instead of 'id' even though I defined 'id'

I have a users table:

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email')->unique();
    $table->integer('role_id')->unsigned();
    $table->timestamp('email_verified_at')->nullable();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});

A roles table:

Schema::create('roles', function (Blueprint $table) {
    $table->increments('id');
    $table->string('role');
    $table->timestamps();
});

And a payments table:

Schema::create('payments', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('user_id')->unsigned();
    $table->integer('driver_id')->unsigned();
    $table->integer('amount');
    $table->date('payment_date');
    $table->timestamps();
});

I also added foreign constraint on users on roles (role_id).

Schema::table('users', function ($table) {
            $table
            ->foreign('role_id')
            ->references('id')
            ->on('roles')
            ->onUpdate('cascade');
        });

When I tried generating dummy payments with faker, I'm trying to get random user_id from users where its role is user, and another random user_id from users where its role is driver.

$factory->define(App\Models\Payment::class, function (Faker $faker) {
    return [
        'user_id' => App\User:: //get user
                        whereHas('roles', function ($query) {
                            $query->where('role', 'user');}) //where its role is user
                        ->select('id') //get its id
                        ->get()
                        ->random(),
        'driver_id' => App\User::
                        whereHas('roles', function ($query) {
                            $query->where('role', 'driver');})
                        ->select('id')
                        ->get()
                        ->random(),
        'amount' => $faker->randomNumber,
        'payment_date' => $faker->date($format = 'Y-m-d', $max = 'now')
    ];
});

However with the whereHas it throws error:

Illuminate\Database\QueryException  : SQLSTATE[42S22]: Column not found: 1054 Unknown column 'roles.user_id' in 'where clause' (SQL: select `id` from `users` where exists (select * from `roles` where `users`.`id` = `roles`.`user_id` and `role` = driver))

If I remove the whereHas part like this, it works:

App\User::select('id')
           ->get()
           ->random(),

I am sure in my whereHas query I did not look for user_id in roles table, so why did it tries to do so?

EDIT: here is my model

role

class Role extends Model
{
    protected $table = 'roles';
    protected $fillable = [
        'role'
    ];

    public function user()
    {
        return $this->hasMany('App\User');
    }
}

user

class User extends Authenticatable
{
    use Notifiable;

    protected $fillable = [
        'name', 'email', 'password', 'role_id'
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    public function payments()
    {
        return $this->hasMany('App\Models\Payment');
    }

    public function roles()
    {
        return $this->belongsTo('App\Models\Role');
    }
}

Upvotes: 1

Views: 856

Answers (1)

Rizki Hadiaturrasyid
Rizki Hadiaturrasyid

Reputation: 448

Here is the solution I found. Laravel assumes that the foreign key for roles in user model is roles_id, even though I used role_id. To override this, put another parameter role_id after the model in belongsTo() function. in User model

public function roles()
{
    return $this->belongsTo('App\Models\Role','role_id');
}

Upvotes: 1

Related Questions