Certainly! Let’s clarify how Inertia::optional works and what you can (and cannot) do with it.
How Inertia::optional Works
Inertia::optional is designed to conditionally load data for a prop, usually based on whether a request is an Inertia visit or not. The closure you provide is executed synchronously during the request/response cycle.
Regarding Jobs
Jobs in Laravel are typically queued and run asynchronously (in the background). You cannot start a job in the closure and "wait" for it to finish within the same HTTP request, because:
- PHP (and Laravel) does not support waiting for asynchronous jobs to finish in the same request.
- The closure must return a value immediately.
Solution
If you need to return data after a job is finished, you have two main options:
1. Run the Job Synchronously
If the job is not time-consuming, you can dispatch it synchronously (i.e., not queued):
use App\Jobs\MyJob;
return Inertia::render('Articles/Show', [
'details' => Inertia::optional(function () {
// Run the job synchronously
(new MyJob())->handle();
// Now fetch the data
return Model::find(1);
}),
]);
2. Check Job Status and Return Data When Ready
If the job is queued, you should not wait for it in the request. Instead:
- Trigger the job elsewhere (e.g., on a previous request).
- In the closure, check if the job is done (e.g., by checking a status column in the database).
- Return the data if available, or
null/a placeholder if not.
Example:
return Inertia::render('Articles/Show', [
'details' => Inertia::optional(function () {
$model = Model::find(1);
if ($model->job_status === 'finished') {
return $model->details;
}
// Job not finished yet
return null;
}),
]);
Then, on the frontend, you can poll or refresh until the data is available.
Summary:
You cannot "wait" for a queued job to finish inside an Inertia::optional closure. Either run the job synchronously, or check for job completion and return data when ready.
Let me know if you need a more specific example for your use case!