tool: search-docs

text:
# Search Results

## Queues Testing Faking a Subset of Jobs
Queues | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/queues.md

### Faking a Subset of Jobs

If you only need to fake specific jobs while allowing your other jobs to execute normally, you may pass the class names of the jobs that should be faked to the `fake` method:

```php tab=Pest
test('orders can be shipped', function () {
    Queue::fake([
        ShipOrder::class,
    ]);

    // Perform order shipping...

    // Assert a job was pushed twice...
    Queue::assertPushedTimes(ShipOrder::class, 2);
});
```

```php tab=PHPUnit
public function test_orders_can_be_shipped(): void
{
    Queue::fake([
        ShipOrder::class,
    ]);

    // Perform order shipping...

    // Assert a job was pushed twice...
    Queue::assertPushedTimes(ShipOrder::class, 2);
}
```

You may fake all jobs except for a set of specified jobs using the `except` method:

```php
Queue::fake()->except([
    ShipOrder::class,
]);
```

---

## Horizon Installation Job Backoff
Horizon | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/horizon.md

### Job Backoff

You can define the `backoff` value at the supervisor level to specify how long Horizon should wait before retrying a job that encounters an unhandled exception:

```php
'environments' => [
    'production' => [
        'supervisor-1' => [
            // ...
            'backoff' => 10,
        ],
    ],
],
```

You may also configure "exponential" backoffs by using an array for the `backoff` value. In this example, the retry delay will be 1 second for the first retry, 5 seconds for the second retry, 10 seconds for the third retry, and 10 seconds for every subsequent retry if there are more attempts remaining:

```php
'environments' => [
    'production' => [
        'supervisor-1' => [
            // ...
            'backoff' => [1, 5, 10],
        ],
    ],
],
```

---

## Components Modal > Modal
Components Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux

    Modal

Display content in a layer above the main page. Ideal for confirmations, alerts, and forms.

<flux:modal.trigger name="edit-profile">    <flux:button>Edit profile</flux:button></flux:modal.trigger><flux:modal name="edit-profile" class="md:w-96">

            <flux:heading size="lg">Update profile</flux:heading>            <flux:text class="mt-2">Make changes to your personal details.</flux:text>
        <flux:input label="Name" placeholder="Your name" />        <flux:input label="Date of birth" type="date" />
            <flux:spacer />            <flux:button type="submit" variant="primary">Save changes</flux:button>

</flux:modal>

---

## Validation Form objects
Validation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation

## Form objects

As more properties and validation rules are added to a Livewire component, it can begin to feel too crowded. To alleviate this pain and also provide a helpful abstraction for code reuse, you can use Livewire's *Form Objects* to store your properties and validation rules.

Below is the same `CreatePost` example, but now the properties and rules have been extracted to a dedicated form object named `PostForm`:

```php
<?php

namespace App\Livewire\Forms;

use Livewire\Attributes\Validate;
use Livewire\Form;

class PostForm extends Form
{
    #[Validate('required|min:3')]
	public $title = '';

    #[Validate('required|min:3')]
    public $content = '';
}
```

The `PostForm` above can now be defined as a property on the `CreatePost` component:

```php
<?php

namespace App\Livewire;

use App\Livewire\Forms\PostForm;
use Livewire\Component;
use App\Models\Post;

class CreatePost extends Component
{
    public PostForm $form;

    public function save()
    {
		Post::create(
    		$this->form->all()
    	);

		return redirect()->to('/posts');
    }

    // ...
}
```

As you can see, instead of listing out each property individually, we can retrieve all the property values using the `->all()` method on the form object.

Also, when referencing the property names in the template, you must prepend `form.` to each instance:

```blade
<form wire:submit="save">
	<input type="text" wire:model="form.title">
    <div>@error('form.title') {{ $message }} @enderror</div>

	<textarea wire:model="form.content"></textarea>
    <div>@error('form.content') {{ $message }} @enderror</div>

	<button type="submit">Save</button>
</form>
```

When using form objects, `#[Validate]` attribute validation will be run every time a property is updated. However, if you disable this behavior by specifying `onUpdate: false` on the attribute, you can manually run a form object's validation using `$this->form->validate()`:

```php
public function save()
{
    Post::create(
        $this->form->validate()
    );

    return redirect()->to('/posts');
}
```

Form objects are a useful abstraction for most larger datasets and a variety of additional features that make them even more powerful. For more information, check out the comprehensive [form object documentation](/docs/4.x/forms#extracting-a-form-object).

---

## Http Tests Validation Assertions assertInvalid
Http Tests | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/http-tests.md

#### assertInvalid

Assert that the response has validation errors for the given keys. This method may be used for asserting against responses where the validation errors are returned as a JSON structure or where the validation errors have been flashed to the session:

```php
$response->assertInvalid(['name', 'email']);
```

You may also assert that a given key has a particular validation error message. When doing so, you may provide the entire message or only a small portion of the message:

```php
$response->assertInvalid([
    'name' => 'The name field is required.',
    'email' => 'valid email address',
]);
```

---

## Components Badge > With close button
Components Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux

With close button

Make a badge removable by appending a close button.

<flux:badge>    Admin <flux:badge.close /></flux:badge>

---

## Components Badge > Rounded
Components Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux

Rounded

Display badges with a fully rounded border radius using the rounded prop.

<flux:badge rounded icon="user">Users</flux:badge>

---

## Validation See also
Validation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation

## See also

- **[Forms](/docs/4.x/forms)** — Validate form inputs with real-time feedback
- **[Properties](/docs/4.x/properties)** — Validate property values before persisting
- **[Validate Attribute](/docs/4.x/attribute-validate)** — Use #[Validate] for property validation
- **[Actions](/docs/4.x/actions)** — Validate data in action methods

---

## Telescope Available Watchers HTTP Client Watcher
Telescope | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/telescope.md

### HTTP Client Watcher

The HTTP client watcher records outgoing [HTTP client requests](/docs/{{version}}/http-client) made by your application.

---

## Scout Installation Queueing
Scout | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/scout.md

### Queueing

When using an engine that is not the `database` or `collection` engine, you should strongly consider configuring a [queue driver](/docs/{{version}}/queues) before using the library. Running a queue worker will allow Scout to queue all operations that sync your model information to your search indexes, providing much better response times for your application's web interface.

Once you have configured a queue driver, set the value of the `queue` option in your `config/scout.php` configuration file to `true`:

```php
'queue' => true,
```

Even when the `queue` option is set to `false`, it's important to remember that some Scout drivers like Algolia and Meilisearch always index records asynchronously. In other words, even though the index operation has completed within your Laravel application, the search engine itself may not reflect the new and updated records immediately.

To specify the connection and queue that your Scout jobs utilize, you may define the `queue` configuration option as an array:

```php
'queue' => [
    'connection' => 'redis',
    'queue' => 'scout'
],
```

Of course, if you customize the connection and queue that Scout jobs utilize, you should run a queue worker to process jobs on that connection and queue:

```shell
php artisan queue:work redis --queue=scout
```

---

## Understanding Nesting Performance implications
Understanding Nesting | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/understanding-nesting

## Performance implications

Livewire's independent component architecture can have both positive and negative implications for your application.

An advantage of this architecture is it allows you to isolate expensive portions of your application. For example, you can quarantine a slow database query to its own independent component, and its performance overhead won't impact the rest of the page.

However, the biggest drawback of this approach is that because components are entirely separate, inter-component communication/dependencies becomes more difficult.

For example, if you had a property passed down from the above parent `Posts` component to the nested `ShowPost` component, it wouldn't be "reactive". Because each component is independent, if a request to the parent component changed the value of the property being passed into `ShowPost`, it wouldn't update inside `ShowPost`.

Livewire has overcome a number of these hurdles and provides dedicated APIs for these scenarios like: [Reactive properties](/docs/4.x/nesting#reactive-props), [Modelable components](/docs/4.x/nesting#binding-to-child-data-using-wiremodel), and [the `$parent` object](/docs/4.x/nesting#directly-accessing-the-parent-from-the-child).

Armed with this knowledge of how nested Livewire components operate, you will be able to make more informed decisions about when and how to nest components within your application.

---

## Queues Dealing With Failed Jobs
Queues | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/queues.md

## Dealing With Failed Jobs

Sometimes your queued jobs will fail. Don't worry, things don't always go as planned! Laravel includes a convenient way to [specify the maximum number of times a job should be attempted](#max-job-attempts-and-timeout). After an asynchronous job has exceeded this number of attempts, it will be inserted into the `failed_jobs` database table. [Synchronously dispatched jobs](/docs/{{version}}/queues#synchronous-dispatching) that fail are not stored in this table and their exceptions are immediately handled by the application.

A migration to create the `failed_jobs` table is typically already present in new Laravel applications. However, if your application does not contain a migration for this table, you may use the `make:queue-failed-table` command to create the migration:

```shell
php artisan make:queue-failed-table

php artisan migrate
```

When running a [queue worker](#running-the-queue-worker) process, you may specify the maximum number of times a job should be attempted using the `--tries` switch on the `queue:work` command. If you do not specify a value for the `--tries` option, jobs will only be attempted once or as many times as specified by the job class' `$tries` property:

```shell
php artisan queue:work redis --tries=3
```

Using the `--backoff` option, you may specify how many seconds Laravel should wait before retrying a job that has encountered an exception. By default, a job is immediately released back onto the queue so that it may be attempted again:

```shell
php artisan queue:work redis --tries=3 --backoff=3
```

If you would like to configure how many seconds Laravel should wait before retrying a job that has encountered an exception on a per-job basis, you may do so by defining a `backoff` property on your job class:

```php
/**
 * The number of seconds to wait before retrying the job.
 *
 * @var int
 */
public $backoff = 3;
```

If you require more complex logic for determining the job's backoff time, you may define a `backoff` method on your job class:

```php
/**
 * Calculate the number of seconds to wait before retrying the job.
 */
public function backoff(): int
{
    return 3;
}
```

You may easily configure "exponential" backoffs by returning an array of backoff values from the `backoff` method. In this example, the retry delay will be 1 second for the first retry, 5 seconds for the second retry, 10 seconds for the third retry, and 10 seconds for every subsequent retry if there are more attempts remaining:

```php
/**
 * Calculate the number of seconds to wait before retrying the job.
 *
 * @return array<int, int>
 */
public function backoff(): array
{
    return [1, 5, 10];
}
```

---

## Validation Form Request Validation
Validation | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/validation.md

## Form Request Validation

---

## Components Badge > Badge
Components Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux

    Badge

Highlight information like status, category, or count.

<flux:badge color="lime">New</flux:badge>

---

## Http Client Testing Preventing Stray Requests
Http Client | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/http-client.md

### Preventing Stray Requests

If you would like to ensure that all requests sent via the HTTP client have been faked throughout your individual test or complete test suite, you can call the `preventStrayRequests` method. After calling this method, any requests that do not have a corresponding fake response will throw an exception rather than making the actual HTTP request:

```php
use Illuminate\Support\Facades\Http;

Http::preventStrayRequests();

Http::fake([
    'github.com/*' => Http::response('ok'),
]);

// An "ok" response is returned...
Http::get('https://github.com/laravel/framework');

// An exception is thrown...
Http::get('https://laravel.com');
```

Sometimes, you may wish to prevent most stray requests while still allowing specific requests to execute. To accomplish this, you may pass an array of URL patterns to the `allowStrayRequests` method. Any request matching one of the given patterns will be allowed, while all other requests will continue to throw an exception:

```php
use Illuminate\Support\Facades\Http;

Http::preventStrayRequests();

Http::allowStrayRequests([
    'http://127.0.0.1:5000/*',
]);

// This request is executed...
Http::get('http://127.0.0.1:5000/generate');

// An exception is thrown...
Http::get('https://laravel.com');
```

---

## Components Badge > As button
Components Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux

As button

Make the entire badge clickable by wrapping it in a button element.

<flux:badge as="button" rounded icon="plus" size="lg">Amount</flux:badge>

---

## Components Field > With badge
Components Field | livewire/flux@2.x | Source: https://fluxui.dev/components/field#livewire/flux

With badge

Badges allow you to enhance a field with additional information such as being "required" or "optional" when it might not be expected.

<flux:field>    <flux:label badge="Required">Email</flux:label>    <flux:input type="email" required />    <flux:error name="email" /></flux:field><flux:field>    <flux:label badge="Optional">Phone number</flux:label>    <flux:input type="phone" placeholder="(555) 555-5555" mask="(999) 999-9999"  />    <flux:error name="phone" /></flux:field>

---

## Forms See also
Forms | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/forms

## See also

- **[Validation](/docs/4.x/validation)** — Validate form inputs with real-time feedback
- **[wire:model](/docs/4.x/wire-model)** — Bind form inputs to component properties
- **[File Uploads](/docs/4.x/uploads)** — Handle file uploads in forms
- **[Actions](/docs/4.x/actions)** — Process form submissions with actions
- **[Loading States](/docs/4.x/loading-states)** — Show loading indicators during form submission

---

## Lifecycle Hooks Using hooks inside a form object
Lifecycle Hooks | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/lifecycle-hooks

## Using hooks inside a form object

Form objects in Livewire support property update hooks. These hooks work similarly to [component update hooks](#update), letting you perform actions when properties in the form object change.

Below is an example of a component using a `PostForm` form object:

```php
<?php // resources/views/components/post/⚡create.blade.php

use Livewire\Component;

new class extends Component {
    public PostForm $form;

    // ...
};
```

Here's the `PostForm` form object containing all the available hooks:

```php
namespace App\Livewire\Forms;

use Livewire\Attributes\Validate;
use Livewire\Form;

class PostForm extends Form
{
    public $title = '';

    public $tags = [];

    public function updating($property, $value)
    {
        // ...
    }

    public function updated($property, $value)
    {
        // ...
    }

    public function updatingTitle($value)
    {
        // ...
    }

    public function updatedTitle($value)
    {
        // ...
    }

    public function updatingTags($value, $key)
    {
        // ...
    }

    public function updatedTags($value, $key)
    {
        // ...
    }

    // ...
}
```

---

## Scheduling Defining Schedules Scheduling Queued Jobs
Scheduling | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/scheduling.md

### Scheduling Queued Jobs

The `job` method may be used to schedule a [queued job](/docs/{{version}}/queues). This method provides a convenient way to schedule queued jobs without using the `call` method to define closures to queue the job:

```php
use App\Jobs\Heartbeat;
use Illuminate\Support\Facades\Schedule;

Schedule::job(new Heartbeat)->everyFiveMinutes();
```

Optional second and third arguments may be provided to the `job` method which specifies the queue name and queue connection that should be used to queue the job:

```php
use App\Jobs\Heartbeat;
use Illuminate\Support\Facades\Schedule;

// Dispatch the job to the "heartbeats" queue on the "sqs" connection...
Schedule::job(new Heartbeat, 'heartbeats', 'sqs')->everyFiveMinutes();
```

---

## Structure The App Directory The Http Directory
Structure | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/structure.md

### The Http Directory

The `Http` directory contains your controllers, middleware, and form requests. Almost all of the logic to handle requests entering your application will be placed in this directory.

---

## Validation Deprecated `[#Rule]` attribute
Validation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation

## Deprecated `[#Rule]` attribute

When Livewire v3 first launched, it used the term "Rule" instead of "Validate" for it's validation attributes (`#[Rule]`).

Because of naming conflicts with Laravel rule objects, this has since been changed to `#[Validate]`. Both are supported in Livewire v3, however it is recommended that you change all occurrences of `#[Rule]` with `#[Validate]` to stay current.

---

## Queues Job Events
Queues | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/queues.md

## Job Events

Using the `before` and `after` methods on the `Queue` [facade](/docs/{{version}}/facades), you may specify callbacks to be executed before or after a queued job is processed. These callbacks are a great opportunity to perform additional logging or increment statistics for a dashboard. Typically, you should call these methods from the `boot` method of a [service provider](/docs/{{version}}/providers). For example, we may use the `AppServiceProvider` that is included with Laravel:

```php
<?php

namespace App\Providers;

use Illuminate\Support\Facades\Queue;
use Illuminate\Support\ServiceProvider;
use Illuminate\Queue\Events\JobProcessed;
use Illuminate\Queue\Events\JobProcessing;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        // ...
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Queue::before(function (JobProcessing $event) {
            // $event->connectionName
            // $event->job
            // $event->job->payload()
        });

        Queue::after(function (JobProcessed $event) {
            // $event->connectionName
            // $event->job
            // $event->job->payload()
        });
    }
}
```

Using the `looping` method on the `Queue` [facade](/docs/{{version}}/facades), you may specify callbacks that execute before the worker attempts to fetch a job from a queue. For example, you might register a closure to rollback any transactions that were left open by a previously failed job:

```php
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Queue;

Queue::looping(function () {
    while (DB::transactionLevel() > 0) {
        DB::rollBack();
    }
});
```

---

## Validation Form Request Validation Preparing Input for Validation
Validation | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/validation.md

### Preparing Input for Validation

If you need to prepare or sanitize any data from the request before you apply your validation rules, you may use the `prepareForValidation` method:

```php
use Illuminate\Support\Str;

/**
 * Prepare the data for validation.
 */
protected function prepareForValidation(): void
{
    $this->merge([
        'slug' => Str::slug($this->slug),
    ]);
}
```

Likewise, if you need to normalize any request data after validation is complete, you may use the `passedValidation` method:

```php
/**
 * Handle a passed validation attempt.
 */
protected function passedValidation(): void
{
    $this->replace(['name' => 'Taylor']);
}
```

---

## Octane Serving Your Application Serving Your Application via HTTPS
Octane | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/octane.md

### Serving Your Application via HTTPS

By default, applications running via Octane generate links prefixed with `http://`. The `OCTANE_HTTPS` environment variable, used within your application's `config/octane.php` configuration file, can be set to `true` when serving your application via HTTPS. When this configuration value is set to `true`, Octane will instruct Laravel to prefix all generated links with `https://`:

```php
'https' => env('OCTANE_HTTPS', false),
```

---

## Validation Accessing errors in JavaScript
Validation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation

## Accessing errors in JavaScript

Livewire provides a `$errors` magic property for client-side access to validation errors:

```blade
<form wire:submit="save">
    <input type="email" wire:model="email">

    <div wire:show="$errors.has('email')">
        <span wire:text="$errors.first('email')"></span>
    </div>

    <button type="submit">Save</button>
</form>
```

### Available methods

- `$errors.has('field')` - Check if a field has errors
- `$errors.missing('field')` - Check if a field doesn't have errors
- `$errors.first('field')` - Get the first error message for a field
- `$errors.get('field')` - Get all error messages for a field
- `$errors.all()` - Get all errors for all fields
- `$errors.clear()` - Clear all errors
- `$errors.clear('field')` - Clear errors for a specific field

When using Alpine.js, access `$errors` through `$wire.$errors`.

---

## Validation Validating Arrays Validating Nested Array Input
Validation | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/validation.md

### Validating Nested Array Input

Validating nested array-based form input fields doesn't have to be a pain. You may use "dot notation" to validate attributes within an array. For example, if the incoming HTTP request contains a `photos[profile]` field, you may validate it like so:

```php
use Illuminate\Support\Facades\Validator;

$validator = Validator::make($request->all(), [
    'photos.profile' => 'required|image',
]);
```

You may also validate each element of an array. For example, to validate that each email in a given array input field is unique, you may do the following:

```php
$validator = Validator::make($request->all(), [
    'users.*.email' => 'email|unique:users',
    'users.*.first_name' => 'required_with:users.*.last_name',
]);
```

Likewise, you may use the `*` character when specifying [custom validation messages in your language files](#custom-messages-for-specific-attributes), making it a breeze to use a single validation message for array-based fields:

```php
'custom' => [
    'users.*.email' => [
        'unique' => 'Each user must have a unique email address',
    ]
],
```

---

## Http Client Testing Faking Responses Faking Exceptions
Http Client | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/http-client.md

#### Faking Exceptions

Sometimes you may need to test your application's behavior if the HTTP client encounters an `Illuminate\Http\Client\ConnectionException` when attempting to make a request. You can instruct the HTTP client to throw a connection exception using the `failedConnection` method:

```php
Http::fake([
    'github.com/*' => Http::failedConnection(),
]);
```

To test your application's behavior if a `Illuminate\Http\Client\RequestException` is thrown, you may use the `failedRequest` method:

```php
$this->mock(GithubService::class);
    ->shouldReceive('getUser')
    ->andThrow(
        Http::failedRequest(['code' => 'not_found'], 404)
    );
```

---

## Http Client Testing Faking Responses
Http Client | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/http-client.md

### Faking Responses

For example, to instruct the HTTP client to return empty, `200` status code responses for every request, you may call the `fake` method with no arguments:

```php
use Illuminate\Support\Facades\Http;

Http::fake();

$response = Http::post(/* ... */);
```

---

## Forms Throttling input
Forms | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/forms

## Throttling input

As stated previously, when an input debounce is applied to a field, a network request will not be sent until the user has stopped typing for a certain amount of time. This means if the user continues typing a long message, a network request won't be sent until the user is finished.

Sometimes this isn't the desired behavior, and you would rather send a request as the user types, not when they've finished or taken a break.

In these cases, you can instead use `.throttle` to signify a time interval to send network requests:

```blade
<input type="text" wire:model.live.throttle.150ms="title" >
```

In the above example, as a user is typing continuously in the "title" field, a network request will be sent every 150 milliseconds until the user is finished.

---

## Queues Testing Testing Job / Queue Interactions
Queues | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/queues.md

### Testing Job / Queue Interactions

Sometimes, you may need to test that a queued job [releases itself back onto the queue](#manually-releasing-a-job). Or, you may need to test that the job deleted itself. You may test these queue interactions by instantiating the job and invoking the `withFakeQueueInteractions` method.

Once the job's queue interactions have been faked, you may invoke the `handle` method on the job. After invoking the job, various assertion methods are available to verify the job's queue interactions:

```php
use App\Exceptions\CorruptedAudioException;
use App\Jobs\ProcessPodcast;

$job = (new ProcessPodcast)->withFakeQueueInteractions();

$job->handle();

$job->assertReleased(delay: 30);
$job->assertDeleted();
$job->assertNotDeleted();
$job->assertFailed();
$job->assertFailedWith(CorruptedAudioException::class);
$job->assertNotFailed();
```

---

## Lifecycle Lifecycle Overview HTTP / Console Kernels
Lifecycle | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/lifecycle.md

### HTTP / Console Kernels

Next, the incoming request is sent to either the HTTP kernel or the console kernel, using the `handleRequest` or `handleCommand` methods of the application instance, depending on the type of request entering the application. These two kernels serve as the central location through which all requests flow. For now, let's just focus on the HTTP kernel, which is an instance of `Illuminate\Foundation\Http\Kernel`.

The HTTP kernel defines an array of `bootstrappers` that will be run before the request is executed. These bootstrappers configure error handling, configure logging, [detect the application environment](/docs/{{version}}/configuration#environment-configuration), and perform other tasks that need to be done before the request is actually handled. Typically, these classes handle internal Laravel configuration that you do not need to worry about.

The HTTP kernel is also responsible for passing the request through the application's middleware stack. These middleware handle reading and writing the [HTTP session](/docs/{{version}}/session), determining if the application is in maintenance mode, [verifying the CSRF token](/docs/{{version}}/csrf), and more. We'll talk more about these soon.

The method signature for the HTTP kernel's `handle` method is quite simple: it receives a `Request` and returns a `Response`. Think of the kernel as being a big black box that represents your entire application. Feed it HTTP requests and it will return HTTP responses.

---

## Validation Testing validation
Validation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation

## Testing validation

Livewire provides useful testing utilities for validation scenarios, such as the `assertHasErrors()` method.

Below is a basic test case that ensures validation errors are thrown if no input is set for the `title` property:

```php
<?php

namespace Tests\Feature\Livewire;

use App\Livewire\CreatePost;
use Livewire\Livewire;
use Tests\TestCase;

class CreatePostTest extends TestCase
{
    public function test_cant_create_post_without_title()
    {
        Livewire::test(CreatePost::class)
            ->set('content', 'Sample content...')
            ->call('save')
            ->assertHasErrors('title');
    }
}
```

In addition to testing the presence of errors, `assertHasErrors` allows you to also narrow down the assertion to specific rules by passing the rules to assert against as the second argument to the method:

```php
public function test_cant_create_post_with_title_shorter_than_3_characters()
{
    Livewire::test(CreatePost::class)
        ->set('title', 'Sa')
        ->set('content', 'Sample content...')
        ->call('save')
        ->assertHasErrors(['title' => ['min:3']]);
}
```

You can also assert the presence of validation errors for multiple properties at the same time:

```php
public function test_cant_create_post_without_title_and_content()
{
    Livewire::test(CreatePost::class)
        ->call('save')
        ->assertHasErrors(['title', 'content']);
}
```

For more information on other testing utilities provided by Livewire, check out the [testing documentation](/docs/4.x/testing).

---

## Attribute Validate Example: Contact form
Attribute Validate | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/attribute-validate

## Example: Contact form

Here's a complete contact form with validation:

```php
<?php // resources/views/pages/⚡contact.blade.php

use Livewire\Attributes\Validate;
use Livewire\Component;
use App\Mail\ContactMessage;
use Illuminate\Support\Facades\Mail;

new class extends Component {
    #[Validate('required|min:2', as: 'name')]
    public $name = '';

    #[Validate('required|email')]
    public $email = '';

    #[Validate('required')]
    public $subject = '';

    #[Validate('required|min:10', as: 'message')]
    public $message = '';

    public function submit()
    {
        $validated = $this->validate();

        Mail::to('support@example.com')->send(new ContactMessage($validated));

        session()->flash('success', 'Message sent successfully!');

        $this->reset();
    }
};
?>

<div>
    @if (session('success'))
        <div class="alert">{{ session('success') }}</div>
    @endif

    <form wire:submit="submit">
        <div>
            <input type="text" wire:model.live.blur="name" placeholder="Your name">
            @error('name') <span class="error">{{ $message }}</span> @enderror
        </div>

        <div>
            <input type="email" wire:model.live.blur="email" placeholder="Your email">
            @error('email') <span class="error">{{ $message }}</span> @enderror
        </div>

        <div>
            <input type="text" wire:model.live.blur="subject" placeholder="Subject">
            @error('subject') <span class="error">{{ $message }}</span> @enderror
        </div>

        <div>
            <textarea wire:model.live.blur="message" placeholder="Your message"></textarea>
            @error('message') <span class="error">{{ $message }}</span> @enderror
        </div>

        <button type="submit">Send Message</button>
    </form>
</div>
```

Users get immediate feedback as they fill out the form, with friendly field names and helpful error messages.

---

## Components Navbar > Navlist badges
Components Navbar | livewire/flux@2.x | Source: https://fluxui.dev/components/navbar#livewire/flux

Navlist badges

Show additional information related to a navlist item using the badge prop.

<flux:navlist class="w-64">    <flux:navlist.item href="#" icon="home">Home</flux:navlist.item>    <flux:navlist.item href="#" icon="envelope" badge="12">Inbox</flux:navlist.item>    <flux:navlist.item href="#" icon="user-group">Contacts</flux:navlist.item>    <flux:navlist.item href="#" icon="calendar-days" badge="Pro" badge:color="lime">Calendar</flux:navlist.item></flux:navlist>

---

## Components Badge > flux:badge
Components Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux

flux:badge

<ui-table-scroll-area>

Prop

Description

    color

Badge color (e.g., zinc, red, blue). Default: zinc.

    size

Badge size. Options: sm, lg.

    rounded

If present or true, makes the badge fully rounded instead of slightly rounded corners.

    variant

Badge style variant. Options: solid (depracated: pill, use rounded prop instead).

    icon

Name of the icon to display before the badge text.

    icon:trailing

Name of the icon to display after the badge text.

    icon:variant

Icon variant. Options: outline, solid, mini, micro. Default: mini.

    as

HTML element to render the badge as. Options: button. Default: div.

    inset

Add negative margins to specific sides. Options: top, bottom, left, right, or any combination of the four.

</ui-table-scroll-area>

---

## Forms Extracting input fields to Blade components
Forms | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/forms

## Extracting input fields to Blade components

Even in a small component such as the `post.create` example we've been discussing, we end up duplicating lots of form field boilerplate like validation messages and labels.

It can be helpful to extract repetitive UI elements such as these into dedicated [Blade components](https://laravel.com/docs/blade#components) to be shared across your application.

For example, below is the original Blade template from the `post.create` component. We will be extracting the following two text inputs into dedicated Blade components:

```blade
<form wire:submit="save">
    <input type="text" wire:model="title"> <!-- [tl! highlight:3] -->
    <div>
        @error('title') <span class="error">{{ $message }}</span> @enderror
    </div>

    <input type="text" wire:model="content"> <!-- [tl! highlight:3] -->
    <div>
        @error('content') <span class="error">{{ $message }}</span> @enderror
    </div>

    <button type="submit">Save</button>
</form>
```

Here's what the template will look like after extracting a re-usable Blade component called `<x-input-text>`:

```blade
<form wire:submit="save">
    <x-input-text name="title" wire:model="title" /> <!-- [tl! highlight] -->

    <x-input-text name="content" wire:model="content" /> <!-- [tl! highlight] -->

    <button type="submit">Save</button>
</form>
```

Next, here's the source for the `x-input-text` component:

```blade
<!-- resources/views/components/input-text.blade.php -->

@props(['name'])

<input type="text" name="{{ $name }}" {{ $attributes }}>

<div>
    @error($name) <span class="error">{{ $message }}</span> @enderror
</div>
```

As you can see, we took the repetitive HTML and placed it inside a dedicated Blade component.

For the most part, the Blade component contains only the extracted HTML from the original component. However, we have added two things:

* The `@props` directive
* The `{{ $attributes }}` statement on the input

Let's discuss each of these additions:

By specifying `name` as a "prop" using `@props(['name'])` we are telling Blade: if an attribute called "name" is set on this component, take its value and make it available inside this component as `$name`.

For other attributes that don't have an explicit purpose, we used the `{{ $attributes }}` statement. This is used for "attribute forwarding", or in other words, taking any HTML attributes written on the Blade component and forwarding them onto an element within the component.

This ensures `wire:model="title"` and any other extra attributes such as `disabled`, `class="..."`, or `required` still get forwarded to the actual `<input>` element.

### Custom form controls

In the previous example, we "wrapped" an input element into a re-usable Blade component we can use as if it was a native HTML input element.

This pattern is very useful; however, there might be some cases where you want to create an entire input component from scratch (without an underlying native input element), but still be able to bind its value to Livewire properties using `wire:model`.

For example, let's imagine you wanted to create an `<x-input-counter />` component that was a simple "counter" input written in Alpine.

Before we create a Blade component, let's first look at a simple, pure-Alpine, "counter" component for reference:

```blade
<div x-data="{ count: 0 }">
    <button x-on:click="count--">-</button>

    <span x-text="count"></span>

    <button x-on:click="count++">+</button>
</div>
```

As you can see, the component above shows a number alongside two buttons to increment and decrement that number.

Now, let's imagine we want to extract this component into a Blade component called `<x-input-counter />` that we would use within a component like so:

```blade
<x-input-counter wire:model="quantity" />
```

Creating this component is mostly simple. We take the HTML of the counter and place it inside a Blade component template like `resources/views/components/input-counter.blade.php`.

However, making it work with `wire:model="quantity"` so that you can easily bind data from your Livewire component to the "count" inside this Alpine component needs one extra step.

Here's the source for the component:

```blade
<!-- resources/view/components/input-counter.blade.php -->

<div x-data="{ count: 0 }" x-modelable="count" {{ $attributes}}>
    <button x-on:click="count--">-</button>

    <span x-text="count"></span>

    <button x-on:click="count++">+</button>
</div>
```

As you can see, the only different bit about this HTML is the `x-modelable="count"` and `{{ $attributes }}`.

`x-modelable` is a utility in Alpine that tells Alpine to make a certain piece of data available for binding from outside. [The Alpine documentation has more information on this directive.](https://alpinejs.dev/directives/modelable)

`{{ $attributes }}`, as we explored earlier, forwards any attributes passed into the Blade component from outside. In this case, the `wire:model` directive will be forwarded.

Because of `{{ $attributes }}`, when the HTML is rendered in the browser, `wire:model="quantity"` will be rendered alongside `x-modelable="count"` on the root `<div>` of the Alpine component like so:

```blade
<div x-data="{ count: 0 }" x-modelable="count" wire:model="quantity">
```

`x-modelable="count"` tells Alpine to look for any `x-model` or `wire:model` statements and use "count" as the data to bind them to.

Because `x-modelable` works for both `wire:model` and `x-model`, you can also use this Blade component interchangeably with Livewire and Alpine. Here’s an example of using this Blade component in a purely Alpine context:

```blade
<x-input-counter x-model="quantity" />
```

Creating custom input elements in your application is extremely powerful but requires a deeper understanding of the utilities Livewire and Alpine provide and how they interact with each other.

---

## Queues Testing Testing Job Batches Testing Job / Batch Interaction
Queues | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/queues.md

#### Testing Job / Batch Interaction

In addition, you may occasionally need to test an individual job's interaction with its underlying batch. For example, you may need to test if a job cancelled further processing for its batch. To accomplish this, you need to assign a fake batch to the job via the `withFakeBatch` method. The `withFakeBatch` method returns a tuple containing the job instance and the fake batch:

```php
[$job, $batch] = (new ShipOrder)->withFakeBatch();

$job->handle();

$this->assertTrue($batch->cancelled());
$this->assertEmpty($batch->added);
```

---

## Http Tests Validation Assertions assertValid
Http Tests | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/http-tests.md

#### assertValid

Assert that the response has no validation errors for the given keys. This method may be used for asserting against responses where the validation errors are returned as a JSON structure or where the validation errors have been flashed to the session:

```php
// Assert that no validation errors are present...
$response->assertValid();

// Assert that the given keys do not have validation errors...
$response->assertValid(['name', 'email']);
```

---

## Validation Using custom validators
Validation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation

## Using custom validators

If you wish to use your own validation system in Livewire, that isn't a problem. Livewire will catch any `ValidationException` exceptions thrown inside of components and provide the errors to the view just as if you were using Livewire's own `validate()` method.

Below is an example of the `CreatePost` component, but instead of using Livewire's validation features, a completely custom validator is being created and applied to the component properties:

```php
use Illuminate\Support\Facades\Validator;
use Livewire\Component;
use App\Models\Post;

class CreatePost extends Component
{
	public $title = '';

    public $content = '';

    public function save()
    {
        $validated = Validator::make(
            // Data to validate...
            ['title' => $this->title, 'content' => $this->content],

            // Validation rules to apply...
            ['title' => 'required|min:3', 'content' => 'required|min:3'],

            // Custom validation messages...
            ['required' => 'The :attribute field is required'],
         )->validate();

		Post::create($validated);

		return redirect()->to('/posts');
    }

    // ...
}
```

_[Truncated]_


output:
Wall time: 5.2501 seconds
Output:
[{"type":"text","text":"# Search Results\n\n## Queues Testing Faking a Subset of Jobs\nQueues | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/queues.md\n\n\n### Faking a Subset of Jobs\n\nIf you only need to fake specific jobs while allowing your other jobs to execute normally, you may pass the class names of the jobs that should be faked to the `fake` method:\n\n```php tab=Pest\ntest('orders can be shipped', function () {\n    Queue::fake([\n        ShipOrder::class,\n    ]);\n\n    // Perform order shipping...\n\n    // Assert a job was pushed twice...\n    Queue::assertPushedTimes(ShipOrder::class, 2);\n});\n```\n\n```php tab=PHPUnit\npublic function test_orders_can_be_shipped(): void\n{\n    Queue::fake([\n        ShipOrder::class,\n    ]);\n\n    // Perform order shipping...\n\n    // Assert a job was pushed twice...\n    Queue::assertPushedTimes(ShipOrder::class, 2);\n}\n```\n\nYou may fake all jobs except for a set of specified jobs using the `except` method:\n\n```php\nQueue::fake()->except([\n    ShipOrder::class,\n]);\n```\n\n---\n\n## Horizon Installation Job Backoff\nHorizon | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/horizon.md\n\n\n### Job Backoff\n\nYou can define the `backoff` value at the supervisor level to specify how long Horizon should wait before retrying a job that encounters an unhandled exception:\n\n```php\n'environments' => [\n    'production' => [\n        'supervisor-1' => [\n            // ...\n            'backoff' => 10,\n        ],\n    ],\n],\n```\n\nYou may also configure \"exponential\" backoffs by using an array for the `backoff` value. In this example, the retry delay will be 1 second for the first retry, 5 seconds for the second retry, 10 seconds for the third retry, and 10 seconds for every subsequent retry if there are more attempts remaining:\n\n```php\n'environments' => [\n    'production' => [\n        'supervisor-1' => [\n            // ...\n            'backoff' => [1, 5, 10],\n        ],\n    ],\n],\n```\n\n---\n\n## Components Modal > Modal\nComponents Modal | livewire/flux@2.x | Source: https://fluxui.dev/components/modal#livewire/flux\n\n

\n    Modal\n

Display content in a layer above the main page. Ideal for confirmations, alerts, and forms.

<flux:modal.trigger name=\"edit-profile\">    <flux:button>Edit profile</flux:button></flux:modal.trigger><flux:modal name=\"edit-profile\" class=\"md:w-96\">

            <flux:heading size=\"lg\">Update profile</flux:heading>            <flux:text class=\"mt-2\">Make changes to your personal details.</flux:text>
        <flux:input label=\"Name\" placeholder=\"Your name\" />        <flux:input label=\"Date of birth\" type=\"date\" />
            <flux:spacer />            <flux:button type=\"submit\" variant=\"primary\">Save changes</flux:button>

</flux:modal>

\n\n---\n\n## Validation Form objects\nValidation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation\n\n## Form objects\n\nAs more properties and validation rules are added to a Livewire component, it can begin to feel too crowded. To alleviate this pain and also provide a helpful abstraction for code reuse, you can use Livewire's *Form Objects* to store your properties and validation rules.\n\nBelow is the same `CreatePost` example, but now the properties and rules have been extracted to a dedicated form object named `PostForm`:\n\n```php\n<?php\n\nnamespace App\\Livewire\\Forms;\n\nuse Livewire\\Attributes\\Validate;\nuse Livewire\\Form;\n\nclass PostForm extends Form\n{\n    #[Validate('required|min:3')]\n\tpublic $title = '';\n\n    #[Validate('required|min:3')]\n    public $content = '';\n}\n```\n\nThe `PostForm` above can now be defined as a property on the `CreatePost` component:\n\n```php\n<?php\n\nnamespace App\\Livewire;\n\nuse App\\Livewire\\Forms\\PostForm;\nuse Livewire\\Component;\nuse App\\Models\\Post;\n\nclass CreatePost extends Component\n{\n    public PostForm $form;\n\n    public function save()\n    {\n\t\tPost::create(\n    \t\t$this->form->all()\n    \t);\n\n\t\treturn redirect()->to('/posts');\n    }\n\n    // ...\n}\n```\n\nAs you can see, instead of listing out each property individually, we can retrieve all the property values using the `->all()` method on the form object.\n\nAlso, when referencing the property names in the template, you must prepend `form.` to each instance:\n\n```blade\n<form wire:submit=\"save\">\n\t<input type=\"text\" wire:model=\"form.title\">\n    <div>@error('form.title') {{ $message }} @enderror</div>\n\n\t<textarea wire:model=\"form.content\"></textarea>\n    <div>@error('form.content') {{ $message }} @enderror</div>\n\n\t<button type=\"submit\">Save</button>\n</form>\n```\n\nWhen using form objects, `#[Validate]` attribute validation will be run every time a property is updated. However, if you disable this behavior by specifying `onUpdate: false` on the attribute, you can manually run a form object's validation using `$this->form->validate()`:\n\n```php\npublic function save()\n{\n    Post::create(\n        $this->form->validate()\n    );\n\n    return redirect()->to('/posts');\n}\n```\n\nForm objects are a useful abstraction for most larger datasets and a variety of additional features that make them even more powerful. For more information, check out the comprehensive [form object documentation](/docs/4.x/forms#extracting-a-form-object).\n\n---\n\n## Http Tests Validation Assertions assertInvalid\nHttp Tests | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/http-tests.md\n\n\n#### assertInvalid\n\nAssert that the response has validation errors for the given keys. This method may be used for asserting against responses where the validation errors are returned as a JSON structure or where the validation errors have been flashed to the session:\n\n```php\n$response->assertInvalid(['name', 'email']);\n```\n\nYou may also assert that a given key has a particular validation error message. When doing so, you may provide the entire message or only a small portion of the message:\n\n```php\n$response->assertInvalid([\n    'name' => 'The name field is required.',\n    'email' => 'valid email address',\n]);\n```\n\n---\n\n## Components Badge > With close button\nComponents Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux\n\n
With close button

Make a badge removable by appending a close button.

<flux:badge>    Admin <flux:badge.close /></flux:badge>

\n\n---\n\n## Components Badge > Rounded\nComponents Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux\n\n
Rounded

Display badges with a fully rounded border radius using the rounded prop.

<flux:badge rounded icon=\"user\">Users</flux:badge>

\n\n---\n\n## Validation See also\nValidation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation\n\n## See also\n\n- **[Forms](/docs/4.x/forms)** — Validate form inputs with real-time feedback\n- **[Properties](/docs/4.x/properties)** — Validate property values before persisting\n- **[Validate Attribute](/docs/4.x/attribute-validate)** — Use #[Validate] for property validation\n- **[Actions](/docs/4.x/actions)** — Validate data in action methods\n\n---\n\n## Telescope Available Watchers HTTP Client Watcher\nTelescope | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/telescope.md\n\n\n### HTTP Client Watcher\n\nThe HTTP client watcher records outgoing [HTTP client requests](/docs/{{version}}/http-client) made by your application.\n\n---\n\n## Scout Installation Queueing\nScout | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/scout.md\n\n\n### Queueing\n\nWhen using an engine that is not the `database` or `collection` engine, you should strongly consider configuring a [queue driver](/docs/{{version}}/queues) before using the library. Running a queue worker will allow Scout to queue all operations that sync your model information to your search indexes, providing much better response times for your application's web interface.\n\nOnce you have configured a queue driver, set the value of the `queue` option in your `config/scout.php` configuration file to `true`:\n\n```php\n'queue' => true,\n```\n\nEven when the `queue` option is set to `false`, it's important to remember that some Scout drivers like Algolia and Meilisearch always index records asynchronously. In other words, even though the index operation has completed within your Laravel application, the search engine itself may not reflect the new and updated records immediately.\n\nTo specify the connection and queue that your Scout jobs utilize, you may define the `queue` configuration option as an array:\n\n```php\n'queue' => [\n    'connection' => 'redis',\n    'queue' => 'scout'\n],\n```\n\nOf course, if you customize the connection and queue that Scout jobs utilize, you should run a queue worker to process jobs on that connection and queue:\n\n```shell\nphp artisan queue:work redis --queue=scout\n```\n\n---\n\n## Understanding Nesting Performance implications\nUnderstanding Nesting | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/understanding-nesting\n\n## Performance implications\n\nLivewire's independent component architecture can have both positive and negative implications for your application.\n\nAn advantage of this architecture is it allows you to isolate expensive portions of your application. For example, you can quarantine a slow database query to its own independent component, and its performance overhead won't impact the rest of the page.\n\nHowever, the biggest drawback of this approach is that because components are entirely separate, inter-component communication/dependencies becomes more difficult.\n\nFor example, if you had a property passed down from the above parent `Posts` component to the nested `ShowPost` component, it wouldn't be \"reactive\". Because each component is independent, if a request to the parent component changed the value of the property being passed into `ShowPost`, it wouldn't update inside `ShowPost`.\n\nLivewire has overcome a number of these hurdles and provides dedicated APIs for these scenarios like: [Reactive properties](/docs/4.x/nesting#reactive-props), [Modelable components](/docs/4.x/nesting#binding-to-child-data-using-wiremodel), and [the `$parent` object](/docs/4.x/nesting#directly-accessing-the-parent-from-the-child).\n\nArmed with this knowledge of how nested Livewire components operate, you will be able to make more informed decisions about when and how to nest components within your application.\n\n---\n\n## Queues Dealing With Failed Jobs\nQueues | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/queues.md\n\n\n## Dealing With Failed Jobs\n\nSometimes your queued jobs will fail. Don't worry, things don't always go as planned! Laravel includes a convenient way to [specify the maximum number of times a job should be attempted](#max-job-attempts-and-timeout). After an asynchronous job has exceeded this number of attempts, it will be inserted into the `failed_jobs` database table. [Synchronously dispatched jobs](/docs/{{version}}/queues#synchronous-dispatching) that fail are not stored in this table and their exceptions are immediately handled by the application.\n\nA migration to create the `failed_jobs` table is typically already present in new Laravel applications. However, if your application does not contain a migration for this table, you may use the `make:queue-failed-table` command to create the migration:\n\n```shell\nphp artisan make:queue-failed-table\n\nphp artisan migrate\n```\n\nWhen running a [queue worker](#running-the-queue-worker) process, you may specify the maximum number of times a job should be attempted using the `--tries` switch on the `queue:work` command. If you do not specify a value for the `--tries` option, jobs will only be attempted once or as many times as specified by the job class' `$tries` property:\n\n```shell\nphp artisan queue:work redis --tries=3\n```\n\nUsing the `--backoff` option, you may specify how many seconds Laravel should wait before retrying a job that has encountered an exception. By default, a job is immediately released back onto the queue so that it may be attempted again:\n\n```shell\nphp artisan queue:work redis --tries=3 --backoff=3\n```\n\nIf you would like to configure how many seconds Laravel should wait before retrying a job that has encountered an exception on a per-job basis, you may do so by defining a `backoff` property on your job class:\n\n```php\n/**\n * The number of seconds to wait before retrying the job.\n *\n * @var int\n */\npublic $backoff = 3;\n```\n\nIf you require more complex logic for determining the job's backoff time, you may define a `backoff` method on your job class:\n\n```php\n/**\n * Calculate the number of seconds to wait before retrying the job.\n */\npublic function backoff(): int\n{\n    return 3;\n}\n```\n\nYou may easily configure \"exponential\" backoffs by returning an array of backoff values from the `backoff` method. In this example, the retry delay will be 1 second for the first retry, 5 seconds for the second retry, 10 seconds for the third retry, and 10 seconds for every subsequent retry if there are more attempts remaining:\n\n```php\n/**\n * Calculate the number of seconds to wait before retrying the job.\n *\n * @return array<int, int>\n */\npublic function backoff(): array\n{\n    return [1, 5, 10];\n}\n```\n\n---\n\n## Validation Form Request Validation\nValidation | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/validation.md\n\n\n## Form Request Validation\n\n---\n\n## Components Badge > Badge\nComponents Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux\n\n

\n    Badge\n

Highlight information like status, category, or count.

<flux:badge color=\"lime\">New</flux:badge>

\n\n---\n\n## Http Client Testing Preventing Stray Requests\nHttp Client | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/http-client.md\n\n\n### Preventing Stray Requests\n\nIf you would like to ensure that all requests sent via the HTTP client have been faked throughout your individual test or complete test suite, you can call the `preventStrayRequests` method. After calling this method, any requests that do not have a corresponding fake response will throw an exception rather than making the actual HTTP request:\n\n```php\nuse Illuminate\\Support\\Facades\\Http;\n\nHttp::preventStrayRequests();\n\nHttp::fake([\n    'github.com/*' => Http::response('ok'),\n]);\n\n// An \"ok\" response is returned...\nHttp::get('https://github.com/laravel/framework');\n\n// An exception is thrown...\nHttp::get('https://laravel.com');\n```\n\nSometimes, you may wish to prevent most stray requests while still allowing specific requests to execute. To accomplish this, you may pass an array of URL patterns to the `allowStrayRequests` method. Any request matching one of the given patterns will be allowed, while all other requests will continue to throw an exception:\n\n```php\nuse Illuminate\\Support\\Facades\\Http;\n\nHttp::preventStrayRequests();\n\nHttp::allowStrayRequests([\n    'http://127.0.0.1:5000/*',\n]);\n\n// This request is executed...\nHttp::get('http://127.0.0.1:5000/generate');\n\n// An exception is thrown...\nHttp::get('https://laravel.com');\n```\n\n---\n\n## Components Badge > As button\nComponents Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux\n\n
As button

Make the entire badge clickable by wrapping it in a button element.

<flux:badge as=\"button\" rounded icon=\"plus\" size=\"lg\">Amount</flux:badge>

\n\n---\n\n## Components Field > With badge\nComponents Field | livewire/flux@2.x | Source: https://fluxui.dev/components/field#livewire/flux\n\n
With badge

Badges allow you to enhance a field with additional information such as being \"required\" or \"optional\" when it might not be expected.

<flux:field>    <flux:label badge=\"Required\">Email</flux:label>    <flux:input type=\"email\" required />    <flux:error name=\"email\" /></flux:field><flux:field>    <flux:label badge=\"Optional\">Phone number</flux:label>    <flux:input type=\"phone\" placeholder=\"(555) 555-5555\" mask=\"(999) 999-9999\"  />    <flux:error name=\"phone\" /></flux:field>

\n\n---\n\n## Forms See also\nForms | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/forms\n\n## See also\n\n- **[Validation](/docs/4.x/validation)** — Validate form inputs with real-time feedback\n- **[wire:model](/docs/4.x/wire-model)** — Bind form inputs to component properties\n- **[File Uploads](/docs/4.x/uploads)** — Handle file uploads in forms\n- **[Actions](/docs/4.x/actions)** — Process form submissions with actions\n- **[Loading States](/docs/4.x/loading-states)** — Show loading indicators during form submission\n\n---\n\n## Lifecycle Hooks Using hooks inside a form object\nLifecycle Hooks | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/lifecycle-hooks\n\n## Using hooks inside a form object\n\nForm objects in Livewire support property update hooks. These hooks work similarly to [component update hooks](#update), letting you perform actions when properties in the form object change.\n\nBelow is an example of a component using a `PostForm` form object:\n\n```php\n<?php // resources/views/components/post/⚡create.blade.php\n\nuse Livewire\\Component;\n\nnew class extends Component {\n    public PostForm $form;\n\n    // ...\n};\n```\n\nHere's the `PostForm` form object containing all the available hooks:\n\n```php\nnamespace App\\Livewire\\Forms;\n\nuse Livewire\\Attributes\\Validate;\nuse Livewire\\Form;\n\nclass PostForm extends Form\n{\n    public $title = '';\n\n    public $tags = [];\n\n    public function updating($property, $value)\n    {\n        // ...\n    }\n\n    public function updated($property, $value)\n    {\n        // ...\n    }\n\n    public function updatingTitle($value)\n    {\n        // ...\n    }\n\n    public function updatedTitle($value)\n    {\n        // ...\n    }\n\n    public function updatingTags($value, $key)\n    {\n        // ...\n    }\n\n    public function updatedTags($value, $key)\n    {\n        // ...\n    }\n\n    // ...\n}\n```\n\n---\n\n## Scheduling Defining Schedules Scheduling Queued Jobs\nScheduling | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/scheduling.md\n\n\n### Scheduling Queued Jobs\n\nThe `job` method may be used to schedule a [queued job](/docs/{{version}}/queues). This method provides a convenient way to schedule queued jobs without using the `call` method to define closures to queue the job:\n\n```php\nuse App\\Jobs\\Heartbeat;\nuse Illuminate\\Support\\Facades\\Schedule;\n\nSchedule::job(new Heartbeat)->everyFiveMinutes();\n```\n\nOptional second and third arguments may be provided to the `job` method which specifies the queue name and queue connection that should be used to queue the job:\n\n```php\nuse App\\Jobs\\Heartbeat;\nuse Illuminate\\Support\\Facades\\Schedule;\n\n// Dispatch the job to the \"heartbeats\" queue on the \"sqs\" connection...\nSchedule::job(new Heartbeat, 'heartbeats', 'sqs')->everyFiveMinutes();\n```\n\n---\n\n## Structure The App Directory The Http Directory\nStructure | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/structure.md\n\n\n### The Http Directory\n\nThe `Http` directory contains your controllers, middleware, and form requests. Almost all of the logic to handle requests entering your application will be placed in this directory.\n\n---\n\n## Validation Deprecated `[#Rule]` attribute\nValidation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation\n\n## Deprecated `[#Rule]` attribute\n\nWhen Livewire v3 first launched, it used the term \"Rule\" instead of \"Validate\" for it's validation attributes (`#[Rule]`).\n\nBecause of naming conflicts with Laravel rule objects, this has since been changed to `#[Validate]`. Both are supported in Livewire v3, however it is recommended that you change all occurrences of `#[Rule]` with `#[Validate]` to stay current.\n\n---\n\n## Queues Job Events\nQueues | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/queues.md\n\n\n## Job Events\n\nUsing the `before` and `after` methods on the `Queue` [facade](/docs/{{version}}/facades), you may specify callbacks to be executed before or after a queued job is processed. These callbacks are a great opportunity to perform additional logging or increment statistics for a dashboard. Typically, you should call these methods from the `boot` method of a [service provider](/docs/{{version}}/providers). For example, we may use the `AppServiceProvider` that is included with Laravel:\n\n```php\n<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\Facades\\Queue;\nuse Illuminate\\Support\\ServiceProvider;\nuse Illuminate\\Queue\\Events\\JobProcessed;\nuse Illuminate\\Queue\\Events\\JobProcessing;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    /**\n     * Register any application services.\n     */\n    public function register(): void\n    {\n        // ...\n    }\n\n    /**\n     * Bootstrap any application services.\n     */\n    public function boot(): void\n    {\n        Queue::before(function (JobProcessing $event) {\n            // $event->connectionName\n            // $event->job\n            // $event->job->payload()\n        });\n\n        Queue::after(function (JobProcessed $event) {\n            // $event->connectionName\n            // $event->job\n            // $event->job->payload()\n        });\n    }\n}\n```\n\nUsing the `looping` method on the `Queue` [facade](/docs/{{version}}/facades), you may specify callbacks that execute before the worker attempts to fetch a job from a queue. For example, you might register a closure to rollback any transactions that were left open by a previously failed job:\n\n```php\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Support\\Facades\\Queue;\n\nQueue::looping(function () {\n    while (DB::transactionLevel() > 0) {\n        DB::rollBack();\n    }\n});\n```\n\n---\n\n## Validation Form Request Validation Preparing Input for Validation\nValidation | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/validation.md\n\n\n### Preparing Input for Validation\n\nIf you need to prepare or sanitize any data from the request before you apply your validation rules, you may use the `prepareForValidation` method:\n\n```php\nuse Illuminate\\Support\\Str;\n\n/**\n * Prepare the data for validation.\n */\nprotected function prepareForValidation(): void\n{\n    $this->merge([\n        'slug' => Str::slug($this->slug),\n    ]);\n}\n```\n\nLikewise, if you need to normalize any request data after validation is complete, you may use the `passedValidation` method:\n\n```php\n/**\n * Handle a passed validation attempt.\n */\nprotected function passedValidation(): void\n{\n    $this->replace(['name' => 'Taylor']);\n}\n```\n\n---\n\n## Octane Serving Your Application Serving Your Application via HTTPS\nOctane | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/octane.md\n\n\n### Serving Your Application via HTTPS\n\nBy default, applications running via Octane generate links prefixed with `http://`. The `OCTANE_HTTPS` environment variable, used within your application's `config/octane.php` configuration file, can be set to `true` when serving your application via HTTPS. When this configuration value is set to `true`, Octane will instruct Laravel to prefix all generated links with `https://`:\n\n```php\n'https' => env('OCTANE_HTTPS', false),\n```\n\n---\n\n## Validation Accessing errors in JavaScript\nValidation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation\n\n## Accessing errors in JavaScript\n\nLivewire provides a `$errors` magic property for client-side access to validation errors:\n\n```blade\n<form wire:submit=\"save\">\n    <input type=\"email\" wire:model=\"email\">\n\n    <div wire:show=\"$errors.has('email')\">\n        <span wire:text=\"$errors.first('email')\"></span>\n    </div>\n\n    <button type=\"submit\">Save</button>\n</form>\n```\n\n### Available methods\n\n- `$errors.has('field')` - Check if a field has errors\n- `$errors.missing('field')` - Check if a field doesn't have errors\n- `$errors.first('field')` - Get the first error message for a field\n- `$errors.get('field')` - Get all error messages for a field\n- `$errors.all()` - Get all errors for all fields\n- `$errors.clear()` - Clear all errors\n- `$errors.clear('field')` - Clear errors for a specific field\n\nWhen using Alpine.js, access `$errors` through `$wire.$errors`.\n\n---\n\n## Validation Validating Arrays Validating Nested Array Input\nValidation | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/validation.md\n\n\n### Validating Nested Array Input\n\nValidating nested array-based form input fields doesn't have to be a pain. You may use \"dot notation\" to validate attributes within an array. For example, if the incoming HTTP request contains a `photos[profile]` field, you may validate it like so:\n\n```php\nuse Illuminate\\Support\\Facades\\Validator;\n\n$validator = Validator::make($request->all(), [\n    'photos.profile' => 'required|image',\n]);\n```\n\nYou may also validate each element of an array. For example, to validate that each email in a given array input field is unique, you may do the following:\n\n```php\n$validator = Validator::make($request->all(), [\n    'users.*.email' => 'email|unique:users',\n    'users.*.first_name' => 'required_with:users.*.last_name',\n]);\n```\n\nLikewise, you may use the `*` character when specifying [custom validation messages in your language files](#custom-messages-for-specific-attributes), making it a breeze to use a single validation message for array-based fields:\n\n```php\n'custom' => [\n    'users.*.email' => [\n        'unique' => 'Each user must have a unique email address',\n    ]\n],\n```\n\n---\n\n## Http Client Testing Faking Responses Faking Exceptions\nHttp Client | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/http-client.md\n\n\n#### Faking Exceptions\n\nSometimes you may need to test your application's behavior if the HTTP client encounters an `Illuminate\\Http\\Client\\ConnectionException` when attempting to make a request. You can instruct the HTTP client to throw a connection exception using the `failedConnection` method:\n\n```php\nHttp::fake([\n    'github.com/*' => Http::failedConnection(),\n]);\n```\n\nTo test your application's behavior if a `Illuminate\\Http\\Client\\RequestException` is thrown, you may use the `failedRequest` method:\n\n```php\n$this->mock(GithubService::class);\n    ->shouldReceive('getUser')\n    ->andThrow(\n        Http::failedRequest(['code' => 'not_found'], 404)\n    );\n```\n\n---\n\n## Http Client Testing Faking Responses\nHttp Client | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/http-client.md\n\n\n### Faking Responses\n\nFor example, to instruct the HTTP client to return empty, `200` status code responses for every request, you may call the `fake` method with no arguments:\n\n```php\nuse Illuminate\\Support\\Facades\\Http;\n\nHttp::fake();\n\n$response = Http::post(/* ... */);\n```\n\n---\n\n## Forms Throttling input\nForms | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/forms\n\n## Throttling input\n\nAs stated previously, when an input debounce is applied to a field, a network request will not be sent until the user has stopped typing for a certain amount of time. This means if the user continues typing a long message, a network request won't be sent until the user is finished.\n\nSometimes this isn't the desired behavior, and you would rather send a request as the user types, not when they've finished or taken a break.\n\nIn these cases, you can instead use `.throttle` to signify a time interval to send network requests:\n\n```blade\n<input type=\"text\" wire:model.live.throttle.150ms=\"title\" >\n```\n\nIn the above example, as a user is typing continuously in the \"title\" field, a network request will be sent every 150 milliseconds until the user is finished.\n\n---\n\n## Queues Testing Testing Job / Queue Interactions\nQueues | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/queues.md\n\n\n### Testing Job / Queue Interactions\n\nSometimes, you may need to test that a queued job [releases itself back onto the queue](#manually-releasing-a-job). Or, you may need to test that the job deleted itself. You may test these queue interactions by instantiating the job and invoking the `withFakeQueueInteractions` method.\n\nOnce the job's queue interactions have been faked, you may invoke the `handle` method on the job. After invoking the job, various assertion methods are available to verify the job's queue interactions:\n\n```php\nuse App\\Exceptions\\CorruptedAudioException;\nuse App\\Jobs\\ProcessPodcast;\n\n$job = (new ProcessPodcast)->withFakeQueueInteractions();\n\n$job->handle();\n\n$job->assertReleased(delay: 30);\n$job->assertDeleted();\n$job->assertNotDeleted();\n$job->assertFailed();\n$job->assertFailedWith(CorruptedAudioException::class);\n$job->assertNotFailed();\n```\n\n---\n\n## Lifecycle Lifecycle Overview HTTP / Console Kernels\nLifecycle | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/lifecycle.md\n\n\n### HTTP / Console Kernels\n\nNext, the incoming request is sent to either the HTTP kernel or the console kernel, using the `handleRequest` or `handleCommand` methods of the application instance, depending on the type of request entering the application. These two kernels serve as the central location through which all requests flow. For now, let's just focus on the HTTP kernel, which is an instance of `Illuminate\\Foundation\\Http\\Kernel`.\n\nThe HTTP kernel defines an array of `bootstrappers` that will be run before the request is executed. These bootstrappers configure error handling, configure logging, [detect the application environment](/docs/{{version}}/configuration#environment-configuration), and perform other tasks that need to be done before the request is actually handled. Typically, these classes handle internal Laravel configuration that you do not need to worry about.\n\nThe HTTP kernel is also responsible for passing the request through the application's middleware stack. These middleware handle reading and writing the [HTTP session](/docs/{{version}}/session), determining if the application is in maintenance mode, [verifying the CSRF token](/docs/{{version}}/csrf), and more. We'll talk more about these soon.\n\nThe method signature for the HTTP kernel's `handle` method is quite simple: it receives a `Request` and returns a `Response`. Think of the kernel as being a big black box that represents your entire application. Feed it HTTP requests and it will return HTTP responses.\n\n---\n\n## Validation Testing validation\nValidation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation\n\n## Testing validation\n\nLivewire provides useful testing utilities for validation scenarios, such as the `assertHasErrors()` method.\n\nBelow is a basic test case that ensures validation errors are thrown if no input is set for the `title` property:\n\n```php\n<?php\n\nnamespace Tests\\Feature\\Livewire;\n\nuse App\\Livewire\\CreatePost;\nuse Livewire\\Livewire;\nuse Tests\\TestCase;\n\nclass CreatePostTest extends TestCase\n{\n    public function test_cant_create_post_without_title()\n    {\n        Livewire::test(CreatePost::class)\n            ->set('content', 'Sample content...')\n            ->call('save')\n            ->assertHasErrors('title');\n    }\n}\n```\n\nIn addition to testing the presence of errors, `assertHasErrors` allows you to also narrow down the assertion to specific rules by passing the rules to assert against as the second argument to the method:\n\n```php\npublic function test_cant_create_post_with_title_shorter_than_3_characters()\n{\n    Livewire::test(CreatePost::class)\n        ->set('title', 'Sa')\n        ->set('content', 'Sample content...')\n        ->call('save')\n        ->assertHasErrors(['title' => ['min:3']]);\n}\n```\n\nYou can also assert the presence of validation errors for multiple properties at the same time:\n\n```php\npublic function test_cant_create_post_without_title_and_content()\n{\n    Livewire::test(CreatePost::class)\n        ->call('save')\n        ->assertHasErrors(['title', 'content']);\n}\n```\n\nFor more information on other testing utilities provided by Livewire, check out the [testing documentation](/docs/4.x/testing).\n\n---\n\n## Attribute Validate Example: Contact form\nAttribute Validate | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/attribute-validate\n\n## Example: Contact form\n\nHere's a complete contact form with validation:\n\n```php\n<?php // resources/views/pages/⚡contact.blade.php\n\nuse Livewire\\Attributes\\Validate;\nuse Livewire\\Component;\nuse App\\Mail\\ContactMessage;\nuse Illuminate\\Support\\Facades\\Mail;\n\nnew class extends Component {\n    #[Validate('required|min:2', as: 'name')]\n    public $name = '';\n\n    #[Validate('required|email')]\n    public $email = '';\n\n    #[Validate('required')]\n    public $subject = '';\n\n    #[Validate('required|min:10', as: 'message')]\n    public $message = '';\n\n    public function submit()\n    {\n        $validated = $this->validate();\n\n        Mail::to('support@example.com')->send(new ContactMessage($validated));\n\n        session()->flash('success', 'Message sent successfully!');\n\n        $this->reset();\n    }\n};\n?>\n\n<div>\n    @if (session('success'))\n        <div class=\"alert\">{{ session('success') }}</div>\n    @endif\n\n    <form wire:submit=\"submit\">\n        <div>\n            <input type=\"text\" wire:model.live.blur=\"name\" placeholder=\"Your name\">\n            @error('name') <span class=\"error\">{{ $message }}</span> @enderror\n        </div>\n\n        <div>\n            <input type=\"email\" wire:model.live.blur=\"email\" placeholder=\"Your email\">\n            @error('email') <span class=\"error\">{{ $message }}</span> @enderror\n        </div>\n\n        <div>\n            <input type=\"text\" wire:model.live.blur=\"subject\" placeholder=\"Subject\">\n            @error('subject') <span class=\"error\">{{ $message }}</span> @enderror\n        </div>\n\n        <div>\n            <textarea wire:model.live.blur=\"message\" placeholder=\"Your message\"></textarea>\n            @error('message') <span class=\"error\">{{ $message }}</span> @enderror\n        </div>\n\n        <button type=\"submit\">Send Message</button>\n    </form>\n</div>\n```\n\nUsers get immediate feedback as they fill out the form, with friendly field names and helpful error messages.\n\n---\n\n## Components Navbar > Navlist badges\nComponents Navbar | livewire/flux@2.x | Source: https://fluxui.dev/components/navbar#livewire/flux\n\n
Navlist badges

Show additional information related to a navlist item using the badge prop.

<flux:navlist class=\"w-64\">    <flux:navlist.item href=\"#\" icon=\"home\">Home</flux:navlist.item>    <flux:navlist.item href=\"#\" icon=\"envelope\" badge=\"12\">Inbox</flux:navlist.item>    <flux:navlist.item href=\"#\" icon=\"user-group\">Contacts</flux:navlist.item>    <flux:navlist.item href=\"#\" icon=\"calendar-days\" badge=\"Pro\" badge:color=\"lime\">Calendar</flux:navlist.item></flux:navlist>

\n\n---\n\n## Components Badge > flux:badge\nComponents Badge | livewire/flux@2.x | Source: https://fluxui.dev/components/badge#livewire/flux\n\n
flux:badge

<ui-table-scroll-area>

Prop

Description

\n    color\n

Badge color (e.g., zinc, red, blue). Default: zinc.

\n    size\n

Badge size. Options: sm, lg.

\n    rounded\n

If present or true, makes the badge fully rounded instead of slightly rounded corners.

\n    variant\n

Badge style variant. Options: solid (depracated: pill, use rounded prop instead).

\n    icon\n

Name of the icon to display before the badge text.

\n    icon:trailing\n

Name of the icon to display after the badge text.

\n    icon:variant\n

Icon variant. Options: outline, solid, mini, micro. Default: mini.

\n    as\n

HTML element to render the badge as. Options: button. Default: div.

\n    inset\n

Add negative margins to specific sides. Options: top, bottom, left, right, or any combination of the four.

</ui-table-scroll-area>

\n\n---\n\n## Forms Extracting input fields to Blade components\nForms | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/forms\n\n## Extracting input fields to Blade components\n\nEven in a small component such as the `post.create` example we've been discussing, we end up duplicating lots of form field boilerplate like validation messages and labels.\n\nIt can be helpful to extract repetitive UI elements such as these into dedicated [Blade components](https://laravel.com/docs/blade#components) to be shared across your application.\n\nFor example, below is the original Blade template from the `post.create` component. We will be extracting the following two text inputs into dedicated Blade components:\n\n```blade\n<form wire:submit=\"save\">\n    <input type=\"text\" wire:model=\"title\"> <!-- [tl! highlight:3] -->\n    <div>\n        @error('title') <span class=\"error\">{{ $message }}</span> @enderror\n    </div>\n\n    <input type=\"text\" wire:model=\"content\"> <!-- [tl! highlight:3] -->\n    <div>\n        @error('content') <span class=\"error\">{{ $message }}</span> @enderror\n    </div>\n\n    <button type=\"submit\">Save</button>\n</form>\n```\n\nHere's what the template will look like after extracting a re-usable Blade component called `<x-input-text>`:\n\n```blade\n<form wire:submit=\"save\">\n    <x-input-text name=\"title\" wire:model=\"title\" /> <!-- [tl! highlight] -->\n\n    <x-input-text name=\"content\" wire:model=\"content\" /> <!-- [tl! highlight] -->\n\n    <button type=\"submit\">Save</button>\n</form>\n```\n\nNext, here's the source for the `x-input-text` component:\n\n```blade\n<!-- resources/views/components/input-text.blade.php -->\n\n@props(['name'])\n\n<input type=\"text\" name=\"{{ $name }}\" {{ $attributes }}>\n\n<div>\n    @error($name) <span class=\"error\">{{ $message }}</span> @enderror\n</div>\n```\n\nAs you can see, we took the repetitive HTML and placed it inside a dedicated Blade component.\n\nFor the most part, the Blade component contains only the extracted HTML from the original component. However, we have added two things:\n\n* The `@props` directive\n* The `{{ $attributes }}` statement on the input\n\nLet's discuss each of these additions:\n\nBy specifying `name` as a \"prop\" using `@props(['name'])` we are telling Blade: if an attribute called \"name\" is set on this component, take its value and make it available inside this component as `$name`.\n\nFor other attributes that don't have an explicit purpose, we used the `{{ $attributes }}` statement. This is used for \"attribute forwarding\", or in other words, taking any HTML attributes written on the Blade component and forwarding them onto an element within the component.\n\nThis ensures `wire:model=\"title\"` and any other extra attributes such as `disabled`, `class=\"...\"`, or `required` still get forwarded to the actual `<input>` element.\n\n### Custom form controls\n\nIn the previous example, we \"wrapped\" an input element into a re-usable Blade component we can use as if it was a native HTML input element.\n\nThis pattern is very useful; however, there might be some cases where you want to create an entire input component from scratch (without an underlying native input element), but still be able to bind its value to Livewire properties using `wire:model`.\n\nFor example, let's imagine you wanted to create an `<x-input-counter />` component that was a simple \"counter\" input written in Alpine.\n\nBefore we create a Blade component, let's first look at a simple, pure-Alpine, \"counter\" component for reference:\n\n```blade\n<div x-data=\"{ count: 0 }\">\n    <button x-on:click=\"count--\">-</button>\n\n    <span x-text=\"count\"></span>\n\n    <button x-on:click=\"count++\">+</button>\n</div>\n```\n\nAs you can see, the component above shows a number alongside two buttons to increment and decrement that number.\n\nNow, let's imagine we want to extract this component into a Blade component called `<x-input-counter />` that we would use within a component like so:\n\n```blade\n<x-input-counter wire:model=\"quantity\" />\n```\n\nCreating this component is mostly simple. We take the HTML of the counter and place it inside a Blade component template like `resources/views/components/input-counter.blade.php`.\n\nHowever, making it work with `wire:model=\"quantity\"` so that you can easily bind data from your Livewire component to the \"count\" inside this Alpine component needs one extra step.\n\nHere's the source for the component:\n\n```blade\n<!-- resources/view/components/input-counter.blade.php -->\n\n<div x-data=\"{ count: 0 }\" x-modelable=\"count\" {{ $attributes}}>\n    <button x-on:click=\"count--\">-</button>\n\n    <span x-text=\"count\"></span>\n\n    <button x-on:click=\"count++\">+</button>\n</div>\n```\n\nAs you can see, the only different bit about this HTML is the `x-modelable=\"count\"` and `{{ $attributes }}`.\n\n`x-modelable` is a utility in Alpine that tells Alpine to make a certain piece of data available for binding from outside. [The Alpine documentation has more information on this directive.](https://alpinejs.dev/directives/modelable)\n\n`{{ $attributes }}`, as we explored earlier, forwards any attributes passed into the Blade component from outside. In this case, the `wire:model` directive will be forwarded.\n\nBecause of `{{ $attributes }}`, when the HTML is rendered in the browser, `wire:model=\"quantity\"` will be rendered alongside `x-modelable=\"count\"` on the root `<div>` of the Alpine component like so:\n\n```blade\n<div x-data=\"{ count: 0 }\" x-modelable=\"count\" wire:model=\"quantity\">\n```\n\n`x-modelable=\"count\"` tells Alpine to look for any `x-model` or `wire:model` statements and use \"count\" as the data to bind them to.\n\nBecause `x-modelable` works for both `wire:model` and `x-model`, you can also use this Blade component interchangeably with Livewire and Alpine. Here’s an example of using this Blade component in a purely Alpine context:\n\n```blade\n<x-input-counter x-model=\"quantity\" />\n```\n\nCreating custom input elements in your application is extremely powerful but requires a deeper understanding of the utilities Livewire and Alpine provide and how they interact with each other.\n\n---\n\n## Queues Testing Testing Job Batches Testing Job / Batch Interaction\nQueues | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/queues.md\n\n\n#### Testing Job / Batch Interaction\n\nIn addition, you may occasionally need to test an individual job's interaction with its underlying batch. For example, you may need to test if a job cancelled further processing for its batch. To accomplish this, you need to assign a fake batch to the job via the `withFakeBatch` method. The `withFakeBatch` method returns a tuple containing the job instance and the fake batch:\n\n```php\n[$job, $batch] = (new ShipOrder)->withFakeBatch();\n\n$job->handle();\n\n$this->assertTrue($batch->cancelled());\n$this->assertEmpty($batch->added);\n```\n\n---\n\n## Http Tests Validation Assertions assertValid\nHttp Tests | laravel/framework@12.x | Source: https://github.com/laravel/docs/blob/12.x/http-tests.md\n\n\n#### assertValid\n\nAssert that the response has no validation errors for the given keys. This method may be used for asserting against responses where the validation errors are returned as a JSON structure or where the validation errors have been flashed to the session:\n\n```php\n// Assert that no validation errors are present...\n$response->assertValid();\n\n// Assert that the given keys do not have validation errors...\n$response->assertValid(['name', 'email']);\n```\n\n---\n\n## Validation Using custom validators\nValidation | livewire/livewire@4.x | Source: https://livewire.laravel.com/docs/4.x/validation\n\n## Using custom validators\n\nIf you wish to use your own validation system in Livewire, that isn't a problem. Livewire will catch any `ValidationException` exceptions thrown inside of components and provide the errors to the view just as if you were using Livewire's own `validate()` method.\n\nBelow is an example of the `CreatePost` component, but instead of using Livewire's validation features, a completely custom validator is being created and applied to the component properties:\n\n```php\nuse Illuminate\\Support\\Facades\\Validator;\nuse Livewire\\Component;\nuse App\\Models\\Post;\n\nclass CreatePost extends Component\n{\n\tpublic $title = '';\n\n    public $content = '';\n\n    public function save()\n    {\n        $validated = Validator::make(\n            // Data to validate...\n            ['title' => $this->title, 'content' => $this->content],\n\n            // Validation rules to apply...\n            ['title' => 'required|min:3', 'content' => 'required|min:3'],\n\n            // Custom validation messages...\n            ['required' => 'The :attribute field is required'],\n         )->validate();\n\n\t\tPost::create($validated);\n\n\t\treturn redirect()->to('/posts');\n    }\n\n    // ...\n}\n```\n\n_[Truncated]_"}]


command: sed -n '430,560p' specs/09-IMPLEMENTATION-ROADMAP.md

type: read

aggregated_output:
**File to create:** `App\Services\NavigationService`

| Method | Description |
|--------|-------------|
| `buildTree(NavigationMenu $menu): array` | Builds navigation trees from navigation_menus / navigation_items |
| `resolveUrl(NavigationItem $item): string` | Resolves URLs for page, collection, product type items |

Caches per store with 5-minute TTL.

---

### Phase 4: Cart, Checkout, Discounts, Shipping, Taxes

**Priority:** HIGH - core shopping flow.

#### Step 4.1: Migrations (Batch 4-5)

1. `create_carts_table` - FK: `store_id`, `customer_id`
2. `create_cart_lines_table` - FK: `cart_id`, `variant_id`
3. `create_checkouts_table` - FK: `store_id`, `cart_id`, `customer_id`
4. `create_shipping_zones_table` - FK: `store_id`
5. `create_shipping_rates_table` - FK: `zone_id`
6. `create_tax_settings_table` - PK: `store_id`
7. `create_discounts_table` - FK: `store_id`

#### Step 4.2: Models

**Files to create:**

| Type | Name | Purpose |
|------|------|---------|
| Model (with migration, factory, seeder) | `Cart` | Shopping cart entity |
| Model (with migration, factory, seeder) | `CartLine` | Individual cart line item |
| Model (with migration, factory, seeder) | `Checkout` | Checkout session entity |
| Model (with migration, factory, seeder) | `ShippingZone` | Shipping zone configuration |
| Model (with migration, factory, seeder) | `ShippingRate` | Shipping rate within a zone |
| Model (with migration, factory, seeder) | `TaxSettings` | Per-store tax configuration |
| Model (with migration, factory, seeder) | `Discount` | Discount code or automatic discount |

**Relationship definitions:**

| Model | Key Relationships |
|-------|-------------------|
| `Cart` | `belongsTo(Store)`, `belongsTo(Customer)`, `hasMany(CartLine)`, `hasMany(Checkout)` |
| `CartLine` | `belongsTo(Cart)`, `belongsTo(ProductVariant)` |
| `Checkout` | `belongsTo(Store)`, `belongsTo(Cart)`, `belongsTo(Customer)` |
| `ShippingZone` | `belongsTo(Store)`, `hasMany(ShippingRate)` |
| `ShippingRate` | `belongsTo(ShippingZone)` |
| `TaxSettings` | `belongsTo(Store)` |
| `Discount` | `belongsTo(Store)` |

**Enums to create:**

| Enum | Values |
|------|--------|
| `CartStatus` | `Active`, `Converted`, `Abandoned` |
| `CheckoutStatus` | `Started`, `Addressed`, `ShippingSelected`, `PaymentPending`, `Completed`, `Expired` |
| `DiscountType` | `Code`, `Automatic` |
| `DiscountValueType` | `Percent` (`percent`), `Fixed` (`fixed`), `FreeShipping` (`free_shipping`) -- PascalCase cases backed by lowercase string values stored in DB |
| `DiscountStatus` | `Draft`, `Active`, `Expired`, `Disabled` |
| `ShippingRateType` | `Flat`, `Weight`, `Price`, `Carrier` |
| `TaxMode` | `Manual`, `Provider` |

#### Step 4.3: Cart Service

**File to create:** `App\Services\CartService`

| Method | Description |
|--------|-------------|
| `create(Store, ?Customer): Cart` | Creates cart with store currency, version 1 |
| `addLine(Cart, int $variantId, int $qty): CartLine` | Validates variant/product active, inventory, increments existing line or creates new |
| `updateLineQuantity(Cart, int $lineId, int $qty): CartLine` | Validates quantity, recalculates amounts |
| `removeLine(Cart, int $lineId): void` | Deletes line, increments version |
| `getOrCreateForSession(Store, ?Customer): Cart` | Session-based cart binding |
| `mergeOnLogin(Cart $guest, Cart $customer): Cart` | Merges guest cart into customer cart |

All mutations increment `cart_version`. API clients must send `expected_version` or receive 409 Conflict.

#### Step 4.4: Discount Service

**File to create:** `App\Services\DiscountService`

| Method | Description |
|--------|-------------|
| `validate(string $code, Store $store, Cart $cart): Discount` | Validates code exists, is active, dates valid, usage limit not reached, minimum purchase met |
| `calculate(Discount $discount, int $subtotal, array $lines): DiscountResult` | Calculates amount, allocates proportionally across qualifying lines |

Case-insensitive code lookup. Throws `InvalidDiscountException` with specific reason codes.

#### Step 4.5: Shipping Calculator

**File to create:** `App\Services\ShippingCalculator`

| Method | Description |
|--------|-------------|
| `getAvailableRates(Store $store, array $address): Collection` | Matches zones by country/region, returns active rates |
| `calculate(ShippingRate $rate, Cart $cart): int` | Calculates cost based on rate type (flat/weight/price) |

Zone matching: checks `countries_json` for country code, then `regions_json` for region code.

#### Step 4.6: Tax Calculator

**File to create:** `App\Services\TaxCalculator`

| Method | Description |
|--------|-------------|
| `calculate(int $amount, TaxSettings $settings, array $address): TaxResult` | Calculates tax per manual rate or provider |
| `extractInclusive(int $grossAmount, int $rateBasisPoints): int` | Extracts tax from gross (prices-include-tax mode) |
| `addExclusive(int $netAmount, int $rateBasisPoints): int` | Adds tax to net amount |

All math uses integers. Rates stored in basis points (1900 = 19%).

#### Step 4.7: Pricing Engine

**File to create:** `App\Services\PricingEngine`

Method: `calculate(Checkout $checkout): PricingResult`

**Pipeline steps:**
1. Line subtotals: `unit_price * quantity` per line
2. Cart subtotal: sum of line subtotals
3. Discount: apply rules, allocate proportionally
4. Discounted subtotal: subtotal minus discount
5. Shipping: based on selected method/rate
6. Tax: on discounted amounts (plus shipping if taxable)
7. Total: discounted_subtotal + shipping + tax_total

Result stored in `checkouts.totals_json` as snapshot.

**Value objects to create:**

status: completed