兄弟姐妹的关系是多对多的自我关系。因此,对于多对多的自我关系,我们可以在模型中定义两个函数:
public function siblings()
{
return $this->belongsToMany('Student', 'student_sibling', 'student_id', 'sibling_id');
}
public function siblingOf()
{
return $this->belongsToMany('Student', 'student_sibling', 'sibling_id', 'student_id');
}
第一个返回学生兄弟姐妹的学生。兄弟姐妹也是如此。因此,第二个返回学生是兄弟姐妹的学生。
因此,我们可以合并两个馆藏,以获得学生兄弟姐妹的列表。这是我在控制器方法中的代码:
$siblingOf = $student->siblingOf;
$siblings = $student->siblings;
$siblings = $siblings->merge($siblingOf);
但还有更多。兄弟姐妹关系是一种与朋友关系不同的连锁关系。这意味着,如果X是Y的兄弟,Y是Z的兄弟,则Z是X的兄弟。
那么,如何收集所有兄弟姐妹的学生集合?
答案 0 :(得分:1)
我假设你有一个Student模型,其中student_id是你的主键,而一个数据透视表看起来像这样:
+---------+------------+------------+
| id (PK) | student_id | sibling_id |
+---------+------------+------------+
| 1 | 1 | 2 |
| 2 | 2 | 1 |
| 3 | 3 | 4 |
| 4 | 4 | 2 |
| 5 | 6 | 5 |
+---------+------------+------------+
在这个例子中,我们希望能够辨别出1,2,3和4是彼此的所有兄弟姐妹。 5和6也是兄弟姐妹。
解决此问题的一种方法是在模型中收集两个belongsToMany()
关系的结果 - 就像在问题中一样 - 然后递归迭代结果,继续检查belongsToMany()
直到我们的兄弟姐妹都用完为止。
在Student模型中,定义两个函数:
public function getAllSiblings(){
// create a collection containing just the first student
$this->siblings = $this->newCollection()->make($this);
// add siblings (recursively) to the collection
$this->gatherSiblings($this->student_id);
// OPTIONAL: remove the first student, if desired
$this->siblings->shift();
return($this->siblings);
}
private function gatherSiblings($student_id){
$checkStudent = Student::find($student_id);
if ($checkStudent) {
// get related siblings from model, combine them into one collection
$siblingOf = $checkStudent->siblingOf()->get();
$siblings = $checkStudent->siblings()->get();
$siblings = $siblings->merge($siblingOf);
// iterate over the related siblings
$siblings->each(function($sibling)
{
// if we've found a new sibling who's
// not already in the collection, add it
if(!$this->siblings->contains($sibling->student_id)) {
$this->siblings->push($sibling);
// look for more siblings (recurse)
$this->gatherSiblings($sibling->student_id);
};
});
return;
}
}
在您的控制器中,找到初始学生,然后从学生呼叫getAllSiblings()
:
$student = Student::find($id);
$siblings = $student->getAllSiblings();
结果是与原始学生的所有兄弟姐妹的集合。所以,如果你为学生1运行这个,你会得到一个包含学生2,3和4的集合。(如果你更愿意将原来的学生作为兄弟姐妹集合的一部分,那么为1运行它会返回1, 2,3和4,只需删除optional
中的getAllSiblings()
步骤。)
从那里,您可以根据需要将集合转换为数组或排序等。
答案 1 :(得分:1)
递归关系可以做到这一点,但它可能会导致无限循环(函数嵌套限制错误)。
无论如何,这是如何设置这种关系:
public function siblingsRecursive()
{
return $this->siblings()->with('siblingsRecursive');
}
public function siblings()
{
return $this->belongsToMany('Student', 'siblings');
}
然后你打电话,就像这样简单:
$students = Student::with('siblingsRecursive');
答案 2 :(得分:0)
我想你可能想要的是这个
public function siblings() {
return $this->hasMany(self::class, 'parent_id', 'parent_id');
}