#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. Извините, я не понимаю — возможно, вы могли бы обновить свой ответ, чтобы отразить то, что вы имеете в виду, и показать сторону контроллера и показать вариант использования в представлении?