Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Totem Laravel Package

studio/laravel-totem

Laravel Totem provides a Horizon-style dashboard to manage Laravel Scheduler jobs. Create, enable/disable, and edit scheduled Artisan commands without changing code. Includes migrations/assets, auth customization, and supports Laravel 11/12 on PHP 8.2+.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Steps to First Use
1. **Installation**
   ```bash
   composer require always-open/laravel-totem:^13.0
   php artisan migrate
   php artisan totem:assets
  • Verify the config/totem.php file exists (published automatically).
  • Note: Requires Laravel 13.x, PHP 8.3+, and drops support for Laravel 10/11 and PHP 8.2.
  1. Define a Scheduled Command In app/Console/Kernel.php, register a command in the schedule() method:

    protected function schedule(Schedule $schedule)
    {
        $schedule->command('emails:send')->dailyAt('10:00');
    }
    
    • Run php artisan schedule:list to confirm the command is registered.
  2. Access the Dashboard Visit /totem (or your configured route) to see the UI. The dashboard will auto-detect all scheduled commands.


First Use Case: Enabling/Disabling Jobs

  • Toggle a job: Navigate to the dashboard, locate your command (e.g., emails:send), and use the slider to enable/disable it without editing code.
  • Immediate Execution: Use the "Run Now" button to trigger the command manually from the UI.

Implementation Patterns

Core Workflows

1. Command Management

  • Registering Commands: Ensure commands are defined in Kernel.php's schedule() method. Totem mirrors Laravel’s scheduler but adds a UI layer.

    $schedule->command(new SendEmailsCommand())->hourly();
    
    • Tip: Use dependency-injected commands for flexibility (e.g., pass queues, environments).
  • Grouping Commands: Organize commands in the UI by prefixing them with a namespace or using tags (via ->name()):

    $schedule->command('analytics:process')->name('Analytics')->daily();
    

2. Environment-Specific Scheduling

  • Use Laravel’s environment detection (config('app.env')) to conditionally schedule jobs:
    if (app()->environment('production')) {
        $schedule->command('backups:run')->weekly();
    }
    
    • Totem respects these conditions but hides disabled jobs in the UI (unless forced via config).

3. Event-Based Scheduling

Schedule commands to run after events (e.g., scheduled:run):

$schedule->command('cleanup:logs')->after(function () {
    return now()->startOfDay();
});
  • Note: Event-based schedules appear in Totem but may require manual triggers in the UI.

4. Queue Integration

Offload commands to queues by default:

$schedule->command('process:invoices')->onOneServer()->withoutOverlapping();
  • Totem shows queue status (e.g., "Pending" or "Running") in the dashboard.

Integration Tips

Customizing the Dashboard

  • Extend Views: Publish and override Totem’s Blade templates:

    php artisan vendor:publish --tag=totem-views
    
    • Modify resources/views/vendor/totem/... to add custom fields (e.g., job priority).
  • Add Metadata: Attach custom data to commands via ->name() or extend the Totem\Jobs\Job model:

    $schedule->command('deploy:staging')->name('Deploy [Staging]')->description('Deploys to staging environment');
    

API Access

  • Use Totem’s API endpoints to manage jobs programmatically:
    // Enable a job via API
    $response = Http::post('/api/totem/jobs/enable', ['command' => 'emails:send']);
    
    • Tip: Protect routes with middleware (e.g., auth:sanctum).

Logging and Monitoring

  • Log Entries: Totem logs job executions to jobs table. Query via:
    use Totem\Jobs\Job;
    $job = Job::where('command', 'emails:send')->latest()->first();
    
  • Custom Logs: Extend the Job model to log additional context:
    protected static function booted()
    {
        static::created(function ($job) {
            \Log::info("Totem job triggered: {$job->command}", $job->attributes);
        });
    }
    

Testing

  • Mock the Scheduler: In tests, use Schedule::fake() and assert job triggers:
    $schedule = $this->app->make(Schedule::class);
    $schedule->fake();
    $schedule->command('test:job')->shouldBeRun();
    
  • UI Tests: Test dashboard interactions with Laravel Dusk or Pest:
    $this->visit('/totem')
         ->see('emails:send')
         ->press('Run Now')
         ->see('Job executed successfully');
    

Gotchas and Tips

Pitfalls

  1. Cron Configuration Mismatch

    • Issue: Totem enables/disables jobs via the UI, but the system cron must still run schedule:run periodically.
    • Fix: Ensure your server’s cron has:
      * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1
      
    • Tip: Use config('totem.cron_expression') to customize the cron schedule in Totem’s config.
  2. Overlapping Jobs

    • Issue: Commands with withoutOverlapping() may fail silently if the previous run isn’t marked as finished.
    • Fix: Ensure your command exits properly and logs completion:
      public function handle()
      {
          try {
              // Job logic
              \Log::info("Job completed: " . now());
          } catch (\Throwable $e) {
              \Log::error("Job failed: " . $e->getMessage());
              throw $e;
          }
      }
      
  3. Permission Issues

    • Issue: UI buttons (e.g., "Run Now") may fail with 403 if middleware isn’t configured.
    • Fix: Add middleware to routes/totem.php:
      Route::middleware(['auth', 'verified'])->group(function () {
          // Totem routes
      });
      
  4. Timezone Confusion

    • Issue: Scheduled times may not match expectations due to timezone mismatches.
    • Fix: Set config('app.timezone') and ensure Totem’s config respects it:
      'timezone' => env('APP_TIMEZONE', 'UTC'),
      
  5. Database Locking

    • Issue: Frequent job toggles can cause database contention.
    • Fix: Use DB::transaction() for bulk operations in custom Totem extensions.

Debugging

  1. Job Not Appearing in UI?

    • Verify the command is registered in Kernel.php.
    • Check php artisan schedule:list for typos or missing schedules.
    • Clear cached schedules:
      php artisan schedule:clear-cache
      
  2. UI Assets Not Loading

    • Run php artisan totem:assets and check public/vendor/totem/ for files.
    • Clear Laravel cache:
      php artisan cache:clear
      php artisan view:clear
      
  3. Logs Missing

    • Ensure config/totem.php has 'log_enabled' => true.
    • Check storage/logs/laravel.log for Totem-related entries.

Extension Points

  1. Custom Job Fields Extend the Job model to add columns (e.g., priority, owner):

    php artisan make:migration add_priority_to_jobs_table --table=jobs
    
    • Update the model:
      protected $fillable = ['command', 'enabled', 'priority'];
      
  2. Webhook Triggers Add a webhook endpoint to trigger jobs via HTTP:

    Route::post('/totem/webhook/run', function (Request $request) {
        $job = Totem\Jobs\Job::where('command', $request->command)->first();
        if ($job) {
            $job->runManually();
            return response()->json(['status' => 'success']);
        }
        return response()->json(['error' => 'Job not found'], 404);
    });
    
  3. Slack/Teams Notifications Integrate with Totem’s job events to send alerts:

    use Totem\Events\JobExecuted;
    
    Event::listen(JobExecuted::class, function ($event) {
        if ($event->job->failed()) {
            // Send Slack notification
        }
    });
    
  4. Bulk Actions Add a bulk toggle feature via a custom controller:

    public
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium