KoolReport's Forum

Official Support Area, Q&As, Discussions, Suggestions and Bug reports.
Forum's Guidelines

Many to many relations #3371

Open Eugene opened this topic on on Nov 7 - 9 comments

Eugene commented on Nov 7

Hi,

do you have an example of the realization with edit possibility.

This relation use the 3rd table and I am a bit stuck how to correct make possibility to create and edit tables with these relations

KoolReport commented on Nov 8

Do you mean using the admin panel of dashboard framework? Could you please describe more details of your case.

Eugene commented on Nov 8

I mean Admin panel The case is pretty simple 2 tables with many to many relation via 3rd table like student, courses and junction table student-courses

if I edit or create a record in the student table I want to choose 1or more courses - actually it means new records in the junction table but it should work from the student table resource ... etc

KoolReport commented on Nov 11

In this case, you need to create a column "Courses" inside Student resource which has the Select2 multiple selection as input. This column is only available in Update and Create screen. In this Select2 input will be provided list of courses inside dataSource(). When the UpdateScreen/CreateScreen of student open, The Select2 will allow you to select one or more courses. When click Save, list of course id will be sent to server in format of array. Admin panel will help to convey those data to methods called updateRecord($conditions, $data) and createRecord($data) depend on screens.

These methods can be overwritten inside Student resource. So what you do inside that updateRecord() and createRecord() is to create/update student, and insert/update the list of course to the StudentCourse (linked table).

Eugene commented on Nov 11

Could you give more detailed answer maybe with example? I am not sure I understood what do I have to do

KoolReport commented on Nov 12

Ok, please give me some time, I will write some pseudo code for you.

Eugene commented on Nov 12

thank you I will wait

KoolReport commented on Nov 13

Hi Eugene, the code will be something like this:

You need first to create a CourseField, a virtual field to mange the list of courses in student table:

<?php

use demo\AdminAutoMaker;
use koolreport\dashboard\Field;

class CourseField extends Field
{
    protected $oriValue = null; // Use this value to avoid multiple query to database
    protected function onCreated()
    {
        $this->valueType("array");
    }

    public function orginalValue()
    {
        if($this->oriValue === null)
        {
            // Make query to database to get list of couses of particular student
            $arrayStudentCourseIds = AdminAutoMaker::table("student_course")
                    ->select("course_id")
                    ->where("student_id",$this->row["student_id"])
                    ->run()
                    ->pluck("course_id");
            //Save to oriValue
            $this->oriValue = $arrayStudentCourseIds;
        }
        return $this->oriValue;
    }

    public function defaultFormatValue($value, $row = null)
    {
        // To show list of student courses in array formats
        return json_encode($value);
    }
}

Now in the Student resource, you do this:

<?php

use koolreport\dashboard\admin\Resource;
use demo\AdminAutoMaker;
use koolreport\dashboard\fields\ID;
use koolreport\dashboard\fields\Text;
use koolreport\dashboard\inputs\Select2;

class Student extends Resource
{
    protected function onCreated()
    {
        $this->manageTable("students")->inSource(AdminAutoMaker::class);
    }

    protected function fields()
    {
        return [
            ID::create("student_id"),
            Text::create("student_name"),
            Text::create("student_email"),
            Text::create("student_phone"),
            Text::create("student_address"),
            CourseField::create("courses")
                ->inputWidget(
                    Select2::create()
                        ->dataSource(function(){
                            return AdminAutoMaker::table("courses")
                                ->select("course_id","course_name");
                        })
                        ->multiple(true)
                        ->value("course_id")
                        ->text("course_name")
                )
                ->showOnAll(false)
                ->showOnCreate(true)
                ->showOnUpdate(true)
        ];
    }

    public function createRecord($data)
    {

        $couses = null;
        if(isset($data["courses"])) {
            $courses = $data["courses"];
            unset($data["courses"]);
        }
        $result = parent::createRecord($data);
        if($result === false) {
            return false;
        }
        //Now we will insert student courses into student_course table
        if(is_array($courses)) {
            foreach($courses as $course_id) {
                AdminAutoMaker::table("student_course")->insert([
                    "student_id"=>$data["student_id"],
                    "course_id"=>$course_id
                ])->run();
            }
        }
        return true;
    }

    public function updateRecord($ids,$data)
    {
        $couses = null;
        if(isset($data["courses"])) {
            $courses = $data["courses"];
            unset($data["courses"]);
        }

        $result = parent::updateRecord($ids,$data);
        if($result === false) {
            return false;
        }

        //Now we delete all records in student_course table
        AdminAutoMaker::table("student_course")
            ->where("student_id",$data["student_id"])
            ->delete()
            ->run();

        //And then insert again
        if(is_array($courses)) {
            foreach($courses as $course_id) {
                AdminAutoMaker::table("student_course")->insert([
                    "student_id"=>$data["student_id"],
                    "course_id"=>$course_id
                ])->run();
            }
        }
        return true;
    }

}

Hope that helps.

Eugene commented on Nov 13

Thank you, but I met with some issues

  1. CourseField::create("courses") - table Students does not have any column courses because the relations is organized via 3rd table student_courses - it generate sql error Column not found: 1054 Unknown column 'students.courses' in 'field list'

  2. the following generate error that method text is not exist

->value("course_id")
->text("course_name")

I changed it like this but I cannot be sureis it correct or not coz control does not appear

->fields(function () {
    return [
        Number::create('course_id'),
        Text::create('course_name')
    ];

})
  1. If I set $this->autoColName = false; in CourseField and don't use any clolumn name in CourseField::create() I get the error that Call undefined showOnCreate() method....

If I delete all that showOn methods maximum what I got is the column CourseField at the list screen - just array value and absolutely nothing in the Create and Update screens.

I really do not know where to go now.

KoolReport commented on Nov 14

Yeah, you are right. Let me a little time consulting with dev.team to find solution.

Build Your Excellent Data Report

Let KoolReport help you to make great reports. It's free & open-source released under MIT license.

Download KoolReport View demo
help needed

Dashboard