milenmk / laravel-route-label
Add label support to Laravel routes with routeLabel() helper and Blade @routeLink directive
Installs: 7
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/milenmk/laravel-route-label
Requires
- php: ^8.2|^8.3|^8.4
- illuminate/routing: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
- illuminate/view: ^10.0|^11.0|^12.0
Requires (Dev)
- brianium/paratest: ^7.9
- laravel/pint: ^1.13
- orchestra/testbench: ^10.2
- phpunit/phpunit: ^12.1
- squizlabs/php_codesniffer: ^3.11
- tightenco/duster: ^3.1
Conflicts
- laravel/framework: <10.0
README
A tiny Laravel package that lets you attach human‑friendly labels to your routes and use them in views via a helper or a Blade directive.
- Route macro:
->label('My Label')(supports string‑backed Enums) - Localizing the label You can also pass a translatable string
->label(__('MyLabel'))or key->label(__('routes.home'))for a label - Helper:
routeLabel('route.name')→ label or route name fallback - Blade directive:
@routeLink('route.name')→<a href="/...">Label</a> - Extended Blade directive:
@routeLink('route.name', ['class' => 'btn', 'wire:navigate' => true])→ enhanced<a>tag with custom attributes - Block Blade directives:
@routeLinkStart('route.name', ['attributes'])...@routeLinkEnd→ for complex link content - Blade component:
<x-route-link route="route.name" />
Requirements
- PHP: 8.2, 8.3, 8.4
- Laravel: 10.x, 11.x, 12.x (Illuminate Support/View/Routing)
Installation
composer require milenmk/laravel-route-label
No further setup is needed (package discovery enabled).
Quick Start
1) Define routes with labels
use Illuminate\Support\Facades\Route; // Simple string label Route::get('/users', [UserController::class, 'index']) ->name('users.index') ->label('Users'); // Dynamic label via closure Route::get('/users/{user}/edit', [UserController::class, 'edit']) ->name('users.edit') ->label(fn($params) => "Edit {$params['user']->name}"); // Translation key Route::get('/home', [HomeController::class, 'index']) ->name('home') ->label('trans:routes.home'); // String-backed Enum enum RouteLabel: string { case Users = 'Users'; } Route::get('/users', [UserController::class, 'index']) ->name('users.index') ->label(RouteLabel::Users);
You must call
->name()before->label().
2) Use the label in Blade
Using the helper
<a href="{{ route('users.index') }}">{{ routeLabel('users.index') }}</a>
<a href="{{ route('users.edit', ['user' => $user]) }}">{{ routeLabel('users.edit', ['user' => $user]) }}</a>
Renders
<a href="/users">Users</a> <a href="/users/1/edit">Edit John</a>
Using Blade directives
-
Simple directive
@routeLink('users.index')
Renders:
<a href="/users">Users</a>
-
With additional attributes
@routeLink('users.index', ['class' => 'btn btn-primary', 'wire:navigate' => true])
Renders:
<a href="/users" class="btn btn-primary" wire:navigate>Users</a>
-
With Alpine.js / complex attributes
@routeLink('users.index', [ 'class' => 'menu-item', 'x-data' => '{ open: false }', 'x-show' => 'open', '@click' => 'open = !open' ])
Renders:
<a href="/users" class="menu-item" x-data="{ open: false }" x-show="open" @click="open = !open">Users</a>
Block directives for complex content
@routeLinkStart('home', ['class' => 'logo-link', 'wire:navigate' => true]) <img class="logo" src="{{ asset('images/logo.png') }}" alt="Logo" /> <span class="brand-name">{{ config('app.name') }}</span> @routeLinkEnd
Renders
<a href="/" class="logo-link" wire:navigate> <img class="logo" src="/images/logo.png" alt="Logo" /> <span class="brand-name">My App</span> </a>
Another example with Alpine.js
@routeLinkStart('profile', [ 'class' => 'profile-link', 'x-data' => '{ open: false }', '@click' => 'open = !open' ]) <img class="avatar" src="{{ $user->avatar }}" alt="Profile" /> <span class="name">{{ $user->name }}</span> <svg class="dropdown-icon" :class="open ? 'rotate-180' : ''">...</svg> @routeLinkEnd
Renders
<a href="/profile" class="profile-link" x-data="{ open: false }" @click="open = !open"> <img class="avatar" src="/avatar.jpg" alt="Profile" /> <span class="name">John Doe</span> <svg class="dropdown-icon">...</svg> </a>
3) Using the Blade component
<x-route-link route="users.index" class="btn btn-primary" /> <x-route-link route="users.edit" :params="['user' => $user]" /> <x-route-link route="home" /> <x-route-link route="users.index" :attributes="['wire:navigate' => true]" />
Renders
<a href="/users" class="btn btn-primary">Users</a> <a href="/users/1/edit" class="text-blue-500 hover:underline">Edit John</a> <a href="/" class="text-blue-500 hover:underline">Homepage</a> <a href="/users" class="text-blue-500 hover:underline" wire:navigate>Users</a>
Boolean attributes (like
wire:navigate) are added as attribute names only when set totrue.HTML is escaped by default, configurable via
config/route-label.php.Fallbacks: if a route has no label, the route name is used (
missing_label_behavior).
Enum Support
You can use string-backed Enums for labels:
enum RouteLabel: string { case Users = 'Users'; } Route::get('/users', [UserController::class, 'index']) ->name('users.index') ->label(RouteLabel::Users);
For route names (Laravel expects a string), pass the enum value:
enum RouteName: string { case UsersIndex = 'users.index'; } Route::get('/users', [UserController::class, 'index']) ->name(RouteName::UsersIndex->value) ->label('Users');
The
@routeLink()directive expects a string route name (not an Enum), because it internally callsroute().
Helper Reference
routeLabel(string|BackedEnum $name): ?string- Returns the route label if set.
- Returns the route name when no label is set.
- Returns
nullif the route does not exist.
Usage examples:
routeLabel('users.index'); // "Users" (if labeled), otherwise "users.index" routeLabel(RouteName::UsersIndex); // Works with string-backed Enum
In Blade:
{{ routeLabel('users.index') ?? 'Unknown route' }}
Configuration (Optional / Advanced)
Publish the config to customize defaults:
php artisan vendor:publish --tag=route-label-config
- default_link_class → default CSS class for the Blade component
- escape_html → whether labels are escaped (true by default)
- missing_label_behavior → controls fallback when a label is missing
Basic usage does not require publishing the config.
Errors and Edge Cases
- Calling
->label()before->name()will throw aLogicException. - Passing a non string‑backed Enum to
->label()will throw anInvalidArgumentException. - Unknown routes:
routeLabel()returnsnull→ use the null coalescing operator to provide a fallback.
Why use route labels?
- Consistency: keep link texts centralized alongside routes.
- Localization friendly: prepare for i18n by mapping names to labels.
- Cleaner views: no more hard‑coded strings scattered in templates.
- Dynamic content: closures allow runtime-generated labels (e.g., usernames).
Changelog
Please see CHANGELOG.md for recent changes.
Contributing
- Pull requests and issues are welcome at GitHub.
- Follow PSR‑12 requirements
Support My Work
If this package saves you time, you can support ongoing development:
👉 Become a Patron
Other Packages
Check out my other Laravel packages:
- Laravel GDPR Cookie Manager - GDPR-compliant cookie consent management with user preference tracking
- Laravel Email Change Confirmation - Secure email change confirmation system
- Laravel Blacklist - A Laravel package for blacklist validation of user input
- Laravel GDPR Exporter - GDPR-compliant data export functionality
- Laravel Locations - Add Countries, Cities, Areas, Languages and Currencies models to your Laravel application
- Laravel Rate Limiting - Advanced rate limiting capabilities with exponential backoff
- Laravel Datatables and Forms - Easy to use package to create datatables and forms for Livewire components
License
This package is licensed under the MIT License. See the LICENSE file for details.
Disclaimer
This package is provided "as is", without warranty of any kind, express or implied, including but not limited to warranties of merchantability, fitness for a particular purpose, or noninfringement. The author(s) make no guarantees regarding the accuracy, reliability, or completeness of the code, and shall not be held liable for any damages or losses arising from its use. Please ensure you thoroughly test this package in your environment before deploying it to production.