Panels
Command Line
The artisan commands that write a resource, its pages, a page of your own and a relationship's table — and the one that reads back what is registered.
On this page
Everything a panel is made of can be written by hand, and every command here
writes exactly what the pages expect — so the first file is right and the rest
is yours. None of them edits a file you already have unless you pass --force.
Generating A Resource
php artisan make:wire-resource Order
writes the resource and the three pages an ordinary resource has:
app/Resources/OrderResource.phpapp/Livewire/Resources/Orders/ListOrders.phpapp/Livewire/Resources/Orders/CreateOrder.phpapp/Livewire/Resources/Orders/EditOrder.php
The resource declares its pages(), so once it is registered and
Route::wireResources() runs in your panel's route group, its URLs exist. The
edit page is written with $this->deleteHeaderAction() in its header — the one
default the pages leave to you, because who may delete what is your rule
(Pages).
| Option | What it changes |
|---|---|
--model=App\Domain\Order |
The model, when it is not App\Models\{Name} |
--generate |
Fields, columns and infolist entries read off the model's table |
--view |
A read-only ViewPage and an infolist() on the resource |
--simple |
One ManagePage instead of three pages |
--soft-deletes |
ManagesTrashedRecords, and Restore / Force delete in the record pages' headers |
--register |
Adds the class to a published config/wire-core.php |
--force |
Overwrites files that already exist |
--generate reads the table, not the model. Each column becomes a field, a
column and an entry by its type — a boolean a Toggle and a BooleanColumn, a
date a DateTimePicker::make()->asDate() and a ->date() column, a text column
a Textarea, a number ->numeric(), anything else a TextInput — and a column
that is neither nullable nor defaulted is required(). The key, the timestamps,
deleted_at and credentials are left out. It is a starting point written once:
a table that does not exist yet writes the resource without generated lines
and says so, rather than failing.
It ends by saying where the pages are, or what is missing. It reads the
application as it is: whether the resource is registered — listed in
config('wire-core.resources'), just added with --register, or inside a
folder config('wire-core.discover.resources') names — and whether anything
routes registered classes — a route file calling Route::wireResources(), or
a panel entry of wire-core.routes.groups. With
both in place it prints Ready: registered and routed at /admin/order-lines;
otherwise it names only the step that is missing, written out for this
resource. make:wire-page does the same for a page of your own.
--register only writes where it can do so safely — into a published
config/wire-core.php that has a resources list, and only once. Anywhere else
it prints the line to add.
Generating A Page Of Your Own
php artisan make:wire-page TaskBoardphp artisan make:wire-page History --resource=Order
The first writes a Page and the view it draws —
app/Livewire/Pages/TaskBoard.php and
resources/views/livewire/pages/task-board.blade.php. The second writes a page
about one record of OrderResource: it composes BelongsToResource,
ResolvesOneRecord and LinksToRecordPages, so it takes the record's key and
draws the record's tabs. The command prints what is left to do: a page of its own
is registered like a resource — config('wire-panels.pages')
or a discovered folder — and is then routed and listed by itself; a record page
is routed from its resource's pages():
'history' => RoutePage::make(\App\Livewire\Resources\Orders\History::class)->uri('{record}/history'),
— which is also what makes it one of the record's tabs. Routing is the owner's declaration, so the command prints it rather than editing the resource.
Generating A Cluster
php artisan make:wire-cluster Settingsphp artisan make:wire-page Taxes --cluster=Settings
The first writes app/Clusters/Settings.php, a cluster — one
section with one menu entry and one URL prefix — and says how to register it,
which is the way a page is registered. The second writes a page that is a member
of it: the page names the cluster with protected static ?string $cluster. A
resource joins by implementing BelongsToCluster, one method, written by hand.
Generating A Relationship's Table
php artisan make:wire-relation-manager Order items
writes app/Livewire/Resources/Orders/ItemsRelationManager.php, a
RelationManager over the items relationship
with a table to fill in, and prints how to embed it: have the resource implement
ProvidesRelationManagers and return the class from relationManagers().
Reading Back What Is Registered
php artisan wire:resourcesphp artisan wire:resources orders
The first lists every registered resource — its key, class, model, the surfaces
it declares, its pages and how many routes they have. The second shows one
resource page by page: the component, every route that reaches it (a page
routed in two zones is two rows), its URI and the permission it requires, or
not routed. Both read the catalogue and the router — the same answers the
menu, the palette and Route::wireResources() work from — so what it prints is
what the application actually has.
Changing What They Write
php artisan vendor:publish --tag=wire-panels::stubs
copies the templates to stubs/wire-panels/, and every command here reads a
published template before its own: resource.stub, resource-page.stub,
page.stub, page-view.stub, relation-manager.stub and
dashboard-page.stub.
Generating A Component
The parts a table, a form or an infolist is built from have generators of their own, in the package that owns each one — so they exist without a panel too:
| Command | Writes | Package |
|---|---|---|
make:wire-column Price |
app/Tables/Columns/PriceColumn.php + its cell view |
wire-table — custom column |
make:wire-filter Region |
app/Tables/Filters/RegionFilter.php + its control view |
wire-table — custom filter |
make:wire-field MoneyInput |
app/Forms/Components/MoneyInput.php + its input view |
wire-forms — custom field |
make:wire-entry Money |
app/Infolists/Components/MoneyEntry.php + its view |
wire-core — custom entry |
make:wire-action Archive [--bulk] |
app/Wire/Actions/ArchiveAction.php |
wire-core — preset action |
make:wire-widget Revenue |
app/Widgets/RevenueWidget.php + its view |
wire-core — widgets |
Each adds its suffix unless the name already ends with it (a field takes none),
never overwrites a view that exists, and replaces the class only with --force.
Each package publishes its own templates — --tag=wire-table::stubs,
wire-forms::stubs, wire-core::stubs — into stubs/<package>/.