diff --git a/src/Illuminate/Bus/PendingBatch.php b/src/Illuminate/Bus/PendingBatch.php index 56297bc80e0d..ba130fcefd1d 100644 --- a/src/Illuminate/Bus/PendingBatch.php +++ b/src/Illuminate/Bus/PendingBatch.php @@ -10,6 +10,7 @@ use Illuminate\Support\Collection; use Illuminate\Support\Traits\Conditionable; use Laravel\SerializableClosure\SerializableClosure; +use RuntimeException; use Throwable; use function Illuminate\Support\enum_value; @@ -56,7 +57,10 @@ class PendingBatch public function __construct(Container $container, Collection $jobs) { $this->container = $container; - $this->jobs = $jobs; + + $this->jobs = $jobs->each(function (object|array $job) { + $this->ensureJobIsBatchable($job); + }); } /** @@ -70,12 +74,35 @@ public function add($jobs) $jobs = is_iterable($jobs) ? $jobs : Arr::wrap($jobs); foreach ($jobs as $job) { + $this->ensureJobIsBatchable($job); + $this->jobs->push($job); } return $this; } + /** + * Ensure the given job is batchable. + * + * @param object|array $job + * @return void + */ + protected function ensureJobIsBatchable(object|array $job): void + { + foreach (Arr::wrap($job) as $job) { + if ($job instanceof PendingBatch) { + $this->ensureJobIsBatchable($job->jobs->all()); + + return; + } + + if (! in_array(Batchable::class, class_uses_recursive($job))) { + throw new RuntimeException(sprintf('Attempted to batch job [%s], but it does not use the Batchable trait.', $job::class)); + } + } + } + /** * Add a callback to be executed when the batch is stored. * diff --git a/tests/Bus/BusPendingBatchTest.php b/tests/Bus/BusPendingBatchTest.php index d5b9bd8d9ea7..d0398da85e69 100644 --- a/tests/Bus/BusPendingBatchTest.php +++ b/tests/Bus/BusPendingBatchTest.php @@ -222,4 +222,13 @@ public function test_batch_before_event_is_called() $this->assertTrue($beforeCalled); } + + public function test_it_throws_exception_if_batched_job_is_not_batchable(): void + { + $nonBatchableJob = new class {}; + + $this->expectException(RuntimeException::class); + + new PendingBatch(new Container, new Collection([$nonBatchableJob])); + } }