问题
I am using laravel 5.1. The scenario is as follows(this is an example. The real scenario is similar to this example)
I have 3 models
- College
- Student
- Teacher
A college can have many students but a student can belong to only 1 college.
A college can have many teachers but a teacher can belong to only 1 college.
I want to establish relationships between these tables in laravel. One of the methods for this is to place a college_id foreign key on the Students and Teachers table. But in my case, this foreign key will be null a lot of times. So rather than have separate columns in 3-4 tables with mostly null values, I wanted to explore the option of having a polymorphic relationship for College table.
This is what I tried: The example given in the laravel docs(link below) depict a one-to-many relationship whereas my scenario is more of a many to one relationship.
http://laravel.com/docs/5.1/eloquent-relationships#polymorphic-relations
As given in the example, having collegeable_id and collegeable_type columns on the College table would not have fulfilled my requirement as a college can contain many students/teachers so I created a pivot table:
Schema::create('collegeables', function (Blueprint $table) {
$table->integer('college_id')->unsigned();
$table->integer('collegeable_id')->unsigned();
$table->string('collegeable_type');
});
And I have the following models
College Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class College extends Model
{
public function students()
{
return $this->morphedByMany('App\Student', 'collegeable');
}
}
Student Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Student extends Model
{
public function college()
{
return $this->morphOne('App\Colleges', 'collegeable');
}
}
With this arrangement, I am able to store students using College model instance like this
$college = \App\College::find(1);
$student = new \App\Student;
$student->name = 'John Doe';
$college->students()->save($student);
But when I try to retrieve a College model instance using a student model instance as specified below, it gives me an error:-
public function index()
{
return \App\Student::find(1)->college;
}
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'colleges.collegeable_id'
This is kind of expected as morphOne works with columns in a table I suppose. If I change the morphOne function in Student Model to morphToMany, the code starts working and I am able to retrieve values as well. But that make this relationship a many to many which again is not what I want.
So my question is this:- Is their a morphSomething function I can use in the student model to be able to retrieve values for the student's college while maintaining the relationship as a one-to-many?
Any help would be really appreciated. Thanks.
回答1:
There's no reason to use Polymorphic relationships here. Instead, just add a foreign key to your colleges
table on both your students
and teachers
tables. Like this:
colleges
id
name
teachers
id
name
college_id
students
id
name
college_id
Then your models can use the belongsTo()
and hasMany()
relations, like so:
class College extends Model {
public function students() {
return $this->hasMany(App\Student::class);
}
public function teachers() {
return $this->hasMany(App\Teacher::class);
}
}
class Teacher extends Model {
public function colleges() {
return $this->belongsTo(App\College::class);
}
}
class Student extends Model {
public function colleges() {
return $this->belongsTo(App\College::class);
}
}
Polymorphic one-to-many relations are for the opposite of this relationship where you have a model that can only be related to a single record, but that record can be many different models.
Edit: To further explain why a polymorphic relationship isn't needed here, let's take a look at where it would be needed. Say you have a simple CRM style website. There are Customers and Projects and you want to have Comments on both. In this case, you would make Comments a polymorphic relationship because Comments belong to a single Customer or a single Project, but not both.
Your relationship is the exact opposite. In your case, Students and Teachers belong to a college. If you were to follow the previous example's pattern, a college would have belonged to a single student or teacher.
来源:https://stackoverflow.com/questions/33370264/laravel-many-to-one-polymorphic-relationship