GridView with relational data through a junction table

Hello,

I have 3 tables, let’s say: student, course and coursestudent, the last is a junction table. So a student could participate on many courses and a course can be attended by multiple students.

I need to show multiple attributes from the course in the student view page, using a GridView and in a row per course fashion. For example, if I go to the view page of student John Doe I need to display every course that he’s participating in, using attributes from the course table:

John Doe’s view page




Course Name | Starting Date | Hours -> attributes from the class table

course1       xx-xx-xxx       80

course2       xx-xx-xxx       75  -> every row is a class where studentX is enrolled



I do not need sorting and searching for this view, also I removed the serial and action parts of the GridView.

So far I was able to get the needed data on the Grid, but is displayed like an array in one row, instead of a row per value.

This is what I have done:




    <?php

        $query = Student::find()

            ->joinWith('courseperstudents')

            ->where(['courseperstudent.course_id' => $model->id_student])

        ;

        $dataProvider = new ActiveDataProvider([

            'query' => $query,

            'pagination' => false,

    ]) ?>



And in the widget:




     <?= GridView::widget([

        'dataProvider' => $dataProvider,

        //'summary' => '',

        'columns' => [

            [

                'label' => 'Course',

                'value' => function($model) {

                    return join(', ', yii\helpers\ArrayHelper::map($model->courseperstudents, 'id_courseperstudent', 'course.course_name'));

                    },

            ],

//other columns needed using the same logic

...],

]); ?>



You can treat the course as the main model, not the student.




    <?php

        $query = Course::find()

            ->joinWith('courseperstudent')

            ->where(['courseperstudent.student_id' => $model->id_student])

        ;

        ...

    ]) ?>






     <?= GridView::widget([

        'dataProvider' => $dataProvider,

        'columns' => [

            'course_name',

            // other attributes of the course

        ],

      ]); ?>



Neat!, works as expected. Thank you very much softark.

If I’m allowed, I would like to make a question related to this topic.

In a 4th column in the GridView I need to put related data to the course table but this time in an array way (like I’ve achieved first), but with data that is in a table 3 relations away from course, what would be the best way to achieve that?

Is best to use this method:




        'columns' => [

            [

                'label' => 'Course',

                'value' => function($model) {

                    return join(', ', yii\helpers\ArrayHelper::map($model->courseperstudents, 'id_courseperstudent', 'course.course_name'));

                    },

            ],



Or work with another dataprovider that obtains the data that I need?

Thank you.

Sorry, but I don’t understand what you are trying to show.

Would you please elaborate it in details with the involved tables and their relations?

I’m sorry, my explanation was very poor. For the sake of simplicity in my first question I didn’t use the real models and used basic examples.

In this image is the model being used (I put the equivalents to the given example in the 1st question):

Model

And what I need to show in the GridView:

View

I hope with that it gets clearer, if it’s confusing I’ll gladly open another thread and request this as solved. Thanks!

Edit: It seems that photobucket links are not working properly.

I see. So, these are the relations:




Programa has many Spraying via SprayingxPrograma

Spraying has one Receta

Receta has many Dosis via DosisxReceta



I would write an utility method in Receta model to enumerate the related Dosises:




public function getAllDosisesText()

{

    $items = [];

    foreach($this->dosises as $dosis) {

        $items[] = $dosis->insumo->...

    }

    return implode(',', $items);

}



And in the GridView in which the main model is Spraying:




    'columns' => [

        [

            'label' => 'Dosis',

            'value' => function($model) {

                return $model->receta->getAllDosisesText();

            },

        ],



Thank you softark, yesterday I ended up doing this:

In the Dosis model I made this function to concatenate the name of the Insumo and the amount of it




    public function getfullDosis()

    {

        return $this->insumo->nombre_insumo.'-'.$this->cantidad.'-'.$this->insumo->um;

    } 



And in the view page:




            [

                'label' => 'Dosis',

                'value' => function($model){

                    return join(' , ', yii\helpers\ArrayHelper::map($model->receta->dosisxrecetas, 'id_dosisxreceta', 'dosis.fulldosis'));

                },

            ],



The view displayed the data as requested, like this:

http://imgur.com/HYeyFVO