Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Laravel Eloquent – relation of relation – three model relationship

I am trying to convert the below DB query to an eloquent relation.

$device_barcodes = ["BSC0337", "BSC0503", "BSC0626"];
$devices = DB::table('devices')
       ->leftjoin('devices_repairs', 'devices_repairs.device_id', '=', 'devices.device_id')
       ->leftJoin('staff','staff.staff_id','devices_repairs.repair_damaged_by')
       ->whereIn('barcode', $device_barcodes)
       ->get();

So far I have the below, but I am struggling with the staff relation.

$devices = Devices::with('repairDetails')->whereIn('barcode', $device_barcodes)->get();

I’ve overcome this for now with the below, but this is not ideal.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

foreach($devices as $device) {
           $staff_name = Staff::find($device->repairDetails->repair_damaged_by);
           $device->staff_name = $staff_name->staff_name;
 }

I am hoping for something like:

$devices = Devices::with('repairDetails')->with('staffDetails')->whereIn('barcode', $device_barcodes)->get();

This way I can show the device details, the repair details and the staff name on my blade form.

So the basic issue is I am trying to relate three models together.

Devices is the top model, where I join with DevicesRepairs using the device_id primary and foreign keys. But for the Staff model I need to join devices_repairs.repair_damaged by to staff.staff_id.

Here are my models:
Devices:

class Devices extends Model
{
    /**
     * @var bool $timestamps Disable timestamps
     */
    public $timestamps = false;
    /**
     * @var string $table Name of the db table
     */
    protected $table = 'devices';
    /**
     * @var string $primaryKey Name of the primary key
     */
    protected $primaryKey = 'device_id';
    /**
     * @var array $fillable The attributes that are mass assignable.
     */
    protected $fillable = [
        'status',
        'order_reference',
        'model',
        'serial',
        'imei',
        'barcode',
        'mobile_number',
        'helpdesk_url_id',
        'device_notes'
    ];

    use Searchable;

    function repairDetails() {
        return $this->hasOne(DevicesRepairs::class, 'device_id');
    }

    function repairHistoryDetails() {
        return $this->hasOne(DevicesRepairsHistory::class, 'device_id');
    }

}

DevicesRepairs:

class DevicesRepairs extends Model
{
    use HasFactory;
    protected $table = 'devices_repairs';
    protected $primaryKey = 'device_id';
    public $timestamps = false;
    protected $fillable = [
        'device_id',
        'repair_damanged_by',
        'repair_damage_type',
        'repair_date_received',
        'repair_date_sent_for',
        'repair_damage_notes',
        'repairer_name',
        'repair_is_user_damage',
        'job_number',
        'operator_date_received',
        'operator_date_received_by',
        'operator_date_sent',
        'operator_sent_by',
        'photo_id',
        'photo_id_back'
    ];

    function device() {
        return $this->hasOne(Devices::class, 'device_id');
    }

    //This doesn't work - seems to return a random staff member.
    function staffDetails() {
        return $this->hasOne(Staff::class,'staff_id','repair_damaged_by');
    }  
}

Staff:

class Staff extends Model
{
    use searchable;

    /**
     * @var bool $timestamps Disable timestamps
     */
    public $timestamps = false;
    /**
     * @var string $table Name of the db table
     */
    protected $table = 'staff';
    /**
     * @var string $primaryKey Name of the primary key
     */
    protected $primaryKey = 'staff_id';
    /**
     * @var array $fillable The attributes that are mass assignable.
     */

    protected $fillable = [
        'staff_id',
        'staff_name',
        'manager_id',
        'is_active',
        'is_mdm_user',
        'user_id',
    ];
}

My ultimate aim is to be able to return fields like this in my view:

{{$device->barcode}}
{{$device->repairDetails->repair_damage_notes}}

//The above work fine but not this:
{{$device->staffDetails->staff_name}}

>Solution :

treat at as a pivot table, a many to many relation between devices and staff

class Devices extends Model
{
    public function damagedBy()
    {
        return $this->belongsToMany(Staff::class, 'devices_repairs', 'device_id', 'repair_damaged_by');
    }

So the query will be like

$device_barcodes = ["BSC0337", "BSC0503", "BSC0626"];
$devices = Devices::with('damagedBy')->whereIn('barcode', $device_barcodes)->get();
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading