PHP code example of andydefer / laravel-task

1. Go to this page and download the library: Download andydefer/laravel-task library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

andydefer / laravel-task example snippets


use AndyDefer\Directive\DirectiveKernel;

$kernel = DirectiveKernel::init($app);
$kernel->addSource('/path/to/directives');

// Exécution d'une directive
$exitCode = $kernel->run(['directive', 'tasks:process']);

use AndyDefer\Task\Contracts\Services\UniqueTaskServiceInterface;
use AndyDefer\Task\Contracts\Services\RecurringTaskServiceInterface;
use AndyDefer\Task\Records\UniqueTaskConfigRecord;
use AndyDefer\Task\Records\RecurringTaskConfigRecord;

class MyService
{
    public function __construct(
        private readonly UniqueTaskServiceInterface $uniqueService,
        private readonly RecurringTaskServiceInterface $recurringService
    ) {}
}



namespace App\Tasks;

use AndyDefer\Task\Abstract\AbstractUniqueTask;
use AndyDefer\Task\ValueObjects\DescriptionVO;
use AndyDefer\DomainStructures\Utils\StrictDataObject;

class SendWelcomeEmailTask extends AbstractUniqueTask
{
    // ✅ Hook exécuté avant process() - idéal pour la validation
    protected function before(StrictDataObject $payload): void
    {
        if (!$payload->has('email')) {
            throw new \InvalidArgumentException('Email is ook exécuté après process() - idéal pour la notification
    protected function after(bool $success, ?DescriptionVO $error = null): void
    {
        if ($success) {
            $this->info(new DescriptionVO('Task completed successfully'));
        } else {
            $this->error(new DescriptionVO("Task failed: {$error->getValue()}"));
            // Envoyer une alerte, logger, etc.
        }
    }
}



namespace App\Http\Controllers;

use AndyDefer\Task\Contracts\Services\UniqueTaskServiceInterface;
use AndyDefer\Task\Records\UniqueTaskConfigRecord;
use AndyDefer\Task\ValueObjects\UniqueTaskFqcnVO;
use AndyDefer\DomainStructures\Utils\StrictDataObject;
use AndyDefer\Task\ValueObjects\Iso8601DateTimeVO;
use AndyDefer\Task\ValueObjects\MaxAttemptsVO;
use AndyDefer\Task\ValueObjects\DurationVO;

class UserController extends Controller
{
    public function __construct(
        private readonly UniqueTaskServiceInterface $taskService
    ) {}

    public function store(Request $request)
    {
        // Création de l'utilisateur...
        
        // ✅ Enregistrement de la tâche avec UniqueTaskConfigRecord
        $config = UniqueTaskConfigRecord::from([
            'scheduled_at' => new Iso8601DateTimeVO(now()->addMinutes(5)),
            'max_attempts' => new MaxAttemptsVO(3),
            'grace_period' => new DurationVO(3600), // 1h
        ]);

        $payload = StrictDataObject::from([
            'email' => $request->email,
            'name' => $request->name,
        ]);

        $alias = $this->taskService->register(
            new UniqueTaskFqcnVO(SendWelcomeEmailTask::class),
            $payload,
            $config
        );

        return response()->json([
            'message' => 'Email planifié dans 5 minutes',
            'task_alias' => $alias->getValue(),
        ]);
    }
}



namespace App\Tasks;

use AndyDefer\Task\Abstract\AbstractRecurringTask;
use AndyDefer\Task\ValueObjects\DescriptionVO;

class CleanExpiredCacheTask extends AbstractRecurringTask
{
    protected function process(): void
    {
        $this->info(new DescriptionVO('Starting cache cleanup...'));
        
        // ✅ Ici votre code métier exécuté à chaque intervalle
        // Cache::cleanExpired();
        
        $this->info(new DescriptionVO('Cache cleaned successfully'));
    }

    protected function after(bool $success, ?DescriptionVO $error = null): void
    {
        if (!$success) {
            $this->error(new DescriptionVO("Cleanup failed: {$error->getValue()}"));
            // ✅ Alerter l'équipe, envoyer un email, etc.
        }
    }
}



namespace App\Console\Commands;

use AndyDefer\Task\Contracts\Services\RecurringTaskServiceInterface;
use AndyDefer\Task\Records\RecurringTaskConfigRecord;
use AndyDefer\Task\ValueObjects\RecurringTaskFqcnVO;
use AndyDefer\DomainStructures\Utils\StrictDataObject;
use AndyDefer\Task\ValueObjects\DurationVO;
use AndyDefer\Task\ValueObjects\Iso8601DateTimeVO;
use AndyDefer\Task\ValueObjects\MaxFailedAttemptsVO;

class SetupTasksCommand extends Command
{
    public function __construct(
        private readonly RecurringTaskServiceInterface $taskService
    ) {
        parent::__construct();
    }

    public function handle()
    {
        // ✅ Nettoyage toutes les heures, pendant 30 jours
        $config = RecurringTaskConfigRecord::from([
            'interval_seconds' => new DurationVO(3600), // Toutes les heures
            'start_at' => new Iso8601DateTimeVO(now()->toIso8601String()),
            'end_at' => new Iso8601DateTimeVO(now()->addDays(30)->toIso8601String()),
            'max_attempts' => new MaxFailedAttemptsVO(3),
        ]);

        $alias = $this->taskService->register(
            new RecurringTaskFqcnVO(CleanExpiredCacheTask::class),
            StrictDataObject::from(['enabled' => true]),
            $config
        );

        $this->info("Task registered: {$alias->getValue()}");
    }
}



use AndyDefer\Directive\DirectiveKernel;
use AndyDefer\Directive\Enums\ExitCode;

$kernel = DirectiveKernel::init($app);

// Par signature complète
$exitCode = $kernel->runSignature('tasks:process 50 --unique-only --verbose');

// Par FQCN
$exitCode = $kernel->runDirective(
    'AndyDefer\Task\Directives\TasksProcessDirective',
    ['50', '--unique-only']
);

// Par arguments bruts (comme en ligne de commande)
$exitCode = $kernel->run(['directive', 'tasks:process', '50', '--unique-only']);



$kernel = DirectiveKernel::init($app);

// Définir des données dans le contexte
$context = $kernel->getContext();
$context->put('user_id', 12345);
$context->put('batch_id', 'batch-abc-123');

// Exécuter une directive qui utilise le contexte
$kernel->run(['directive', 'process:user']);

// Récupérer les résultats du contexte
$result = $context->get('process_result');



namespace App\Services;

use AndyDefer\Task\Contracts\Services\UniqueTaskServiceInterface;
use AndyDefer\Task\Contracts\Services\RecurringTaskServiceInterface;
use AndyDefer\Task\ValueObjects\TaskAliasVO;
use AndyDefer\Task\ValueObjects\DurationVO;
use AndyDefer\Task\ValueObjects\DescriptionVO;
use AndyDefer\Task\ValueObjects\Iso8601DateTimeVO;
use AndyDefer\Task\ValueObjects\LimitVO;

class TaskManager
{
    public function __construct(
        private readonly UniqueTaskServiceInterface $uniqueService,
        private readonly RecurringTaskServiceInterface $recurringService
    ) {}

    // === TÂCHES UNIQUES ===

    // ✅ Annuler une tâche unique
    public function cancelUnique(string $alias): void
    {
        $this->uniqueService->cancel(
            new TaskAliasVO($alias),
            new DescriptionVO('Canceled by admin')
        );
    }

    // ✅ Reprogrammer à une autre date
    public function reschedule(string $alias, Iso8601DateTimeVO $newDate): void
    {
        $this->uniqueService->reschedule(
            new TaskAliasVO($alias),
            $newDate
        );
    }

    // ✅ Prolonger la période de grâce
    public function extendGracePeriod(string $alias, DurationVO $extraSeconds): void
    {
        $this->uniqueService->extendGracePeriod(
            new TaskAliasVO($alias),
            $extraSeconds
        );
    }

    // ✅ Exécuter une tâche unique manuellement
    public function runUnique(string $alias): TaskRunResultRecord
    {
        return $this->uniqueService->run(new TaskAliasVO($alias));
    }

    // === TÂCHES RÉCURRENTES ===

    // ✅ Mettre en pause
    public function pause(string $alias): void
    {
        $this->recurringService->pause(new TaskAliasVO($alias));
    }

    // ✅ Reprendre
    public function resume(string $alias): void
    {
        $this->recurringService->resume(new TaskAliasVO($alias));
    }

    // ✅ Changer l'intervalle
    public function changeInterval(string $alias, DurationVO $interval): void
    {
        $this->recurringService->changeInterval(
            new TaskAliasVO($alias),
            $interval
        );
    }

    // ✅ Terminer définitivement
    public function finish(string $alias): void
    {
        $this->recurringService->finish(new TaskAliasVO($alias));
    }

    // ✅ Prolonger la date de fin
    public function extendEndAt(string $alias, Iso8601DateTimeVO $newEndAt): void
    {
        $this->recurringService->extendEndAt(
            new TaskAliasVO($alias),
            $newEndAt
        );
    }

    // === INSPECTION ===

    // ✅ Récupérer une tâche
    public function findUnique(string $alias): ?UniqueTaskRecord
    {
        return $this->uniqueService->find(new TaskAliasVO($alias));
    }

    public function findRecurring(string $alias): ?RecurringTaskRecord
    {
        return $this->recurringService->find(new TaskAliasVO($alias));
    }

    // ✅ Compter les tâches
    public function getStats(): array
    {
        return [
            'unique_pending' => $this->uniqueService->countPending()->getValue(),
            'unique_completed' => $this->uniqueService->countCompleted()->getValue(),
            'unique_failed' => $this->uniqueService->countFailed()->getValue(),
            'unique_canceled' => $this->uniqueService->countCanceled()->getValue(),
            'recurring_waiting' => $this->recurringService->countWaiting()->getValue(),
            'recurring_playing' => $this->recurringService->countPlaying()->getValue(),
            'recurring_paused' => $this->recurringService->countPaused()->getValue(),
            'recurring_finished' => $this->recurringService->countFinished()->getValue(),
            'recurring_canceled' => $this->recurringService->countCanceled()->getValue(),
        ];
    }
}



namespace App\Services;

use AndyDefer\Task\Contracts\Services\UniqueTaskServiceInterface;
use AndyDefer\Task\Records\UniqueTaskConfigRecord;
use AndyDefer\Task\ValueObjects\UniqueTaskFqcnVO;
use AndyDefer\Task\ValueObjects\Iso8601DateTimeVO;
use AndyDefer\Task\ValueObjects\MaxAttemptsVO;
use AndyDefer\Task\ValueObjects\DurationVO;
use AndyDefer\DomainStructures\Utils\StrictDataObject;

class SubscriptionService
{
    public function __construct(
        private readonly UniqueTaskServiceInterface $taskService
    ) {}

    public function createSubscription(User $user, Plan $plan): void
    {
        // ✅ Rappel J-1 avant expiration
        $this->taskService->register(
            new UniqueTaskFqcnVO(RenewalReminderTask::class),
            StrictDataObject::from([
                'user_id' => $user->id,
                'email' => $user->email,
                'plan' => $plan->name,
            ]),
            UniqueTaskConfigRecord::from([
                'scheduled_at' => new Iso8601DateTimeVO($user->subscription_end_at->subDay()),
                'max_attempts' => new MaxAttemptsVO(2),
                'grace_period' => new DurationVO(3600),
            ])
        );

        // ✅ Désactivation à la date d'expiration
        $this->taskService->register(
            new UniqueTaskFqcnVO(ExpireSubscriptionTask::class),
            StrictDataObject::from([
                'user_id' => $user->id,
            ]),
            UniqueTaskConfigRecord::from([
                'scheduled_at' => new Iso8601DateTimeVO($user->subscription_end_at),
                'max_attempts' => new MaxAttemptsVO(3),
                'grace_period' => new DurationVO(7200),
            ])
        );

        // ✅ Relance en cas de paiement échoué
        $this->taskService->register(
            new UniqueTaskFqcnVO(PaymentRetryTask::class),
            StrictDataObject::from([
                'user_id' => $user->id,
                'payment_id' => $payment->id,
            ]),
            UniqueTaskConfigRecord::from([
                'scheduled_at' => new Iso8601DateTimeVO(now()->addHours(24)),
                'max_attempts' => new MaxAttemptsVO(3),
                'grace_period' => new DurationVO(86400),
            ])
        );
    }
}



namespace App\Services;

use AndyDefer\Task\Contracts\Services\UniqueTaskServiceInterface;
use AndyDefer\Task\Records\UniqueTaskConfigRecord;
use AndyDefer\Task\ValueObjects\UniqueTaskFqcnVO;
use AndyDefer\Task\ValueObjects\Iso8601DateTimeVO;
use AndyDefer\Task\ValueObjects\MaxAttemptsVO;
use AndyDefer\Task\ValueObjects\DurationVO;
use AndyDefer\DomainStructures\Utils\StrictDataObject;

class AbandonedCartService
{
    public function __construct(
        private readonly UniqueTaskServiceInterface $uniqueService
    ) {}

    public function handleAbandonedCart(Cart $cart, User $user): void
    {
        // ✅ Email de relance 30 min après abandon
        $this->uniqueService->register(
            new UniqueTaskFqcnVO(AbandonedCartReminderTask::class),
            StrictDataObject::from([
                'cart_id' => $cart->id,
                'user_id' => $user->id,
                'items' => $cart->items,
            ]),
            UniqueTaskConfigRecord::from([
                'scheduled_at' => new Iso8601DateTimeVO(now()->addMinutes(30)),
                'max_attempts' => new MaxAttemptsVO(2),
                'grace_period' => new DurationVO(3600),
            ])
        );

        // ✅ Email de suivi J+3
        $this->uniqueService->register(
            new UniqueTaskFqcnVO(FollowUpEmailTask::class),
            StrictDataObject::from([
                'user_id' => $user->id,
                'cart_id' => $cart->id,
            ]),
            UniqueTaskConfigRecord::from([
                'scheduled_at' => new Iso8601DateTimeVO(now()->addDays(3)),
                'max_attempts' => new MaxAttemptsVO(2),
                'grace_period' => new DurationVO(3600),
            ])
        );
    }
}



namespace App\Services;

use AndyDefer\Task\Contracts\Services\UniqueTaskServiceInterface;
use AndyDefer\Task\Records\UniqueTaskConfigRecord;
use AndyDefer\Task\ValueObjects\UniqueTaskFqcnVO;
use AndyDefer\Task\ValueObjects\Iso8601DateTimeVO;
use AndyDefer\Task\ValueObjects\MaxAttemptsVO;
use AndyDefer\Task\ValueObjects\DurationVO;

class WebhookService
{
    public function __construct(
        private readonly UniqueTaskServiceInterface $uniqueService
    ) {}

    public function sendWebhook($event, $data): string
    {
        // ✅ Appel API avec retry automatique
        $config = UniqueTaskConfigRecord::from([
            'scheduled_at' => new Iso8601DateTimeVO(now()->addSeconds(5)),
            'max_attempts' => new MaxAttemptsVO(5),
            'grace_period' => new DurationVO(7200), // 2h
        ]);

        $alias = $this->uniqueService->register(
            new UniqueTaskFqcnVO(SendWebhookTask::class),
            StrictDataObject::from([
                'url' => config('webhooks.endpoint'),
                'event' => $event,
                'data' => $data,
            ]),
            $config
        );

        return $alias->getValue();
    }
}



namespace App\Services;

use AndyDefer\Task\Contracts\Services\RecurringTaskServiceInterface;
use AndyDefer\Task\Contracts\Services\UniqueTaskServiceInterface;
use AndyDefer\Task\Records\RecurringTaskConfigRecord;
use AndyDefer\Task\Records\UniqueTaskConfigRecord;
use AndyDefer\Task\ValueObjects\RecurringTaskFqcnVO;
use AndyDefer\Task\ValueObjects\UniqueTaskFqcnVO;
use AndyDefer\Task\ValueObjects\DurationVO;
use AndyDefer\Task\ValueObjects\Iso8601DateTimeVO;
use AndyDefer\Task\ValueObjects\MaxFailedAttemptsVO;
use AndyDefer\Task\ValueObjects\MaxAttemptsVO;

class MaintenanceService
{
    public function __construct(
        private readonly RecurringTaskServiceInterface $recurringService,
        private readonly UniqueTaskServiceInterface $uniqueService
    ) {}

    public function scheduleMaintenance(): void
    {
        // ✅ Nettoyage toutes les heures
        $this->recurringService->register(
            new RecurringTaskFqcnVO(CacheCleanTask::class),
            StrictDataObject::from(['enabled' => true]),
            RecurringTaskConfigRecord::from([
                'interval_seconds' => new DurationVO(3600),
                'start_at' => new Iso8601DateTimeVO(now()->toIso8601String()),
                'max_attempts' => new MaxFailedAttemptsVO(3),
            ])
        );

        // ✅ Backup DB à 2h du matin
        $this->uniqueService->register(
            new UniqueTaskFqcnVO(BackupDatabaseTask::class),
            StrictDataObject::from([
                'database' => config('database.connections.mysql.database'),
                'backup_path' => storage_path('backups'),
            ]),
            UniqueTaskConfigRecord::from([
                'scheduled_at' => new Iso8601DateTimeVO(Carbon::now()->setTime(2, 0)),
                'max_attempts' => new MaxAttemptsVO(1),
                'grace_period' => new DurationVO(3600),
            ])
        );
    }
}



namespace App\Services;

use AndyDefer\Task\Contracts\Services\UniqueTaskServiceInterface;
use AndyDefer\Task\Records\UniqueTaskConfigRecord;
use AndyDefer\Task\ValueObjects\UniqueTaskFqcnVO;
use AndyDefer\Task\ValueObjects\Iso8601DateTimeVO;
use AndyDefer\Task\ValueObjects\MaxAttemptsVO;
use AndyDefer\Task\ValueObjects\DurationVO;

class OrderWorkflowService
{
    public function __construct(
        private readonly UniqueTaskServiceInterface $uniqueService
    ) {}

    public function processOrder(Order $order): void
    {
        $payload = StrictDataObject::from([
            'order_id' => $order->id,
            'user_id' => $order->user_id,
            'total' => $order->total,
        ]);

        $steps = [
            ValidateOrderTask::class => now()->addSeconds(10),
            ProcessPaymentTask::class => now()->addSeconds(30),
            GenerateInvoiceTask::class => now()->addMinutes(1),
            SendConfirmationTask::class => now()->addMinutes(2),
        ];

        foreach ($steps as $class => $scheduledAt) {
            $this->uniqueService->register(
                new UniqueTaskFqcnVO($class),
                $payload,
                UniqueTaskConfigRecord::from([
                    'scheduled_at' => new Iso8601DateTimeVO($scheduledAt),
                    'max_attempts' => new MaxAttemptsVO(2),
                    'grace_period' => new DurationVO(3600),
                ])
            );
        }
    }
}



namespace App\Services;

use AndyDefer\Task\Contracts\Services\RecurringTaskServiceInterface;
use AndyDefer\Task\Records\RecurringTaskConfigRecord;
use AndyDefer\Task\ValueObjects\RecurringTaskFqcnVO;
use AndyDefer\Task\ValueObjects\DurationVO;
use AndyDefer\Task\ValueObjects\Iso8601DateTimeVO;
use AndyDefer\Task\ValueObjects\MaxFailedAttemptsVO;

class CampaignService
{
    public function __construct(
        private readonly RecurringTaskServiceInterface $recurringService
    ) {}

    public function startCampaign(Campaign $campaign): void
    {
        // ✅ Newsletter hebdomadaire sur 4 semaines
        $this->recurringService->register(
            new RecurringTaskFqcnVO(NewsletterTask::class),
            StrictDataObject::from([
                'campaign_id' => $campaign->id,
                'template' => $campaign->template,
            ]),
            RecurringTaskConfigRecord::from([
                'interval_seconds' => new DurationVO(604800), // 7 jours
                'start_at' => new Iso8601DateTimeVO(now()->toIso8601String()),
                'end_at' => new Iso8601DateTimeVO(now()->addWeeks(4)->toIso8601String()),
                'max_attempts' => new MaxFailedAttemptsVO(2),
            ])
        );
    }
}

// BON
class UserController
{
    public function __construct(
        private readonly UniqueTaskServiceInterface $taskService
    ) {}
}

// BON
new Iso8601DateTimeVO(now()->addMinutes(5))

// ÉVITER
$config['scheduled_at'] = now()->addMinutes(5);

$payload = StrictDataObject::from([
    'user_id' => $user->id,
    'email' => $user->email,
    'metadata' => [
        'source' => 'registration',
        'timestamp' => now()->toIso8601String(),
    ],
]);
bash
composer  vendor:publish --tag=task-migrations
php artisan migrate