Home > Software engineering >  Eloquent - Update eloquent relations with foreach loop
Eloquent - Update eloquent relations with foreach loop

Time:03-31

I have a controller function to send multiple devices for repair (essentially an update request against multiple existing devices_repairs records). When I try to retrieve the devices from the devices table alongside the repair details (Devices table, devices_repairs table), the records are retrieved but when I try to update the values the update request doesn't save the new data.

This is my controller function:

<?php
    public function sendMultiDevicesForRepair(sendDeviceForRepairRequest $request) {
        $request->validated();

       $device_barcodes = ["BSC0626", "BSC0376"];
       $devices = Devices::with('repairDetails')->whereIn('barcode',$device_barcodes)->get();

            DB::transaction(function () use (&$devices) {
               foreach($devices as $device) {
                    $device->repairDetails->repair_date_sent_for = request('repair_date_sent_for');
                    $device->repairDetails->job_number = request('jobNumber'.$device->barcode);
                    $device->repairDetails->operator_date_sent = Carbon::now()->toDateTimeString();
                    $device->repairDetails->operator_sent_by = getCreatedUpdatedBy();
                } 
            });

            $devices->push();

            // perform a redirect if the transaction is successful
            return redirect('/devices/repair')
                ->with('success', 'The devices: '  . request('deviceBarcodes') . ' have been sent for repair.');
    }
?>

When I do (dd($devices)) after changing the repair details in the loop, the attributes array has the new values, but again push() will not update the database even though no error is returned:

Illuminate\Database\Eloquent\Collection {#1439 ▼
  #items: array:2 [▼
    0 => App\Devices {#1446 ▼
       timestamps: false
      #table: "devices"
      #primaryKey: "device_id"
      
      #relations: array:1 [▼
        "repairDetails" => App\DevicesRepairs {#1451 ▼
          #table: "devices_repairs"
          #primaryKey: "device_id"
          #attributes: array:15 [▼
            "device_id" => "54"
            "repair_damaged_by" => "157"
            "repair_damage_type" => "Screen Damage"
            "repair_date_received" => "2020-02-26"
            "repair_date_sent_for" => "2022-03-31"
            "repair_damage_notes" => "Cracked Screen - due to age not worth repairing"
            "repairer_name" => null
            "repair_is_user_damage" => "1"
            "job_number" => "1000.5312.9745"
            "operator_date_received" => "2020-02-26 00:00:00"
            "operator_received_by" => "56"
            "operator_date_sent" => "2022-03-31 16:30:11"
            "operator_sent_by" => "41"
            "photo_id" => null
            "photo_id_back" => null
          ]
          #original: array:15 [▼
            "device_id" => "54"
            "repair_damaged_by" => "157"
            "repair_damage_type" => "Screen Damage"
            "repair_date_received" => "2020-02-26"
            "repair_date_sent_for" => null
            "repair_damage_notes" => "Cracked Screen - due to age not worth repairing"
            "repairer_name" => null
            "repair_is_user_damage" => "1"
            "job_number" => null
            "operator_date_received" => "2020-02-26 00:00:00"
            "operator_received_by" => "56"
            "operator_date_sent" => null
            "operator_sent_by" => null
            "photo_id" => null
            "photo_id_back" => null
          ]
          #changes: []

Here are my models. Devices Model:

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');
    }
}

DevicesRepairs model:

<?php

namespace App;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class DevicesRepairs extends Model
{
    use HasFactory;
    protected $table = 'devices_repairs';
    protected $primaryKey = 'device_id';
    public $timestamps = false;

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

What am I doing wrong? I had this working with separate DB::Table update queries but I much prefer to use eloquent.

CodePudding user response:

you need to push data inside your foreach loop

Instead of

DB::transaction(function () use (&$devices) {
               foreach($devices as $device) {
                    $device->repairDetails->repair_date_sent_for = request('repair_date_sent_for');
                    $device->repairDetails->job_number = request('jobNumber'.$device->barcode);
                    $device->repairDetails->operator_date_sent = Carbon::now()->toDateTimeString();
                    $device->repairDetails->operator_sent_by = getCreatedUpdatedBy();
                } 
            });

            $devices->push();

Use this

DB::transaction(function () use (&$devices) {
                   foreach($devices as $device) {
                        $device->repairDetails->repair_date_sent_for = request('repair_date_sent_for');
                        $device->repairDetails->job_number = request('jobNumber'.$device->barcode);
                        $device->repairDetails->operator_date_sent = Carbon::now()->toDateTimeString();
                        $device->repairDetails->operator_sent_by = getCreatedUpdatedBy();
                        $device->push(); // save data here
                    } 
                });
    
                
  • Related