Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

aliaboussebaba's avatar

Prevent logging personal information in Horizon job payload

Hey Laravel folks,

I'm using Laravel Horizon, but when serializing models, it serialize everything including sensitive data like hashed password, tokens and so on. And it shows all these details in the dashboard. The SerializesModels trait help to serialize only the model ID, then the queue system will automatically re-retrieve the full model instance, but I'm in a situation where I want to track the User update state and check which columns are updated, so it needs to be serialized.

Is there any way or a workaround to hide/fake the sensitive data before serialization?

0 likes
3 replies
LaryAI's avatar
Level 58

Certainly! To prevent logging personal information in Laravel Horizon job payloads, you can customize the serialization process by overriding the toArray or toJson method in your model. This way, you can specify exactly which attributes should be included in the serialization process.

Here's an example of how you can override the toArray method in your User model to exclude sensitive information:

class User extends Authenticatable
{
    use Notifiable, SerializesModels;

    // ...

    /**
     * Convert the model instance to an array.
     *
     * @return array
     */
    public function toArray()
    {
        // Get the original array representation of the model
        $array = parent::toArray();

        // Remove sensitive data
        unset($array['password']);
        unset($array['remember_token']);

        // You can also unset other sensitive attributes if needed
        // unset($array['other_sensitive_attribute']);

        return $array;
    }
}

By doing this, when the model is serialized for the job payload, the sensitive information will not be included.

Additionally, if you want to track which columns are updated without serializing the entire model, you can pass only the changed attributes to the job. Here's an example of how you might dispatch a job with only the changed attributes:

$user->fill($newAttributes);

if ($user->isDirty()) {
    // Get the changed attributes
    $changedAttributes = $user->getDirty();

    // Dispatch the job with the changed attributes
    UpdateUserJob::dispatch($user->id, $changedAttributes);
}

In your job class, you would then handle the changed attributes:

class UpdateUserJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $userId;
    protected $changedAttributes;

    /**
     * Create a new job instance.
     *
     * @param  int   $userId
     * @param  array $changedAttributes
     * @return void
     */
    public function __construct($userId, array $changedAttributes)
    {
        $this->userId = $userId;
        $this->changedAttributes = $changedAttributes;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        // Retrieve the user by ID
        $user = User::findOrFail($this->userId);

        // Update the user with the changed attributes
        $user->update($this->changedAttributes);
    }
}

This way, you're only passing the necessary information to the job, and you're not serializing any sensitive data. Remember to handle the serialization of the $changedAttributes carefully if it contains any sensitive data.

1 like
convenia's avatar

You can add the ShouldBeEncrypted at the job definition. This will hide the entire job data into a single encrypted hash

1 like
kevinbui's avatar

@convenia solution is gonna work.

There's also a secret feature. You can achieve the same result by setting a shouldBeEncrypted property to true in any job. Try this:

// In a job
protected bool $shouldBeEncrypted = true;

In addition, you can pass the model object and the updates, which are fields you want to track later, to the job.

Please or to participate in this conversation.