Reputation: 637
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
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
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