Home > Back-end >  Laravel one to many relationship query doesn't get produced properly
Laravel one to many relationship query doesn't get produced properly

Time:07-18

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'));
    }
}

CodePudding user response:

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

CodePudding user response:

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

  • Related