Многоуровневые отношения Laravel с соответствующей таблицей, относящейся к родительскому

#laravel

#laravel

Вопрос:

Прошу прощения, если название сбивает с толку, но позвольте мне попытаться уточнить. У меня есть таблица учащихся, за которой следует таблица процессов, в которой есть дочерняя таблица задач процесса. Затем я хочу, чтобы для каждого учащегося была соответствующая запись для каждого процесса и аналогично соответствующая запись для каждой задачи процесса.

например:

 Student ABC
Student DEF
Student GHI

Process 1: Enter Student Process
    - Process Task: Enter his name
    - Process Task: Phone the student
    - Process Task: Upload his photo

Process 2: Something else
    - Process Task: Tick this
    - Process Task: Tick that
  

Чтобы затем я мог установить «списки дел» (процессы и их соответствующие задачи), каждый из которых имеет соответствующие статусы для каждого учащегося.

(Упрощенные) таблицы

 Schema::create('students', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('student_name',64);
        $table->string('student_surname',64);
        $table->timestamps();
    });

    Schema::create('processes', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->string('process')->nullable();
        $table->timestamps();
    });

    Schema::create('process_tasks', function (Blueprint $table) {
        $table->bigIncrements('id');
        $table->bigInteger('process_id')->unsigned()->index('process_id_index');
        $table->string('process_task')->nullable();
        $table->integer('sequence'); // task order
        $table->timestamps();
    });

    Schema::create('process_student', function (Blueprint $table) {
        $table->bigInteger('student_id')->unsigned();
        $table->bigInteger('process_id')->unsigned();
        $table->tinyInteger('status')->unsigned()->nullable(); // eg: awaiting feedback, due, etc
        $table->timestamps();
        $table->foreign('student_id', 'ps_student_id_foreign')->references('id')->on('students')->onDelete('cascade');
        $table->foreign('process_id', 'ps_process_id_foreign')->references('id')->on('processes')->onDelete('cascade');
    });

    Schema::create('process_task_student', function (Blueprint $table) {
        $table->bigInteger('student_id')->unsigned();
        $table->bigInteger('process_task_id')->unsigned();
        $table->boolean('complete')->default(0); // eg: awaiting feedback, due, etc
        $table->timestamps();
        $table->foreign('student_id', 'spt_student_id_foreign')->references('id')->on('students')->onDelete('cascade');
        $table->foreign('process_task_id', 'spt_process_task_id_foreign')->references('id')->on('process_tasks')->onDelete('cascade');
    });
  

Модели / отношения

Процесс

 protected $fillable = [
    'process'
];

public function tasks() {
    return $this->hasMany('AppProcessTask');
}
  

Задача обработки

 protected $fillable = [
    'process_id',
    'process_task',
    'sequence'
];
  

Студенты

 protected $fillable = [
    'id','student_name','student_surname'
];

public function processes() {
    return $this->belongsToMany('AppProcess')->withTimestamps();
}

public function tasks() {
    return $this->processes()->belongsToMany('AppProcessTask')->withTimestamps();
}
  

// Редактировать: добавлен дополнительный код для пояснения

Контроллер:

 public function show($id)
{
    $student = Student::with(['processes','processes.tasks'])->findOrFail($id);
    return view('students.show', compact('student'));
}
  

Вид:

 @foreach ($student->processes as $student_process)
@foreach ($student_process->tasks->sortBy('sequence') as $student_process_task)
    <div class="kt-widget2__item kt-widget2__item--primary">
      <div class="kt-widget2__checkbox">
        <label class="kt-checkbox kt-checkbox--solid kt-checkbox--single">
        <input type="checkbox">
        <span></span>
        </label>
      </div>
      <div class="kt-widget2__info">
        <a href="#" class="kt-widget2__title">
            {{$student_process_task->process_task}}
        </a>
      </div>
    </div>
@endforeach
@endforeach
  

Я чувствую, что у меня что-то не так с моими отношениями? Как бы я получил процесс, его соответствующие задачи для конкретного учащегося?

Ответ №1:

Таким образом, у вас есть отношения «многие ко многим» между учащимися и процессами, но «один ко многим» между процессами и задачами. Но у вас также есть сводная таблица для отношений между процессами и задачами. Я в замешательстве. Во-первых, убедитесь, что вы добавили обратные отношения, поскольку я их не вижу. Если процесс-задача относится ко многим, измените hasMany на belongsToMany. Короче говоря, пожалуйста, дважды проверьте, правильно ли вы структурировали все отношения. Затем перейдите к StudentController.php и

 public function index()
{
  return Student::with("processes.tasks")->get();
}
  

Найдите «вложенную нетерпеливую загрузку» на этой странице https://laravel.com/docs/8.x/eloquent-relationships для получения дополнительной информации.

Комментарии:

1. Процесс имеет множество задач — как показано в примере. Это сам «список дел», тогда у каждого учащегося есть «копия» каждого такого процесса / задачи. Например: мне нужно найти «Student ABC» и посмотреть, что у него status есть «Процесс 1: введите процесс Student» и какое complete значение имеет «Задача процесса: введите его имя», Чтобы уточнить, что ProcessTask «принадлежит» процессу (поскольку он будет принадлежать только одному процессу).

2. Моя ошибка. Посмотрев на его название, я подумал, что «process_task» — это сводная таблица (мышечная память). Но другие части моего ответа должны быть правильными. Итак, определите обратные отношения и обновите свою индексную функцию.

3. Это не помогает, потому что ссылка @foreach ($student->processes as $student_process) ссылается на process_student сводную таблицу (правильно). Однако @foreach ($student_process->tasks->sortBy('sequence') as $student_process_task) ссылается ли на tasks таблицу, а не на сводную таблицу `process_task_student»?

4. Вам не нужна какая-либо прямая связь между учащимися и задачами, поэтому сводная таблица «process_task_student». Модели учащихся и процессов имеют отношения «многие ко многим». Модели процессов и задач имеют отношения «один ко многим». Это означает, что вы можете получать доступ к задачам через процесс из контроллера учащихся. Есть много способов сделать это.

5. Извините, я не понимаю — возможно, вы могли бы обновить свой ответ, чтобы отразить то, что вы имеете в виду, и показать сторону контроллера и показать вариант использования в представлении?