在Laravel中建立关系的最佳方法?

时间:2019-04-29 16:42:55

标签: php laravel

我正在研究一个新项目,想了解不同的人如何处理Lavavel中他们的模型之间的关系。

假设我们拥有模型SchoolBatchStudentUser,它们之间的关系如下:

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;

}

但是在这里,我拥有同时属于StudentSchool的{​​{1}}。也许更加复杂,Batch负责将User分配给Student,所以首先他们需要School一个createStudent需要Student belongTo。然后为他们分配一个User,然后一个School

所以我们最终可以得到:

Batch

这突然变得很复杂,因为我们拥有所有这些不同的所有权层次,并且采用了所有这些不同的遍历关系的方式来查看哪个模型与另一个模型以及如何关联。

但是,这可能是正常且良好的,并且// Student Model (simplified, obviously) $this->belongsTo(School::class); $this->belongsTo(Batch::class); $this->belongsTo(User::class); 上的这三种不同关系是实现上述假设情况所必需的。我对Laravel和php来说相对较新,并且想了解其他更有经验的开发人员如何组织此工作。

1 个答案:

答案 0 :(得分:-1)

我已投票结束您的问题,因为我认为该问题属于另一个StackExchange site,随着该问题朝着这个方向发展,您可以从DBA获得更多反馈。但是,为了提供帮助,我将提示您一种解决您的问题的方法。

我认为这是您可以做的:

a)学校和用户

- 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);
}

b)学校和批次

- 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);
}

c)批次和学生

- 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);
}

d)学校和学生

- 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 StudentBatch

模型选项d.1

obs:在这里,您需要在$student->batch->school->user表(students)中增加一列。

school_id

模型选项d.2

您可以在模型中添加其他方法以缩短访问权限。当然这是可选的。

# 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 表(studentsschool_id中创建外键。这样,您可以创建Student对象,而无需在创建时分配学校。

OBS:为了使其正常工作,只需避免在db中设置外键约束,并让Laravel处理该关系。该约束有助于在数据库级别上强制引用完整性,但是您可以在逻辑级别上进行此断言。

相关问题