glhd / gretel
Requires
- illuminate/routing: ^8|^9|^10|^11|12.x-dev|dev-master
- illuminate/support: ^8|^9|^10|^11|12.x-dev|dev-master
- illuminate/view: ^8|^9|^10|^11|12.x-dev|dev-master
- laravel/serializable-closure: ^1.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- mockery/mockery: ^1.3
- orchestra/testbench: ^6.24|^7.10|^8|^9|9.x-dev|10.x-dev|dev-master
- phpunit/phpunit: ^9.5|^10.5
README
Gretel
像童话故事一样的Laravel面包屑。
Gretel是一个Laravel包,用于向您的应用程序添加基于路由的面包屑。
- 定义面包屑
- 显示面包屑
- 使用您选择的CSS框架与Gretel
- 使用自定义模板(同时保持可访问性)
- 缓存面包屑(如果使用
route:cache
则是必需的) - 处理错误
- 与第三方包集成(Inertia.js)
安装
composer require glhd/gretel
用法
定义面包屑
Gretel添加了一个新的路由宏,您可以在定义路由时使用它
单个面包屑
在简单的情况下,将 breadcrumb()
函数链到您现有的路由上以定义一个面包屑
Route::get('/', HomeController::class) ->name('home') ->breadcrumb('Home');
如果您需要动态控制标题,请传递一个闭包
Route::get('/dashboard', DashboardController::class) ->name('dashboard') ->breadcrumb(fn() => Auth::user()->name.'’s dashboard');
嵌套面包屑
除非将它们串联起来,否则面包屑并不很有用。Gretel通过指向之前定义的父面包屑来处理嵌套面包屑
Route::get('/users', [UserController::class, 'index']) ->name('users.index') ->breadcrumb('Users'); Route::get('/users/{user}', [UserController::class, 'show']) ->name('users.show') ->breadcrumb(fn(User $user) => $user->name, 'users.index'); Route::get('/users/{user}/edit', [UserController::class, 'edit']) ->name('users.edit') ->breadcrumb('Edit', 'users.show');
在这里,您可以看到我们的 users.show
路由引用了 users.index
作为其父级。这样,当您为 users.show
渲染面包屑时,它也会显示 users.index
的面包屑。
Gretel假设嵌套路由中的参数可以安全地用于其父路由。在这个例子中,users.edit
将使用为编辑操作解析的 User
值渲染 users.show
面包屑。在大多数情况下,这正是您想要的。如果不这样做,您可以覆盖此行为(见下文)。
父级缩写
通常,子路由会引用具有相同名称前缀的父级。在我们的上述示例中,users.show
引用了 users.index
,而 users.edit
引用了 users.show
。在这种情况下,您可以使用父级缩写
Route::get('/admin/users/{user}/notes/create', [NotesController::class, 'create']) ->name('admin.users.notes.create') ->breadcrumb('Add Note', '.index'); // shorthand for "admin.users.notes.index"
这对于具有许多深层嵌套路由的大型应用程序非常有用。
浅层嵌套路由
如果您的嵌套路由不包含父路由所需的必要路由参数,您需要向Gretel提供这些值。您可以通过使用第三个回调来实现这一点
Route::get('/companies/{company}', [CompanyController::class, 'show']) ->name('companies.show') ->breadcrumb(fn(Company $company) => $company->name); Route::get('/users/{user}', [UserController::class, 'show']) ->name('users.show') ->breadcrumb(fn(User $user) => $user->name, 'companies.show', fn(User $user) => $user->company);
资源路由
您还可以为资源控制器定义面包屑。index()
、create()
、show()
和 edit()
方法的行为与常规面包屑辅助函数完全一样,只是如果您没有提供父级,它们会自动为您设置父级。
Route::resource('users', UserController::class) ->breadcrumbs(function(ResourceBreadcrumbs $breadcrumbs) { $breadcrumbs ->index('Users') ->create('New User') ->show(fn(User $user) => $user->name) ->edit('Edit'); });
如果您愿意,您还可以使用数组语法来表示简单的资源路由
Route::resource('users', UserController::class) ->breadcrumbs([ 'index' => 'Users', 'create' => 'New User', 'show' => fn(User $user) => $user->name, 'edit' => 'Edit', ]);
供应商路由
有时您想为定义在第三方包中的路由注册面包屑。在这种情况下,您可以直接使用 Gretel
门面。API与 Route::breadcrumb()
方法完全相同,但您必须将路由名称作为第一个参数传递
Gretel::breadcrumb( 'teams.show', // Route name fn(Team $team) => $team->name, // Title callback 'profile.show', // Parent );
显示面包屑
您可以使用 <x-breadcrumbs />
Blade组件来显示当前路由的面包屑。Blade组件接受一些可选属性
支持的框架
Gretel支持大多数常见的CSS框架。我们已经为CSS框架的文档标记添加了额外的 aria-
标签,以提供更好的可访问性。当前支持的框架
Tailwind 使用 "tailwind"
(默认)
Materialize 使用 "materialize"
Bootstrap 5 使用 "bootstrap5"
Bulma 使用 "bulma"
Semantic UI 使用 "semantic-ui"
Primer 使用 "primer"
Foundation 6 使用 "foundation6"
UIKit 使用 "uikit"
旧框架
一些框架的旧版本也是可用的
- Bootstrap 3 使用
"bootstrap3"
- Bootstrap 4 使用
"bootstrap4"
- Foundation 5 使用
"foundation5"
您通常需要在应用程序布局的某个位置包含 <x-breadcrumbs />
标签(如果您使用 JSON-LD,可能需要两次)
layouts/app.blade.php
:
<!DOCTYPE html> <html> <head> <title>{{ $title }}</title> <x-breadcrumbs jsonld /> </head> <body> <div class="container mx-auto"> <x-breadcrumbs framework="tailwind" /> ... </div> </body> </html>
自定义面包屑视图
您可以通过发布 gretel.php
配置文件通过 php artisan vendor:publish
或通过向 Blade 组件传递一个 view
属性来渲染自定义视图
<x-breadcrumbs view="app.breadcrumbs" />
以其他方式使用面包屑
如果您需要以其他方式使用面包屑——例如,通过一个 Gretel 没有集成的客户端框架进行渲染——您可以从路由中获取当前的面包屑作为 Collection
或 array
Route::breadcrumbs()->toCollection(); // Collection of `Breadcrumb` objects Route::breadcrumbs()->toArray(); // Array of `Breadcrumb` objects Route::breadcrumbs()->jsonSerialize(); // Array of breadcrumb arrays (title, url, is_current_page) Route::breadcrumbs()->toJson(); // JSON string of breadcrumbs matching jsonSerialize
例如,我们的 Inertia.js 集成 可以很容易地实现
Inertia::share('breadcrumbs', function(Request $request) { return $request->route()->breadcrumbs()->jsonSerialize(); });
可访问性
如果您选择渲染自己的视图,请确保遵循当前 WAI-ARIA 可访问性最佳实践。Gretel 提供了一些助手使这变得更容易
@unless ($breadcrumbs->isEmpty()) <!-- Wrap your breadcrumbs in a <nav> element with an aria-label attribute --> <nav aria-label="Breadcrumb"> <!-- Use an <ol> (ordered list) for the breadcrumb items --> <ol> @foreach ($breadcrumbs as $breadcrumb) <!-- You can use $activeClass() or $inactiveClass() to conditionally apply classes --> <li class="{{ $activeClass('active-breadcrumb') }}"> <!-- Use $ariaCurrent() to apply aria-current="page" to the active breadcrumb --> <a href="{{ $breadcrumb->url }}" {{ $ariaCurrent() }}> {{ $breadcrumb->title }} </a> </li> @endforeach </ol> </nav> @endunless
缓存面包屑
由于 Gretel 面包屑与您的路由一起注册,因此如果您缓存了路由,则需要缓存您的面包屑。您可以使用以下两个命令来完成此操作
# Cache breadcrumbs php artisan breadcrumbs:cache # Clear cached breadcrumbs php artisan breadcrumbs:clear
请注意,您必须在缓存路由之前缓存面包屑 。
处理错误
有时您可能会错误配置面包屑或忘记定义它们。您可以在 Gretel
门面注册处理程序来处理这些情况
// Log or report a missing breadcrumb (will always receive a MissingBreadcrumbException instance) Gretel::handleMissingBreadcrumbs(function(MissingBreadcrumbException $exception) { Log::warning($exception->getMessage()); }); // Throw an exception locally if there's a missing breadcrumb Gretel::throwOnMissingBreadcrumbs(! App::environment('production')); // Log or report a mis-configured breadcrumb (i.e. a parent route that doesn't exist). // This handler will pick up any other exception that is triggered while trying to configure // or render your breadcrumbs, so the type is unknown. Gretel::handleMisconfiguredBreadcrumbs(function(Throwable $exception) { Log::warning($exception->getMessage()); }); // Throw an exception locally if there's a mis-configured breadcrumb Gretel::throwOnMisconfiguredBreadcrumbs(! App::environment('production'));
与第三方包集成
如果您安装了该包,Gretel 将自动 与 Inertia.js 共享您的面包屑。您不需要进行任何操作即可启用此集成。(如果出于某种原因您不希望此行为,您可以通过发布 Gretel 配置来禁用它。)
您的面包屑将在客户端代码中作为 breadcrumbs
提供,并看起来像这样
const breadcrumbs = [ { title: 'Home', url: 'https://www.yourapp.com', is_current_page: false, }, { title: 'Users', url: 'https://www.yourapp.com/users', is_current_page: false, }, { title: 'Add a User', url: 'https://www.yourapp.com/users/create', is_current_page: true, } ];
然后您可以根据需要以客户端渲染面包屑。请务必查看 自定义面包屑 部分,了解如何确保客户端面包屑完全可访问。