unwanted column changing when updating table with Laravel Eloquent

60 Views Asked by At

I have a cronjob in Laravel scheduled to update some info in a table once a day. That job just call a function and that function try to update the table. What is happening is that when the information is updated, the column request_at is updated with the same info as updated_at, but only the columns updated_at and status_id should be changed

Here's my model, the migration and the function called by the cronjob

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;

class StockRecharge extends Model
{
    use SoftDeletes;

    protected $fillable = [
        'worker_stock_id',
        'status_id',
        'requested_at'
    ];

    protected $casts = [
        'worker_stock_id' => 'integer',
        'status_id' => 'integer',
        'requested_at' => 'datetime'
    ];

    /**
     * Return the related status 
     * @return HasOne
     */
    public function status(): HasOne
    {
        return $this->hasOne(Status::class);
    }

    /**
     * Return the related worker stock
     * @return BelongsTo
     */
    public function workerStock(): BelongsTo
    {
        return $this->belongsTo(WorkerStock::class);
    }
}

migration

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateStockRecharges extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('stock_recharges', function (Blueprint $table) {
            $table->id();
            $table->foreignId('worker_stock_id')->constrained('worker_stocks')->cascadeOnDelete()->cascadeOnUpdate();
            $table->tinyInteger('status_id', false, true);
            $table->timestampTz('requested_at');
            $table->timestampsTz();
            $table->softDeletesTz();

            $table->foreign('status_id')->references('id')->on('statuses')->cascadeOnDelete()->cascadeOnUpdate();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('stock_recharges');
    }
}

cronjob

private static function updateStockRechargeToExpiring(): bool
    {
        Log::info('starting updateStockRechargeToExpiring()');

        try {
            StockRecharge::whereNull('deleted_at')
                ->where('status_id', StatusRepository::getByName('ACTIVE'))
                ->whereRaw('DATEDIFF(CURDATE(), requested_at) = 4')
                ->update(['status_id' => StatusRepository::getByName('EXPIRING')]);
        } catch (\Throwable) {
            Log::error('status update failed on updateStockRechargeToExpiring()');
            return false;
        }

        Log::info('job updateStockRechargeToExpiring() finished successfully');

        return true;
    }

I've used the the function DB::enableQueryLog() to see exactly what was the query and got the following:

array:2 [
  0 => array:3 [
    "query" => "select `id` from `statuses` where (`name` = ?)"
    "bindings" => array:1 [
      0 => "EXPIRING"
    ]
    "time" => 4.92
  ]
  1 => array:3 [
    "query" => "update `stock_recharges` set `status_id` = ?, `updated_at` = ? where `deleted_at` is null and DATEDIFF(CURDATE(), requested_at) = 4"
    "bindings" => array:2 [
      0 => 3
      1 => "2024-03-19 12:27:32"
    ]
    "time" => 0.76
  ]
]

As we can see, there's no mention of request_at in the query, but it is changed anyway.

I've tried using DB::table('stock_recharges') instead of the model StockRecharge, but the result was the same

Laravel 9.52 MySQL 8.0.31

Has anyone faced something like it before?

1

There are 1 best solutions below

3
Amin Elhan On

Try

->whereRaw('DATEDIFF(CURDATE(), requested_at)', '=', '4')

I think it is a conflict because you defined requesed_at while you are searching with whereRaw