Home > Mobile >  Laravel Relations Should I use hasManyThrough or belongsToMany? Nesting 3 Tables
Laravel Relations Should I use hasManyThrough or belongsToMany? Nesting 3 Tables

Time:11-18

I asked this question before, but formatted it way different and incorrectly. The deal is, I have 4 tables of which I would like to nest.

I want Measurement containing measurement_data which contains measurement_fields which contains measurement_type (only showing important fields).

So far, I have everything but MeasurementFields inside of Measurement Data.

My tables:

measurements
 - id
 - client_id (not really important now)

measurement_data
 - id
 - measurement_id
 - measurement_field_id

measurement_fields
 - id
 - type_id

measurement_types
 - id
 - name

I have tried hasManyThrough and belongsToMany but I can't get either of them to work. This is what I have in my Models now :

Measurement Model

    protected $fillable = [
        'client_id',
    ];
    public $timestamps = false;

    public function clients() {
        return $this->belongsTo(Client::class, 'client_id');
    }

    public function measurement_datas() {
        return $this->hasMany(MeasurementData::class);
    }
    
    public function measurement_fields() {
        return $this->belongsToMany(MeasurementField::class, 'measurement_fields', 'measurement_id', 'measurement_field_id')
        ->withPivot([
            'type_id',
            'name',
            'enabled',
        ]);
    }

MeasurementData Model

    protected $fillable = [
        'measurement_id',
        'measurement_field_id',
        'data',
    ];

    public function measurement() {
        return $this->belongsTo(Measurements::class, 'measurement_id'); 
    }

MeasurementField Model

    protected $table = 'measurement_fields';

    protected $fillable = [
        'type_id',
        'name',
        'enabled',
    ];
    public $timestamps = false;


    public function measurement_type() {
        return $this->belongsTo(MeasurementType::class, 'type_id');
    }

MeasurementType Model

    protected $table = 'measurement_types';

    protected $fillable = [
        'name',
    ];

    public function measurement_field() {
        return $this->hasMany(MeasurementField::class); 
    }

My Controller MeasurementController

    public function index()
    {
        return JsonResource::collection(Measurement::with(['clients', 'measurement_datas', 'measurement_fields'])->get());
    }

I would appreciate any help, because I've been stuck on this for a while now. Thank you :)

CodePudding user response:

Ok, firstly, your MeasurementData@measurement method is using Measurements when it should be Measurement (singular - to match the class name).

Secondly, the table you reference in a belongsToMany should be the pivot table and not the table of the relationship you want. The withPivot won't work/be needed as those fields are not part of the pivot table. Also, you only need to define the column names for the relationship if the don't follow Laravel's naming convention. This is what your measurement_fields method can look like:

public function measurement_fields()
{
    return $this->belongsToMany(MeasurementField::class, 'measurement_data');
}

Alternatively, you could set up a relationship between MeasurementData and MeasurementField (if you haven't done so already) and then use nested eager loading. Add the following to your MeasurementData model:

public function measurement_field()
{
    return $this->belongsTo(MeasurementField::class);
}

Then you can load the information using:

Measurement::with(['clients', 'measurement_datas.measurement_field.measurement_type', 'measurement_fields'])
  • Related