shcode's avatar

What is the best implementation on Student, Teacher, Lesson, and Score relation

Let's say I have 4 entities

  1. Student, that can take many lesson
  2. Teacher, that can teach many lesson
  3. Lesson, that can be taken by many student and can be taught by many teacher.
  4. Score, that given to a student with each lesson they have taken and each lesson has different type of score, ie: exam 1, exam 2, midterm exam, etc.

How can I implement this with Eloquent Model? Should I use student_lesson pivot and teacher_lesson pivot and then I create relation between score and student lesson. Is it right?

Thanks before and I'm sorry if my English is bad.

0 likes
9 replies
martinbean's avatar

@shcode If you look over your list, you can infer your relationships from them:

  1. A student can belong to many lessons
  2. A teacher can belongs to many lesson

If a score belongs to both a lesson and a student, then you could put a score on the table that maps students to lessons. However, if a student can have many scores during a lesson, then you may consider another entity: Examination, that belongs to both a student and a lesson.

Also, I don’t think “lesson” is the right term. You might consider “course”, as a lesson to me is an individual, timetabled event. So I may attend 30 lessons as part of my course, during which I may also sit numerous examinations.

shcode's avatar

@martinbean Thank you for your reply. However, I want to ask how to implement to Eloquent Model not Database Relation. Ok, let's change lesson to course, but I don't want to add Examination.

I already have solution for this, but I don't know if it's right and I have a little problem too.

Course Model

class Course extends Model {

    public function teachers()
    {
        return $this->belongsToMany('App\Teacher');
    }

    public function students()
    {
        return $this->belongsToMany('App\Student', 'course_student', 'course_id', 'student_id')->withPivot('id');
    }

    public function newPivot(Model $parent, array $attributes, $table, $exists) 
    {
        if ($parent instanceof Student) {
            return new CourseStudent($parent, $attributes, $table, $exists);
        }
        return parent::newPivot($parent, $attributes, $table, $exists);
    }
}

Student Model

class Student extends Model {

    public function courses()
    {
        return $this->belongsToMany('App\Course', 'course_student', 'student_id', 'course_id')->withPivot('id');
    }

    public function newPivot(Model $parent, array $attributes, $table, $exists) 
    {
        if ($parent instanceof Course) {
            return new CourseStudent($parent, $attributes, $table, $exists);
        }
        return parent::newPivot($parent, $attributes, $table, $exists);
    }
}

Teacher Model

class Teacher extends Model {

    public function courses()
    {
        return $this->belongsToMany('App\Course');
    }

}

CourseStudent Pivot

class CourseStudent extends Pivot {
    protected $table = 'course_student';

    public function scores() 
    {
        return $this->hasMany('App\Score', 'course_student_id'); 
    }
}

When I try to get Score from Student, it's work. But if I try to get Student from Score, I get an error.

$student->courses()->first()->pivot->scores(); // it work.
$score->course(); // Error

Argument 1 passed to Illuminate\Database\Eloquent\Relations\Pivot::__construct() must be an instance of Illuminate\Database\Eloquent\Model, none given, called in F:\pindah\laravel\course\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php on line 809 and defined

Maybe I have to create another model that implemet CourseStudent for Scores to get the right relation. Is it right like this?

davorminchorov's avatar

You don't need the CourseStudent (pivot) Model. You need a Score (maybe grades is a better table name than scores?) Model. The scores table should have a one to one relationship with a student and a course. Feel free to correct me if I am wrong but that's how I see it.

shcode's avatar

@Ruffles What do you mean by one to one relationship? Can you give me an example?

davorminchorov's avatar

Something like this:

//Score.php

public function course() 
{
    return $this->belongsTo('Course');
}

public function student() 
{
    return $this->belongsTo('Student');
}

//Student.php
public function score() 
{
    return $this->hasOne('Score');
}

//Course.php
public function score() 
{
    return $this->hasOne('Score');
}

A student can have many scores but only one per course so that's why it's one to one relationship.

You can have different fields for scores in the table like exam 1, exam 2, test 1, test 2, attendance, homework, project etc

Your scores table will look something like this:

id |    course_id|  student_id| midterm| finals| attendance| project| total_exams //etc
-------------------------------------------------------------------------------------------------------------------
1|  1|  1|  78| 80| 100|    20| 17| // random numbers for the scores
--------------------------------------------------------------------------------------------------------------------    

I'd love to hear what other people have to say about this database design.

1 like
shcode's avatar

@Ruffles I think it's not good. What if I want to add another exam that does not exist in the database?

davorminchorov's avatar

What kind of exams? Are we talking about university exams? Usually, the number of exams are limited. (2 main and 1 or 2 for those who failed that semester)

shcode's avatar

Aw, it's never ends. What I want to know is how to get the best implementation for table that has foreign key on pivot. How can I do that in eloquent model. That's it.

Please or to participate in this conversation.