i’m working inside a Laravel 10 application and am building a notification feature designed to notify users when significant columns on various models change. I’ve got a global model observer set up which contains these methods, when a model is updated I want to compare the original against the current.
My issue is that getAttributes()
isn’t casting my columns on my model, for example, my Buyer
model does indeed define a correct casts
property (we can see this from getOriginal() working)
How can I ensure the values are casted / compared correctly:
<?php
namespace AppObservers;
use IlluminateSupportFacadesLog;
use AppJobsProcessModelObserver;
use CarbonCarbon;
use Exception;
class GlobalModelObserver
{
/**
* Handle the User "created" event.
*/
public function created($model): void
{
try {
ProcessModelObserver::dispatch($model, $model->id, 'created', Carbon::now());
} catch (Exception $e) {
// ...
}
}
/**
* Handle the User "updated" event.
*/
public function updated($model): void
{
try {
$originalAttributes = $model->getOriginal();
$currentAttributes = $model->getAttributes();
$columnsToExclude = [
'id',
'description',
'is_favourited',
'last_used_at',
'updated_at',
'created_at',
'type',
'last_built_at',
'last_successful_build_at',
'last_failed_build_at',
'slug'
];
$originalAttrs = collect($model->getOriginal())->reject(function ($value, $key) use ($columnsToExclude) {
return in_array($key, $columnsToExclude);
})->sort()->all();
$currentAttrs = collect($model->getAttributes())->reject(function ($value, $key) use ($columnsToExclude) {
return in_array($key, $columnsToExclude);
})->sort()->all();
$numDifferences = count(collect($originalAttrs)->diffAssoc(collect($currentAttrs))->toArray());
// only dispatch if there are differences
if ($numDifferences > 0) {
ProcessModelObserver::dispatch($model, $model->id, 'updated', Carbon::now(), [
'model' => [
'original' => collect($originalAttrs)->toArray(),
'current' => collect($currentAttrs)->toArray()
]
]);
}
} catch (Exception $e) {
Log::debug("cannot send update notification", [
'e' => $e->getMessage(),
'f' => $e->getFile(),
'l' => $e->getLine()
]);
}
}
/**
* Handle the User "deleted" event.
*/
public function deleted($model): void
{
try {
ProcessModelObserver::dispatch($model, $model->id, 'deleted', Carbon::now());
} catch (Exception $e) {
// ...
}
}
/**
* Handle the User "force deleted" event.
*/
public function forceDeleted($model): void
{
try {
ProcessModelObserver::dispatch($model, $model->id, 'deleted', Carbon::now());
} catch (Exception $e) {
// ...
}
}
}
This code, outputs the following JSON:
{
"model":{
"original":{
"is_default":false,
"dedupe_is_enabled":false,
"dedupe_value":0,
"dedupe_accepts":false,
"deleted_at":null,
"user_id":1,
"company_id":1,
"product_id":1,
"name":"TUK",
"is_enabled":true,
"dedupe_period":"days"
},
"current":{
"is_default":0,
"dedupe_is_enabled":0,
"dedupe_value":0,
"dedupe_accepts":0,
"deleted_at":null,
"user_id":1,
"company_id":1,
"product_id":1,
"is_enabled":1,
"name":"TUK",
"dedupe_period":"days"
}
}
}
What do I need to change please?