Configuration d'un Panel
Un Panel est l'unité d'intégration d'Arrel : il regroupe les Resources, les pages et les widgets que vous voulez exposer sous une URL, avec sa propre marque. Une application peut en enregistrer plusieurs (par exemple, un panneau admin et un panneau branded-demo avec des couleurs différentes pour un client précis).
Enregistrer un Panel
Il s'enregistre auprès du singleton PanelRegistry que le ServiceProvider d'Arrel lie déjà, normalement depuis le boot() d'un ServiceProvider propre à votre application :
use Arrel\Panels\Panel;
use Arrel\Panels\PanelRegistry;
public function boot(PanelRegistry $panels): void
{
$panels->register(
Panel::make('admin')
->resources([
PostResource::class,
])
->pages([
SiteSettingsPage::class,
])
->customPages([
CustomPage::make('about', 'About'),
])
->widgets([
Widget::make('total_posts')
->label('Total Posts')
->value(fn (): int => Post::count()),
])
);
}Panel::make($id) prend l'identifiant qui apparaîtra dans l'URL. Les méthodes resources(), pages(), widgets() et customPages() sont toutes facultatives et se combinent librement. Demander un panneau qui n'est pas enregistré répond 404.
Préfixe et panneaux
Par défaut, le panneau admin se trouve à /arrel/admin. On peut le changer dans config/arrel.php :
return [
'prefix' => 'arrel',
'panels' => [],
'middleware' => [],
'authenticated_middleware' => [],
'extra_scripts' => [],
];| Clé | Description |
|---|---|
prefix | Premier segment de l'URL de la SPA : /{prefix}/{panel}. Peut être n'importe quelle chaîne, ou vide. |
panels | Liste des identifiants de panneau. Nécessaire uniquement quand le prefix est vide. |
middleware | Middleware exécuté avant l'authentification. Voir Middleware. |
authenticated_middleware | Middleware exécuté après l'authentification. |
extra_scripts | URLs de scripts chargés dans tous les panneaux. Voir Scripts et feuilles de style. |
Un panneau à la racine du domaine nécessite le préfixe vide et la liste de ses identifiants, pour qu'Arrel ne réponde qu'à ceux-ci et n'avale pas le reste des routes de l'application :
'prefix' => '',
'panels' => ['admin'],Ainsi, le panneau admin se trouve à /admin. L'API reste sous /arrel/api/{panel}/..., quel que soit le préfixe.
Pour construire l'URL d'une page du panneau depuis votre code, utilisez Arrel\Support\PanelUrl :
use Arrel\Support\PanelUrl;
PanelUrl::to('admin', 'posts'); // "/arrel/admin/posts"Votre propre marque
Panel::make('branded-demo')
->brandName('Branded Demo')
->logo('/images/branded-demo-logo.svg')
->colors(['brand' => '#2E7D32', 'brand-strong' => '#1B5E20'])
->resources([PostResource::class]);brandName(), logo() et colors() sont exposés au frontend via window.Arrel (nom de la marque dans le <title> et dans l'interface, logo, et les tokens de couleur qui remplacent la palette par défaut). Sans brandName(), le panneau s'appelle « Arrel ».
Pour une typographie propre, fonts() et stylesheet() fonctionnent comme colors() mais pour les familles de polices :
Panel::make('branded-demo')
->fonts(['sans' => '"Poppins", sans-serif'])
->stylesheet('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&display=swap');fonts() remplace les tokens de famille de police (sans, display...) comme colors() le fait pour ceux de couleur. stylesheet() charge une feuille de style externe (typiquement un lien Google Fonts) dans le <head>, avant le CSS propre d'Arrel, pour que le @font-face soit déjà enregistré quand il le faut.
Thème
Panel::make('admin')->theme('light');theme() accepte auto (par défaut, suit le système), light ou dark. Toute autre valeur lève une InvalidArgumentException.
Pied de page
Panel::make('admin')->footer(fn (): array => [
'text' => '© '.now()->year.' Acme',
'links' => [
['label' => 'Cookies', 'url' => '/cookies'],
],
]);footer() prend un tableau, ou une closure qui en retourne un, avec text et une liste de links. Il s'affiche sous toutes les pages du panneau.
Textes de l'interface
Les textes de l'interface (boutons, états, écrans de sécurité...) sont en anglais. On peut les traduire avec translations(), qui prend un tableau clé => texte ou une closure qui en retourne un. La closure est évaluée à chaque requête, elle peut donc dépendre de la langue active :
Panel::make('admin')->translations(fn (): array => (array) __('arrel'));Les clés qu'Arrel reconnaît sont :
save, cancel, remove, saved, loading, search_placeholder, searching, no_results, clear_filters, select_all, clear_selection, sign_in, sign_out, dashboard, email, password, invalid_credentials, something_went_wrong, any, new_prefix, edit_prefix, main_navigation, active, all_with_trashed, trashed_only, selected_suffix, columns, select_row_prefix, home, date_placeholder, today, clear, previous_month, next_month, two_factor_code, two_factor_code_hint, verify, use_another_account, security, two_factor_title, two_factor_on, two_factor_off, two_factor_required, two_factor_enable, two_factor_disable, two_factor_scan, two_factor_secret, two_factor_confirm, recovery_codes_title, recovery_codes_hint, continue, two_factor_disable_hint, verify_email_title, verify_email_hint, verify_email_send, verify_email_resend, verify_email_sent, verify_email_continue, verify_email_pending, notifications, mark_all_as_read et no_notifications.
Une clé que vous ne déclarez pas conserve son texte par défaut.
Les messages d'erreur générés par le serveur (connexion, second facteur, vérification de l'e-mail) et les noms des actions intégrées sont des traductions Laravel sous le namespace arrel::, et peuvent être remplacés avec des fichiers dans lang/vendor/arrel.
Page de profil et page d'accueil
Panel::make('admin')
->profile(AccountPage::class)
->home(fn (): ?string => auth()->user()?->is_teacher ? PanelUrl::to('admin', 'custom/pass-list') : null);profile()prend unePageet en fait le lien de profil de l'utilisateur dans la barre latérale. Elle n'est affichée que si lecanView()de la page est vrai.home()prend une closure qui retourne la route où l'utilisateur doit atterrir en ouvrant le panneau (au chargement, ou en venant de la connexion ou de la page de sécurité). Avecnull, ou une valeur vide, l'utilisateur atterrit sur le dashboard. La closure est évaluée par utilisateur, chacun peut donc avoir sa page d'accueil.
Scripts et feuilles de style
Pour charger le JavaScript de vos pages personnalisées, il y a deux voies :
Panel::make('admin')
->scripts(fn (): array => [Vite::asset('resources/js/arrel/pages.ts')])
->stylesheets(fn (): array => [Vite::asset('resources/css/arrel.css')]);scripts() ajoute <script type="module"> après arrel.js, et stylesheets() ajoute <link rel="stylesheet"> après le CSS d'Arrel. Les deux prennent un tableau d'URLs ou une closure qui en retourne un, et sont par panneau. config('arrel.extra_scripts') fait la même chose pour tous les panneaux.
Authentification et sécurité
Tout ce qui concerne Sanctum, la vérification de l'e-mail, le second facteur et les notifications se trouve dans Authentification. L'autorisation et les limites de tentatives, dans Sécurité et autorisation.
Middleware
config('arrel.middleware') est ajouté, dans l'ordre, avant le middleware propre d'Arrel sur toutes les routes web et API. C'est le point d'entrée pour tout ce que votre application doit résoudre avant qu'Arrel ne consulte quoi que ce soit. Le cas le plus courant est le multi-tenancy :
// config/arrel.php
'middleware' => [
\App\Http\Middleware\IdentifyTenant::class,
],config('arrel.authenticated_middleware') s'exécute après qu'Arrel a déjà résolu l'utilisateur, et après la vérification de l'e-mail et le second facteur. middleware s'exécute avant que Sanctum ne résolve la session, il ne voit donc pas encore d'utilisateur authentifié : tout ce qui en a besoin doit aller dans authenticated_middleware.
// config/arrel.php
'authenticated_middleware' => [
\App\Http\Middleware\RecordLastSeen::class,
],L'ordre complet des routes de l'API est :
[
...config('arrel.middleware'),
ForceJsonResponse::class,
EnsureFrontendRequestsAreStateful::class,
'web',
'auth:sanctum',
EnsureEmailIsVerified::class,
EnsureTwoFactorIsSetUp::class,
...config('arrel.authenticated_middleware'),
]Les endpoints des pages personnalisées que vous écrivez dans votre application doivent utiliser cette même pile, car ils héritent des mêmes garanties (voir Pages personnalisées).
Étape suivante
Une fois le Panel enregistré, définissez votre premier Resource.