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