How to execute a scheduled function in Laravel, manually?

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company
# How to Execute Scheduled Functions in Laravel Manually: A Developer's Guide It’s very common when starting with Laravel or any framework to feel lost when you try to bridge the gap between automated scheduling and manual, on-demand execution. You are essentially asking how to take logic that is set up for a recurring event (like a scheduled task) and force it to run immediately, either through an Artisan command, a database seeder, or a simple web request. This guide will walk you through the best architectural patterns in Laravel to solve this problem effectively, moving away from putting complex logic directly inside the `schedule()` method. ## The Core Principle: Decoupling Scheduling from Execution The initial setup you described—placing all your API calls and database storage directly within `$schedule->call(function () { ... })`—is functional but violates a core principle of good software design: **Separation of Concerns**. When you tightly couple the scheduler definition with the actual business logic, it becomes difficult to test, reuse, or execute that logic outside of the scheduled context. The best practice in Laravel is to decouple these concerns by using **Jobs** and **Artisan Commands**. ### 1. Using Laravel Jobs for Scheduled Tasks Instead of putting your entire workflow inside `schedule()`, you should create a dedicated Job class for that specific task. This allows the scheduler to simply queue the job, and the job itself handles the execution. ```php // app/Jobs/ProcessExternalApiData.php namespace App\Jobs; use Illuminate\Support\Facades\Http; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; class ProcessExternalApiData implements ShouldQueue { use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; public function handle() { // All your complex logic (API calls, DB storage) lives here. $response = Http::get('some-external-api'); // ... process $response and save data } } ``` Now, your `schedule` method becomes clean: ```php // app/Console/Kernel.php protected function schedule(Schedule $schedule) { $schedule->job(new ProcessExternalApiData)->dailyAt('07:00'); } ``` ## 2. Executing Tasks Manually via Artisan Commands If you want to run *any* piece of logic "now," the most structured way in Laravel is through an **Artisan Command**. This turns your complex function into a reusable command that can be called from the terminal or within other parts of your application. To execute the logic from your example manually, create a custom command: ```bash php artisan make:command RunApiTask ``` Then, place your execution logic inside the `handle()` method of this new command. This is the perfect way to run the exact same logic that the scheduler runs, but on demand. ```php // app/Console/Commands/RunApiTask.php namespace App\Console\Commands; use Illuminate\Console\Command; use App\Jobs\ProcessExternalApiData; // Import your job class RunApiTask extends Command { protected $signature = 'task:run-now'; // The command name public function handle() { // Manually dispatch the Job. This executes the exact same logic // that the scheduler would run, but immediately. ProcessExternalApiData::dispatch(); $this->info('Scheduled task executed successfully via Artisan command.'); } } ``` To execute this manually, you simply run: ```bash php artisan task:run-now ``` This provides a clean, executable entry point for any scheduled logic. For more advanced scenarios involving database interactions or Eloquent models, understanding how to interact with the service layer defined in **Laravel** is key. ## 3. Running Logic from Seeders vs. Jobs You asked about running tasks via a seeder. While you *could* repeat the code inside a seeder, this generally leads to bloated and hard-to-maintain seeding files. Seeding should focus on populating initial state or creating test data. If your goal is to run business logic that involves external services (like API calls), it should be handled by **Jobs**, not seeders. Seeders are for setup; Jobs are for processing work. If you need a seeder to trigger a process, the seeder should simply dispatch the necessary Job: ```php // DatabaseSeeder.php public function run() { $this->call(ProcessExternalApiData::class); // Dispatch the job immediately during seeding } ``` ## Conclusion: The Architectural Path Forward To summarize, stop trying to force execution logic into your schedule definition. Follow this architectural path for maximum flexibility: 1. **Isolate Logic:** Move all complex API calls and database operations into dedicated **Job** classes. 2. **Define Actions:** Create an **Artisan Command** as a manual entry point to trigger these jobs on demand. 3. **Schedule:** Use the standard `schedule()` method only to queue those Jobs at specific times. By adopting this pattern, you ensure that your system remains clean, testable, and scalable. For deeper dives into structuring complex application flows, exploring resources like **Laravel** documentation will provide the necessary foundation for building robust systems.