Skip to content

Tableaux et colonnes ​

Les colonnes définissent ce qui s'affiche dans la liste d'un Resource. Elles se déclarent dans columns() :

php
public function columns(): array
{
    return [
        Column::make('title')->sortable()->searchable(),
        Column::make('is_published')->as('boolean')->sortable(),
        Column::make('published_at')->as('date')->displayFormat('d/m/Y')->sortable(),
        Column::make('status')
            ->as('badge')
            ->value(fn (Post $post): string => $post->is_published ? 'Published' : 'Draft')
            ->color(fn (Post $post): string => $post->is_published ? 'success' : 'gray'),
    ];
}

L'API de Column ​

MéthodeDescription
make(string $name)Le nom de l'attribut sur le modèle Eloquent (ou le nom logique, si vous utilisez value()).
label(string $label)Libellé de l'en-tête. Par défaut, Str::headline($name).
as(string $type)Comment la cellule est affichée côté frontend : text (par défaut), boolean, date, badge…
sortable(bool $sortable = true)Permet de trier la liste par cette colonne.
hiddenByDefault(bool $hidden = true)Masquée par défaut ; l'utilisateur peut l'afficher depuis le sélecteur de colonnes et choisir l'ordre depuis la liste elle-même.
displayFormat(string $format)Format d'affichage quand as('date') (syntaxe date() de PHP).
value(Closure $callback)Remplace la valeur de la cellule par une valeur calculée. Reçoit le modèle complet, pas seulement l'attribut.
color(Closure $callback)Couleur de la cellule (pertinente surtout pour as('badge')). Reçoit le modèle complet.
circular(bool $circular = true)Affiche la valeur d'une colonne as('image') comme un avatar circulaire. Sans effet sur les autres types.
url(Closure $callback)Résout un lien par ligne. Reçoit le modèle et retourne l'URL, ou null pour laisser cette ligne sans lien.
searchable(bool $searchable = true, ?Closure $using = null, ?Closure $refine = null)Inclut la colonne dans la recherche en texte libre de la liste. Avec using, remplace le LIKE par défaut, et avec refine, affine le résultat en PHP (voir « Recherche sur mesure »).

Une colonne as('boolean') s'affiche comme une icône (✓/✗), pas comme le texte « Yes »/« No » codé en anglais.

Colonnes avec image et lien ​

php
Column::make('cover_path')
    ->as('image')
    ->circular()
    ->url(fn (Post $post): ?string => $post->cover_path === null ? null : "/storage/{$post->cover_path}")
    ->hiddenByDefault()

Le callback de url() reçoit l'enregistrement Eloquent et retourne le lien. Le résultat est ajouté à chaque ligne sous la forme {colonne}_url, de la même manière que la couleur résolue d'une colonne badge est ajoutée sous la forme {colonne}_color, il n'est pas servi comme propriété du schema, il est calculé par ligne.

Recherche sur mesure ​

Par défaut, searchable() compare le terme de recherche de l'index à la colonne avec un simple LIKE. Passez-lui using pour les colonnes qui ne se comparent pas ainsi, une colonne virtuelle, ou une colonne chiffrée :

php
Column::make('author')
    ->value(fn (Post $post): ?string => $post->author?->name)
    ->searchable(using: fn (Builder $query, string $term): Builder => $query->whereHas(
        'author',
        fn (Builder $author) => $author->where('name', 'like', "%{$term}%")
    ))

La closure reçoit un nouveau query builder imbriqué et le terme de recherche brut ; elle doit modifier le builder qu'elle reçoit au lieu d'en retourner un autre, car le where(Closure) de Laravel écarte ce que vous retournez.

Recherches que SQL ne peut que resserrer ​

Une colonne chiffrée, par exemple, ne se compare pas avec LIKE, mais peut être indexée par un préfixe. Avec refine, using ne fait que resserrer les candidats et refine décide en PHP lesquels correspondent :

php
Column::make('name')->searchable(
    using: fn (Builder $query, string $term): Builder => $query->where('name_index', 'like', mb_substr($term, 0, 3).'%'),
    refine: fn (Student $student, string $term): bool => str_contains(mb_strtolower($student->name), mb_strtolower($term)),
)

using s'exécute en SQL et donne au plus 500 candidats. refine reçoit chaque candidat et le terme, et retourne s'il correspond. Les candidats retenus sont combinés avec les autres colonnes recherchables de la liste.

Colonnes calculées ​

value() et color() reçoivent l'enregistrement Eloquent entier, pas un simple $record->$name : une colonne « logique » qui ne correspond à aucun attribut est aussi valide qu'une colonne directe. L'exemple status ci-dessus ne lit aucune colonne status de la base de données, il la calcule à partir de is_published.

php
Column::make('status')
    ->as('badge')
    ->value(fn (Post $post): string => $post->is_published ? 'Published' : 'Draft')
    ->color(fn (Post $post): string => $post->is_published ? 'success' : 'gray')

Vue en lecture seule ​

Quand un Resource a une ViewAction, Arrel réutilise columns() pour afficher la vue de détail de l'enregistrement, avec les mêmes as(), value() et color() de chaque colonne. Pour les regrouper en sections titrées, déclarez infolist(). Une entrée vide s'affiche sous la forme d'un tiret.