Installation
composer require akeneo/batch
Add the service provider to config/app.php:
'providers' => [
// ...
Akeneo\Batch\JobRunner\JobRunnerServiceProvider::class,
],
Define a Job
Create a job class extending Akeneo\Batch\Job\JobInterface:
namespace App\Jobs;
use Akeneo\Batch\Job\JobInterface;
use Akeneo\Batch\Step\StepExecution;
use Akeneo\Batch\Step\StepInterface;
class MyJob implements JobInterface
{
public function getName(): string
{
return 'my_job';
}
public function run(StepExecution $stepExecution): void
{
// Job logic here
}
}
Register the Job
Define the job in config/batch.php:
'jobs' => [
'my_job' => [
'class' => \App\Jobs\MyJob::class,
'steps' => [
// Define steps here (see Implementation Patterns)
],
],
],
Run the Job
Use the JobRunner facade:
use Akeneo\Batch\JobRunner\JobRunner;
$jobRunner = app(JobRunner::class);
$jobRunner->run('my_job');
Check Documentation Focus on:
Job Definition
Jobs are the top-level unit of work. Define them in config/batch.php with:
JobInterface.3 (configurable per job).100 (configurable per step).'jobs' => [
'import_products' => [
'class' => \App\Jobs\ImportProductsJob::class,
'steps' => [
'read' => [
'class' => \App\Steps\ReadFromCsvStep::class,
'reader' => 'csv_reader',
],
'process' => [
'class' => \App\Steps\ProcessProductStep::class,
],
'write' => [
'class' => \App\Steps\WriteToDatabaseStep::class,
'writer' => 'database_writer',
],
],
],
],
Step Patterns Steps are the building blocks of a job. Common patterns:
class ReadFromCsvStep implements StepInterface
{
public function run(StepExecution $stepExecution): void
{
$reader = $this->getReader($stepExecution);
while ($reader->hasNext()) {
$data = $reader->next();
$stepExecution->addReadData($data);
}
}
}
class ProcessProductStep implements StepInterface
{
public function run(StepExecution $stepExecution): void
{
$chunk = $stepExecution->getReadData();
foreach ($chunk as $item) {
$processed = $this->transform($item);
$stepExecution->addProcessedData($processed);
}
}
}
class WriteToDatabaseStep implements StepInterface
{
public function run(StepExecution $stepExecution): void
{
$chunk = $stepExecution->getProcessedData();
foreach ($chunk as $item) {
$this->saveToDatabase($item);
}
}
}
Chunking
Use StepExecution::getReadData() and StepExecution::getProcessedData() to work with chunks of data. Example:
public function run(StepExecution $stepExecution): void
{
$chunk = $stepExecution->getReadData();
foreach ($chunk as $item) {
// Process item
}
$stepExecution->setProcessedData($processedItems);
}
Job Listeners Attach listeners to jobs or steps for logging, validation, or side effects:
'jobs' => [
'my_job' => [
'class' => \App\Jobs\MyJob::class,
'listeners' => [
'before' => \App\Listeners\LogJobStart::class,
'after' => \App\Listeners\SendNotification::class,
],
],
],
Job Parameters Pass parameters to jobs dynamically:
$jobRunner->run('my_job', ['file_path' => '/path/to/file.csv']);
Access parameters in the job:
$filePath = $this->getParameter('file_path');
Job Dependencies Define dependencies between jobs (e.g., run Job B only after Job A succeeds):
'jobs' => [
'job_a' => ['class' => \App\Jobs\JobA::class],
'job_b' => [
'class' => \App\Jobs\JobB::class,
'depends_on' => ['job_a'],
],
],
Job Scheduling Use Laravel’s scheduler to run jobs periodically:
$schedule->job(new \App\Jobs\DailyImportJob())->daily();
Or via the JobRunner:
$jobRunner->run('daily_import_job');
State Management
StepExecution state (e.g., getReadData(), getProcessedData()) is not automatically persisted between retries. If a job fails and retries, you must ensure data is reprocessed or re-fetched.JobRepository (e.g., Akeneo\Batch\Job\JobRepository\DoctrineJobRepository) to persist job state. Configure it in config/batch.php:
'job_repository' => [
'class' => \Akeneo\Batch\Job\JobRepository\DoctrineJobRepository::class,
'entity_manager' => 'default',
],
Chunk Size Mismatch
chunk_size, the job may fail or behave unexpectedly.next() method respects the chunk size. Example:
$chunk = [];
while ($reader->hasNext() && count($chunk) < $stepExecution->getChunkSize()) {
$chunk[] = $reader->next();
}
$stepExecution->addReadData($chunk);
Circular Dependencies
depends_on in a way that creates circular dependencies (e.g., Job A depends on Job B, which depends on Job A) will cause the job runner to throw an exception.Listener Order
before listeners run in reverse order).before_validate, before_log).Transaction Management
Akeneo\Batch\Step\TransactionStep to wrap steps in transactions:
'steps' => [
'write' => [
'class' => \Akeneo\Batch\Step\TransactionStep::class,
'step' => [
'class' => \App\Steps\WriteToDatabaseStep::class,
],
],
],
Reader/Writer Configuration
reader and writer keys in step configuration to pass them in:
'steps' => [
'read' => [
'class' => \App\Steps\ReadFromCsvStep::class,
How can I help you explore Laravel packages today?