Skip to content

Accions ​

Les accions són el que es pot fer amb un registre (o amb el Resource sencer). Es declaren dins d'actions():

php
public function actions(): array
{
    return [
        ViewAction::make(),
        EditAction::make(),
        DeleteAction::make()->bulk(),
        RestoreAction::make(),
        ForceDeleteAction::make(),

        Action::make('publish')
            ->icon('check')
            ->requiresConfirmation()
            ->bulk()
            ->handle(function (array $data, Post $post): array {
                $post->update(['is_published' => true]);

                return $post->only(['id', 'title', 'is_published']);
            }),

        Action::make('purge_drafts')
            ->label('Purge drafts')
            ->icon('trash')
            ->standalone()
            ->requiresConfirmation()
            ->handle(function (array $data): array {
                return ['deleted' => Post::where('is_published', false)->delete()];
            }),
    ];
}

API de Action ​

MètodeDescripció
make(string $name)Nom intern de l'acció (apareix a la URL de l'endpoint).
label(string $label)Etiqueta al botó. Per defecte, Str::headline($name).
icon(string $icon)Nom d'icona (vegeu «Icones» més avall).
standalone(bool = true)Acció sobre el Resource sencer, no sobre un registre concret (per exemple, «Purge drafts»).
bulk(bool = true)Es pot aplicar a una selecció de diversos registres a la vegada; reutilitza el mateix endpoint per-registre, no hi ha una API bulk separada.
requiresConfirmation(bool = true)El frontend demana confirmació abans d'executar-la.
withTrashed(bool = true)L'acció opera sobre registres amb soft delete (necessari per a restore/forceDelete).
authorize(Closure $callback)Decideix si l'acció és visible i executable. Rep els mateixos arguments que handle(). Vegeu «Autorització».
schema(array<Field> $fields)Camps d'un formulari propi de l'acció. Vegeu «Accions amb formulari».
url(Closure $callback, bool $openInNewTab = false)Converteix l'acció en un enllaç. Vegeu «Accions que són un enllaç».
handle(Closure $callback)La lògica de l'acció. Rep (array $data, Model $record) per a accions sobre un registre, o només (array $data) per a standalone().

Autorització ​

  • Amb authorize(), l'acció fa servir aquest closure i res més.
  • Sense authorize(), l'acció exigeix canEdit() sobre el registre, o canCreate() si és standalone(). Una acció que ha de ser oberta a usuaris que no poden editar ha de declarar authorize() explícitament.
  • Les accions incloses segueixen la seva habilitat: ViewAction amb canView(), EditAction i RestoreAction amb canEdit(), DeleteAction i ForceDeleteAction amb canDelete(). Si declares authorize() a una d'elles, s'han de complir les dues condicions.
  • Un Resource que l'usuari no pot llistar (canViewAny() fals) tanca totes les seves accions.

Accions amb formulari ​

schema() demana dades a l'usuari abans d'executar l'acció. Un standalone() amb schema() obre el formulari sense cap registre:

php
Action::make('invite')
    ->label('Invite people')
    ->icon('paper-airplane')
    ->standalone()
    ->schema([
        Tags::make('emails')
            ->itemRules('email')
            ->rules('required', 'array'),
        Select::make('role')
            ->options(['editor' => 'Editor', 'viewer' => 'Viewer'])
            ->rules('required'),
    ])
    ->handle(function (array $data): array {
        Invitations::send($data['emails'], $data['role']);

        return ['message' => count($data['emails']).' invitations sent'];
    })

handle() rep les dades ja validades contra les regles dels camps. Els errors de validació surten amb l'etiqueta del camp, no amb el seu nom intern. Els camps Relation d'una acció serveixen les seves opcions només als usuaris que poden executar-la, i el seu query() s'aplica també en enviar el formulari.

Missatges de l'acció ​

Si el handler retorna un array amb una clau message de tipus text, el panell el mostra a l'usuari un cop feta l'acció. La resta de claus es retornen al frontend tal qual. Un handler que no retorna res respon { "success": true }.

Accions que són un enllaç ​

Amb url(), una acció no executa cap handler: navega. El closure rep el registre i retorna la URL, o null per no mostrar l'acció en aquella fila.

php
Action::make('open_public')
    ->label('Open public page')
    ->icon('eye')
    ->url(fn (Post $post): ?string => $post->is_published ? route('posts.show', $post) : null, openInNewTab: true)

Accions incloses ​

ViewAction, EditAction, DeleteAction, RestoreAction i ForceDeleteAction són Action amb una icona (i, per a les dues últimes, withTrashed()/requiresConfirmation()) predefinides:

php
ViewAction::make();        // icona 'eye'
EditAction::make();        // icona 'pencil'
DeleteAction::make();      // icona 'trash'
RestoreAction::make();     // icona 'arrow-uturn-left', withTrashed()
ForceDeleteAction::make(); // icona 'trash', withTrashed(), requiresConfirmation()

DeleteAction, RestoreAction i ForceDeleteAction reben un handler per defecte si no en declares cap: esborrar/restaurar/forçar l'esborrat del registre via Eloquent (respectant SoftDeletes quan el model el fa servir). Només cal cridar handle() explícitament quan vulguis substituir aquest comportament.

Bloquejar un esborrat des del model: si un listener de l'esdeveniment deleting del teu model llança un RuntimeException (per exemple, «encara té dependents»), l'endpoint d'esborrat el captura i respon 422 amb el missatge de l'excepció, en lloc d'un 500 sense cos que el frontend no pugui mostrar. És el mateix patró que fa servir Filament amb DeleteAction::configureUsing().

php
protected static function booted(): void
{
    static::deleting(function (AcademicYear $year): void {
        if ($year->courses()->exists()) {
            throw new RuntimeException('Aquest curs encara té assignatures.');
        }
    });
}

AttachAction i DetachAction són específiques dels Relation managers; s'hi expliquen en detall.

Icones ​

icon() pren un nom d'un subconjunt curat de Heroicons que Arrel ja porta embegut. No és tot Heroicons: només les icones que Arrel fa servir a les seves pròpies accions, widgets i navegació, per no pagar mida de bundle per icones que cap panell utilitza.

eye, trash, pencil, pencil-square, check, plus, plus-circle, x-mark, inbox, paper-airplane, key, envelope-open, arrow-uturn-left, document-text, home, arrow-right-on-rectangle, academic-cap, book-open, shield-check, squares-2x2, user-group, users, clipboard-document-check, bars-3, cog-6-tooth, chart-bar, calendar-days, calendar, chat-bubble-left-right, document-duplicate, information-circle, clock, user, exclamation-triangle, arrow-down-tray i bell.

Un nom fora d'aquesta llista no es renderitza. Les icones són de resources/js/support/icons.ts al paquet.

Accions estàndard vs. accions a mida ​

ViewAction/EditAction/DeleteAction no fan res de màgic: són Action amb valors per defecte convenients. Qualsevol acció a mida es defineix exactament igual, amb el seu propi schema() i handle():

php
Action::make('rename')
    ->icon('pencil-square')
    ->schema([
        Text::make('title')->rules('required', 'string', 'max:255'),
    ])
    ->handle(function (array $data, Post $post): array {
        $post->update(['title' => $data['title']]);

        return $post->only(['id', 'title']);
    })