Pasindu Ruwandeniya
Pasindu Ruwandeniya

Reputation: 637

Laravel one to many relationship query doesn't get produced properly

I'm designing a feedback web app using Laravel 9 and it has two tables called users and feedbacks, which have a one to many relationship. I tried to implement this using Laravel but when I try to get the data using User Model, the query is executed as below.

select * from `feedback` where `feedback`.`user_userId` = 1 and `feedback`.`user_userId` is not null

which is wrong. The correct query should be,

select * from `feedback` where `feedback`.`userId` = 1 and `feedback`.`userId` is not null

I don't know what I did wrong. Below I have put relevant code,

Feedback Model -

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Feedback extends Model
{
    use HasFactory;

    //One single user can have many feedbacks.
    public function user() {
        return $this->belongsTo(User::class);
    }
}

User model -

<?php

namespace App\Models;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'username',
        'gender',
        'email',
        'password',
        'is_admin',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
        'is_admin',
    ];

    protected $primaryKey = 'userId';

    public function feedbacks() {
        return $this->hasMany(Feedback::class);
    }

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

create_users_table migration

public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('userId');
            $table->string('name');
            $table->string('username')->unique();
            $table->string('gender');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->boolean('is_admin')->default(0);
            $table->rememberToken();
            $table->timestamps();
        });
    }

create_feedback_table migration

public function up()
    {
        Schema::create('feedback', function (Blueprint $table) {
            $table->increments('feedbackId');
            $table->text('feedback');
            $table->unsignedInteger('userId');
            $table->timestamps();
            $table->foreign('userId')
                ->references('userId')
                ->on('users')
                ->onDelete('cascade');
        });
    }

Please request if you need more code to resolve this issue, I will update the question accordingly. TIA.

Edit - FeedbackController to get the data,

class FeedbackController extends Controller
{
    public function giveFeedback($userId)
    {
        $userData = User::find($userId);

        return view('feedback.givefeedback', compact('userData'));
    }
}

Upvotes: 1

Views: 668

Answers (2)

aceraven777
aceraven777

Reputation: 4556

In Laravel, The foreign key name is in this format {foreigntablename}_{primarykey}.

Since you have a custom naming of primary keys and foreign keys, you must customize the foreign key name by specifying it in the 2nd parameter

public function feedbacks() {
    return $this->hasMany(Feedback::class, 'userId');
}

You can find this in the Laravel documentation: https://laravel.com/docs/9.x/eloquent-relationships#one-to-many

Upvotes: 2

Waqas Altaf
Waqas Altaf

Reputation: 392

Remember, Eloquent will automatically determine the proper foreign key column for the Feedback model. By convention, Eloquent will take the "snake case" name of the parent model and suffix it with _id. So, in this example, Eloquent will assume the foreign key column on the Feedback model is user_id. You are using userID as foreign key in feedback model but no defining it in relation, feedbacks relation by default considering user_id as foreign key.

Use one of the following code in relationship.

    public function feedbacks() {
       return $this->hasMany(Feedback::class, 'userID');  
    }   
     OR
    public function feedbacks() {
        return $this->hasMany(Feedback::class, 'userID', 'id');
    }       
           

See documentation to learn more about Relationships

Upvotes: 2

Related Questions