简体   繁体   中英

Laravel Multiple Belongs and Relationship - Eloquent

I have 4 interconnected classes/tables. I summarised the tables for what matters

+--------------------+
| SelectionProcesses | 
+--------------------+
| id                 | 
| name               | 
+--------------------+
+-------------------------+
| StudentSelectionProcess | 
+-------------------------+
| id                      | 
| inscribed_student_id    | << Important
| selection_process_id    | << Important
| status                  | 
+-------------------------+
+------------------+
| InscribedStudent | 
+------------------+
| id               |
| student_id       |  << Important            
+------------------+
+---------+
| Student | 
+---------+
| id      | 
| name    | 
+---------+

So when I filter a selectionProcess I want get the student related by [StudentSelectionProcess -> InscribedStudent -> Student ]

I'm currently getting it, but I wanted to remove an object, my JSON:

{
    "id": 3,
    "name": "Test example name to Selection process.",
    "enrolleds": [
        {
            "id": 6,
            "inscribed_student_id": 1,
            "selection_process_id": 3,
            "status": "Approved"
            "student": {
                "id": 1,
                "student_id": 1,
                "student": {
                    "id": 1,
                    "name": "Mrs. Myrtice Robel",
                }
            }
        }
    ]
}

What I need:

{
    "id": 3,
    "name": "Test example name to Selection process.",
    "enrolleds": [
        {
            "id": 6,
            "inscribed_student_id": 1,
            "selection_process_id": 3,
            "status": "Approved"
            "student": {
                "id": 1,
                "name": "Mrs. Myrtice Robel",
            }
        }
    ]
}

My code

// SelectionProcess.php
    public function enrolleds()
    {
        return $this->hasMany('App\StudentSelectionProcess');
    }

    public function scopeHasEnrolleds($query)
    {
        $query->with(['enrolleds' => function($enrolledQuery) {
            $enrolledQuery->has('student')->with('student');
        }]);
    }

// StudentSelectionProcess.php
    public function student()
    {
        return $this->belongsTo('App\InscribedStudent', 'inscribed_student_id')->with('student');
    }

// InscribedStudent.php
    public function student()
    {
        return $this->hasOne('App\Student', 'id', 'student_id');        
    }

The data has been summarized, so I can't modify the model, I know there are ways to make it work, just couldn't find it yet.

If it's just modifying the resulting json, look into Eloquent Resources.

You can hide unwanted data using that before sending to output.

ie.

StudentResource » individual data

StudentCollection » multiple student data

Another solution is to change your model relationship.

Since you seem to be using intermediate tables to connect related data. Follow the documentation and apply it on your model so you can directly get the Student object without those unnecessary fields from the intermediate table.

Also, you can use both to further improve the output according to your needs.

You could make use of Eloquent Has Many Deep package to add a shortcut function in order to access the student s of a SelectionProcess . You can go through its documentation to know more about how it works.

I think this setup should work:

class StudentSelectionProcess extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function enrolleds()
    {
        return $this->hasManyDeep(
            'App\InscribedStudent',
            ['App\StudentSelectionProcess'], 
            [
               'selection_process_id', // FK on the "student_selection_processes"(-ish) table.
               'id',    // FK on the "inscribed_students"(-ish) table (local key).
            ],
            [
               'id', // PK on the "student_selection_processes"(-ish) table.
               'inscribed_student_id',    // FK of the "inscribed_students"(-ish) table.
            ]
        )->with('student'); // or with('student.student'), one of them should work.
    }
}

Then you could just do:

public function myCoolFunction()
{
    $selectionProcess = SelectionProcess::with('enrolleds')->find(3);

    return $selectionProcess;
}

Expected output:

 { "id": 3, "name": "Test example name to Selection process.", "enrolleds": [ { "id": 6, "inscribed_student_id": 1, "selection_process_id": 3, "status": "Approved" "student": { "id": 1, "name": "Mrs. Myrtice Robel", } } ] } 

  • PS1: I'm not overriding your relationships, it's just another function.

  • PS2: given that I don't have that set up to test it first, it's possible that I have a typo somewhere or messed up a key/foreign-key, but you can figure it out easily with the help package documentation.

SelectionProcessController.php Controller

public function showCurrent($id)
{
    $process = SelectionProcess::hasEnrolleds()->get();
    return $process;
}

SelectionProcess.php Model

/**
 * This function return all enrolleds in selection process
 * 
 * @return Array StudentSelectionProcess
 */
public function enrolleds()
{
    return $this->hasMany('App\StudentSelectionProcess');
}

/**
 * This function get the enrolleds only has the student 
 * 
 * @return Validation
 */
public function scopeHasEnrolleds($query)
{
    $query->with(['enrolleds' => function($enrolledQuery) {
        $enrolledQuery->has('student')->with('student');
    }]);
}

StudentSelectionProcess.php Model

/**
 * This function return the student thought by inscribedStudent
 * 
 * @return Array Student
 */
public function student()
{
    return $this->hasOneThrough(
        'App\Student', // Get the student
        'App\InscribedStudent', // Through by inscribed student
        'id', 
        'id', 
        'inscribed_student_id',
        'student_id' 
    );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM