我正在研究一个新项目,想了解不同的人如何处理Lavavel中他们的模型之间的关系。
假设我们拥有模型School
,Batch
,Student
和User
,它们之间的关系如下:
A School hasMany Batches.
A Batch belongsTo a School.
A Batch hasMany Students.
A Student belongsTo a Batch.
A User hasMany Schools.
A School belongsTo a User.
(A User in this system is a person external to the school that goes in
and provides teaching services to the students on a weekly basis).
到目前为止,一切都很好。通过执行以下操作,我可以得到对学生负责的User
:
$student->batch->school->user;
但是,如果学生加入学校后没有立即将他们分配到批次中怎么办?我也需要这样的东西:
A Student BelongsTo a School.
A School hasMany Students.
然后我可以找到第二种方式对学生负责的人:
$student->school->user;
这在例如StudentPolicy中决定谁可以查看学生时很有用:
public function view(User $user, Student $student) {
// only the user that a student 'belongsTo' can view them
return $user->id === $student->batch->school->user->id;
// OR
return $user->id === $student->school->user->id;
}
但是在这里,我拥有同时属于Student
和School
的{{1}}。也许更加复杂,Batch
负责将User
分配给Student
,所以首先他们需要School
一个create
( Student
需要Student
belongTo
。然后为他们分配一个User
,然后一个School
。
所以我们最终可以得到:
Batch
这突然变得很复杂,因为我们拥有所有这些不同的所有权层次,并且采用了所有这些不同的遍历关系的方式来查看哪个模型与另一个模型以及如何关联。
但是,这可能是正常且良好的,并且// Student Model (simplified, obviously)
$this->belongsTo(School::class);
$this->belongsTo(Batch::class);
$this->belongsTo(User::class);
上的这三种不同关系是实现上述假设情况所必需的。我对Laravel和php来说相对较新,并且想了解其他更有经验的开发人员如何组织此工作。
答案 0 :(得分:-1)
我已投票结束您的问题,因为我认为该问题属于另一个StackExchange site,随着该问题朝着这个方向发展,您可以从DBA获得更多反馈。但是,为了提供帮助,我将提示您一种解决您的问题的方法。
我认为这是您可以做的:
- a School has many User
- a User has many School
=================================================
/** Result: */ School m-----m User (many-to-many)
在模型中,您只是考虑一个User
有很多School
,但是我认为一个School
也可以有很多User
。这是合乎逻辑的(但是,当然,您比我对用例了解更多)。如果我对这个假设没错,那么您将需要一个中间表(school_user
)。
# School.php
public function users()
{
return $this->belongsToMany(User::class);
}
# User.php
public function schools()
{
return $this->belongsToMany(School::class);
}
- a School has many Batch
- a Batch belongs to a School
=================================================
/** Result: */ School 1-----m Batch (one-to-many)
这非常简单。
# School.php
public function batches()
{
return $this->hasMany(Batch::class);
}
# Batch.php
public function school()
{
return $this->belongsTo(School::class);
}
- a Batch has many Student
- a Student belongs to a Batch
=================================================
/** Result: */ Batch 1-----m Student (one-to-many)
这也很简单
# Batch.php
public function students()
{
return $this->hasMany(Student::class);
}
# Student.php
public function school()
{
return $this->belongsTo(Batch::class);
}
- a School has many Student
- a Student belongs to a School
=================================================
/** Result: */ School 1-----m Student (one-to-many)
现在这种安排在逻辑上是合理的。实际上,您可以通过两种方式处理这种关系。一个是上面的示例(选项d.1
),第二个(选项d.2
)可以创建一个特定的Batch
对象(我们称其为“一般批处理”或“未分配”)并将尚未与汉斯链接的每个Student
链接到该通用Batch
,然后通过该链接获取对此Batch
负责的User
Student
:Batch
。
obs:在这里,您需要在$student->batch->school->user
表(students
)中增加一列。
school_id
您可以在模型中添加其他方法以缩短访问权限。当然这是可选的。
# School.php
public function students()
{
return $this->hasMany(Student::class);
}
# Student.php
public function school()
{
return $this->belongsTo(School::class);
}
使用此设置,您现在可以解决您的问题。
“但是,如果学生加入学校后没有立即将他们分配到批次中怎么办?”
# Student.php
public function school()
{
return $this->batch->school;
}
“也许更为复杂,用户负责将学生分配给学校,所以首先他们需要创建一个学生...然后分配一个学校,然后再分配一批”。
在这种情况下,您可以在// with option d.1
$user = $student->school->user;
// with option d.2
$user = $student->batch->school->user;
$user = $student->school->user; // with the shortcut
表(students
)school_id
中创建外键。这样,您可以创建Student对象,而无需在创建时分配学校。
OBS:为了使其正常工作,只需避免在db中设置外键约束,并让Laravel处理该关系。该约束有助于在数据库级别上强制引用完整性,但是您可以在逻辑级别上进行此断言。