Back to examples

PHP Examples

Complete, copy-paste examples for every supported PHP queue backend. Each example includes initialization, job processing, in-job logging, and graceful shutdown.

1. Laravel Queues

Zero config — set JOBVIZ_API_KEY in your .env and the service provider auto-discovers. All queue connections are monitored automatically.

Requires PHP 8.1+, Laravel 10+
Install composer require jobviz/agent
Events captured All lifecycle events
app/Jobs/SendWelcomeEmail.php
// .env
// JOBVIZ_API_KEY=your-api-key

// That's it! The Laravel service provider auto-discovers
// and starts monitoring all queue connections.

// app/Jobs/SendWelcomeEmail.php
namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Jobviz\Agent\Facades\Jobviz;

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

    public function __construct(
        public readonly string $email,
    ) {}

    public function handle(): void
    {
        // Structured logs appear in the Jobviz timeline
        Jobviz::log('Rendering template');
        $html = view('emails.welcome', ['email' => $this->email])->render();

        Jobviz::log('Sending email', ['to' => $this->email]);
        Mail::raw($html, fn ($m) => $m->to($this->email)->subject('Welcome!'));
    }
}

// Dispatch from anywhere
SendWelcomeEmail::dispatch('user@example.com');

// Track deployments (e.g. in a deploy script)
// Jobviz::trackDeployment(['version' => '1.2.0', 'commitHash' => 'abc123f']);

Tip: Publish the config with php artisan vendor:publish --tag=jobviz-config to customise queues, connection, and batching options.

2. Symfony Messenger

Register the SymfonyMessengerProvider as an event subscriber. It hooks into Messenger's dispatch and worker events automatically.

Requires PHP 8.1+, Symfony 6.0+
Install composer require jobviz/agent
Events captured active, completed, failed
src/MessageHandler/SendWelcomeEmailHandler.php
// config/services.yaml
// services:
//     Jobviz\Agent\Providers\SymfonyMessengerProvider:
//         arguments:
//             - '%env(JOBVIZ_API_KEY)%'
//         tags:
//             - { name: kernel.event_subscriber }

// src/Message/SendWelcomeEmail.php
namespace App\Message;

class SendWelcomeEmail
{
    public function __construct(
        public readonly string $email,
    ) {}
}

// src/MessageHandler/SendWelcomeEmailHandler.php
namespace App\MessageHandler;

use App\Message\SendWelcomeEmail;
use Jobviz\Agent\Facades\Jobviz;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;

#[AsMessageHandler]
class SendWelcomeEmailHandler
{
    public function __invoke(SendWelcomeEmail $message): void
    {
        Jobviz::log('Rendering template');
        $html = $this->twig->render('emails/welcome.html.twig', [
            'email' => $message->email,
        ]);

        Jobviz::log('Sending email', ['to' => $message->email]);
        $this->mailer->send($html, $message->email);
    }
}

// Dispatch from a controller
$bus->dispatch(new SendWelcomeEmail('user@example.com'));

3. Custom provider

Implement the QueueProviderInterface to integrate any PHP queue or task system. Three methods: connect(), disconnect(), and queues().

src/Queue/CronJobProvider.php
<?php

namespace App\Queue;

use Jobviz\Agent\Contracts\QueueProviderInterface;

// 1. Implement the QueueProviderInterface
class CronJobProvider implements QueueProviderInterface
{
    private \Closure $push;
    private array $timers = [];

    public function __construct(
        private readonly array $jobs, // [['name' => ..., 'handler' => ...]]
    ) {}

    public function connect(\Closure $push): void
    {
        $this->push = $push;

        foreach ($this->jobs as $job) {
            $this->timers[] = $this->schedule($job['cron'], function () use ($job) {
                $jobId = $job['name'] . '-' . time();

                ($this->push)([
                    'jobId'     => $jobId,
                    'jobName'   => $job['name'],
                    'queue'     => 'cron',
                    'event'     => 'active',
                    'timestamp' => now()->getTimestampMs(),
                ]);

                try {
                    $result = ($job['handler'])();
                    ($this->push)([
                        'jobId'     => $jobId,
                        'jobName'   => $job['name'],
                        'queue'     => 'cron',
                        'event'     => 'completed',
                        'timestamp' => now()->getTimestampMs(),
                        'data'      => ['returnValue' => $result],
                    ]);
                } catch (\Throwable $e) {
                    ($this->push)([
                        'jobId'     => $jobId,
                        'jobName'   => $job['name'],
                        'queue'     => 'cron',
                        'event'     => 'failed',
                        'timestamp' => now()->getTimestampMs(),
                        'data'      => [
                            'failedReason' => $e->getMessage(),
                            'stack'        => $e->getTraceAsString(),
                        ],
                    ]);
                }
            });
        }
    }

    public function disconnect(): void
    {
        foreach ($this->timers as $timer) {
            $timer->stop();
        }
        $this->timers = [];
    }

    public function queues(): array
    {
        return ['cron'];
    }
}

// 2. Use with Jobviz agent
use Jobviz\Agent\JobvizAgent;

$agent = new JobvizAgent(
    apiKey: $_ENV['JOBVIZ_API_KEY'],
    provider: new CronJobProvider([...]),
);
$agent->start();

Learn more: See the PHP SDK Guide for the full QueueProviderInterface contract and configuration reference.

4. MultiProvider

Combine built-in and custom PHP providers under a single agent. All events appear in the same Jobviz dashboard.

bootstrap/jobviz.php
<?php

use Jobviz\Agent\JobvizAgent;
use Jobviz\Agent\Providers\LaravelQueueProvider;
use Jobviz\Agent\Providers\MultiProvider;

// Monitor multiple queue backends in a single agent
$agent = new JobvizAgent(
    apiKey: config('jobviz.api_key'),
    provider: new MultiProvider([
        // Laravel Queues (Redis connection)
        new LaravelQueueProvider(
            queues: ['emails', 'reports'],
            connection: 'redis',
        ),
        // Your custom provider
        new CronJobProvider([
            ['name' => 'sync-analytics', 'cron' => '*/5 * * * *', 'handler' => fn () => syncAnalytics()],
            ['name' => 'cleanup-sessions', 'cron' => '0 * * * *', 'handler' => fn () => cleanupSessions()],
        ]),
    ]),
);

$agent->trackDeployment([
    'version'    => '2.0.0',
    'commitHash' => 'abc123f',
]);

$agent->start();

// Graceful shutdown
register_shutdown_function(fn () => $agent->stop());

Tip: You can mix LaravelQueueProvider, SymfonyMessengerProvider, and custom providers in the same MultiProvider.

Next steps

Ready to start monitoring?

Sign up for free and get your API key in seconds.

Get started free