webflorist/routetree

RouteTree:Laravel(≥v5.5)的高级路由管理

v2.3.4 2023-11-24 22:13 UTC

This package is auto-updated.

Last update: 2024-09-24 23:58:42 UTC


README

Build Status Latest Stable Version

此包包含用于创建和访问Laravel路由及其相关信息的特殊API。其主要概念是使用表达性语法(大部分模仿Laravel本身)创建一个分层多语言RouteTree。利用这个层次结构,RouteTree可以轻松创建:

  • 任何类型的导航。
  • 语言无关的链接。
  • 语言切换菜单。
  • 面包屑菜单。
  • 网站地图菜单。

以下是完整的功能概述

  • 自动路径生成:为所有配置的语言自动生成路由,将地区作为第一个路径段(例如,en/company/team/contact)。
  • 自动生成表达性路由名称(例如,en.company.team.contact.get)。
  • 自动继承各种路由设置(模仿Laravel的Route::group())。
  • Payload 功能,用于为您的路由设置任何自定义数据(例如,页面标题,元描述,includeInMenu)并在应用程序的任何位置检索它。
  • 自动翻译通过各种数据源(例如,使用文件夹树中与分层RouteTree结构相对应的结构化语言文件)。这用于:
    • 本地化路径段(例如,英文的en/company/team/contact和德语的de/firma/team/kontakt)。
    • 使用相应的Eloquent模型本地化路由键(用于参数或资源路由)。
    • 本地化 Payload(页面标题和任何其他自定义信息)- 也适用于参数或资源路由,使用相应的Eloquent模型。
    • 您还可以利用此结构通过包含的 trans_by_route() 助手函数使用页面内容。)
  • 独特的语言无关路由ID(例如,company.team.contact)可用于应用程序中的各种目的。以下是用 route_node() 助手函数的示例:
    • 当前语言的链接
      route_node('company.team.contact')->getUrl().
    • 特定语言的链接
      route_node('company.team.contact')->getUrl()->locale('de').
    • 访问分层父/兄弟/子节点
      route_node('company.team')->getChildNodes()
    • 使用以下方式访问页面标题
      route_node('company.team')->getTitle()
      (回退到路由名称的大写形式 - 例如 Team)。
    • 访问任何其他类型的自定义信息(通过 Payload
      route_node('company.team')->payload->get('icon/description/keywords/author/layout/last_update/whatever').
  • 自动地区设置:
    • 从当前路由名称的第一个段开始(例如,en.company.news.get)。
    • 从一个(自动保存的)会话值。
    • 从一个客户端发送的 HTTP_ACCEPT_LANGUAGE 头。
  • 自动重定向:
    • 从网站根目录 / 到特定语言的首页(例如,/en)。
    • 从省略地区路径的路径(例如,从 /company/team/contacten/company/team/contact)。
  • XML-Sitemap
    • 通过 artisan 命令生成静态文件。
    • 注册一个提供动态网站地图的路由的选项。
    • 自动排除 auth 路由和重定向。
    • 手动排除路由和子路由。
    • 解决所有可能的参数/资源路由键。
    • 通过流畅设置器设置可选标签(lastmod,changefreq,priority),或通过访问Eloquent模型(对于参数/资源路由)。
  • 可缓存(与Laravel的路由缓存结合使用)。
  • REST-API 用于检索路由列表或各种信息或特定路由的 Payload。 (需要至少 Laravel 5.6!)

目录

安装

  1. 通过 composer 需求包
    php composer require webflorist/routetree
  2. 发布配置
    php artisan vendor:publish --provider="Webflorist\RouteTree\RouteTreeServiceProvider"
  3. 在您的 routetree.php 配置文件中的 locales 键下定义您想要在网站上使用的所有区域设置。
    例如: 'locales' => ['en','de']
    (或者您可以将它设置为 null 以强制单语言应用(使用配置 app.locale)。)

请注意,此包已配置为自动发现 Laravel。因此,包的 Service Provider Webflorist\RouteTree\RouteTreeServiceProvider 以及 RouteTree 别名将自动注册到 Laravel 中。

访问 RouteTree-service

访问 RouteTree 服务的方法有几种

  • 通过辅助函数: route_tree()
  • 通过 Laravel 门面: \RouteTree::
  • 通过 Laravel 容器: app('Webflorist\RouteTree\RouteTree')app()['Webflorist\RouteTree\RouteTree']

以下代码示例将使用门面 RouteTree::

定义 RouteTree

就像 Laravel 自身的路由一样,您可以在您的 routes/web.php 中定义 RouteTree。

为了更好地比较语法,以下示例将在可能的情况下对应于在 Laravel 的路由文档 中呈现的示例。它们还将假定配置了 2 种语言('en','de') - 如果没有其他说明。

基本路由

RouteTree::node('foo', function (RouteNode $node) {
    $node->get(function() {
        if (\App::getLocale() === 'de') {
            return 'Hallo Welt';
        }
        return 'Hello World';
    });
});

node() 方法创建一个名为(和 ID)foo 的 RouteNode,然后使用其第二个参数中的闭包进行设置。

RouteNode 本身类似于 Laravel 的路由组。它本身不会产生任何注册的路由,但它集中共享各种数据(例如路径、中间件、命名空间等)及其动作,并将它们继承给任何子节点。

$node->get() 调用使用 HTTP 请求方法 GET 添加一个名为 get 的 RouteAction,并使用闭包作为其回调。

RouteAction 将在每个配置的语言中生成一个 Laravel 路由。

上述代码将注册以下路由

  • 名为 de.foo.get 且路径为 de/foo 的路由
  • 名为 en.foo.get 且路径为 en/foo 的路由

与 Laravel 的语法一样,您也可以使用 Controller@method 表达式指定动作的回调

RouteTree::node('foo')->get('Controller@method');

在上面的示例中,RouteNode 的设置闭包被省略,而是直接将 get 调用链接到 node 调用。这是一种设置(返回 RouteNode 并允许链接各种流畅方法)的替代方法,从而实现了一行代码的可读性。一旦 RouteNode 变得更复杂并具有多个子节点,建议使用设置闭包。此外,请注意,动作创建方法(如 getpostredirectview 等)返回 RouteAction 对象而不是 RouteNode。

以下示例将使用两种语法变体。

可用的 RouteActions

RouteNodes 提供公共方法来注册响应任何 HTTP 动词的 RouteActions

RouteTree::node('foo', function (RouteNode $node) {
    $node->get($callback);
    $node->post($callback);
    $node->put($callback);
    $node->patch($callback);
    $node->delete($callback);
    $node->options($callback);
});

重定向动作

您还可以定义重定向节点,并通过其 ID 指定目标节点

RouteTree::node('here')->redirect('there');

RouteTree::node('there', function (RouteNode $node) {
    $node->get(function() {
        return 'You are now there';
    });
});

默认情况下,$node->redirect() 返回 302 状态码。

您可以使用可选的第二个参数自定义状态码
$node->redirect('there', 301);.

您还可以使用 $node->permanentRedirect() 返回 301 状态码。

视图动作

如果 RouteNode 应仅返回视图,可以使用 view 方法

RouteTree::node('welcome')->view('welcome');

您可以通过 view 方法的第二个参数向视图传递数据。

配置根节点

上面示例中使用的 RouteTree::node() 方法会自动创建以根节点为父节点的节点。您可以使用 root 方法来配置根节点本身

RouteTree::root()->view('welcome');

您不能为根节点指定名称。它的名称和 ID 总是空字符串('')。

添加子节点

有几种方法可以将节点作为另一个节点的子节点创建

  • 在父节点的 setup-callback 中调用 $node->child($childName, $childCallback)
  • 通过将父 RouteNode 的 ID 作为 node 方法的第三个参数指定:RouteTree::node($childName, $childCallback, $parentId);
  • 使用 RouteTree::getRoute('parent')->child('child', $childCallback)

第一个变体将在任何进一步示例中使用。它使用嵌套闭包构建 RouteTree,这有利于在定义代码的缩进中表示分层 RouteTree。

子节点将自动接收一个唯一节点 ID,表示其祖先的层次结构。例如,名为 bar 的子节点,其父节点名为 foo,将具有 ID foo.bar

这与路径段的情况相同,例如 en/foo/bar

您可以通过调用 $node->inheritSegment(false) 来禁用将段继承到其子代。如果您只想将 RouteNode 用于分组目的,而不在 URL 路径中表示,这很有用。

与 Laravel 的 Route groups 一样,默认情况下,中间件和(控制器-)命名空间也将继承。

路径段

默认情况下,RouteNode 的名称也将是其路径段。但您也可以通过调用 RouteNode 的 segment 方法为节点指定不同的段

RouteTree::node('company', function (RouteNode $node) {    
    $node->segment('our-great-company');
    $node->get($callback);
});

上述代码将注册以下路由

  • 名为 de.company.get 且路径为 de/our-great-company 的路由
  • 名为 en.company.get 且路径为 en/our-great-company 的路由

您可以通过传递包括所有语言段的 LanguageMapping 对象来定义本地化路径段

$node->segment(
    Webflorist\RouteTree\LanguageMapping::create()
        ->set('en', 'our-great-company')
        ->set('de', 'unsere-tolle-firma')
);

这将注册以下路由

  • 名为 de.company.get 且路径为 de/our-great-company 的路由
  • 名为 en.company.get 且路径为 en/unsere-tolle-firma 的路由

您还可以通过使用 自动翻译 功能来处理段翻译。

中间件

您可以使用以下方法将中间件分配给 RouteNodes

$node->middleware('auth');

这将将 auth 中间件附加到 RouteNode 的所有操作,并将其继承到所有子节点。

可以在 middleware 方法的第二个参数中指定中间件参数。

可以通过将布尔值 false 作为 middleware 方法的第三个参数传递来禁用中间件的继承。

如果您希望子节点不使用继承的中间件,只需在子节点的回调中声明以下内容

$node->skipMiddleware('auth');

也可能存在这样的情况,您希望 RouteNode 的特定操作具有额外的中间件或跳过在 RouteNode 上定义的中间件。您可以通过将 middleware 调用链接到操作调用来实现这一点。以下是一个示例

RouteTree::node('user', function (RouteNode $node) {
    $node->middleware('auth');
    $node->get($callback)->skipMiddleware('auth');
    $node->post($callback);
    $node->delete($callback)->middlware('admin');
});

这将注册以下路由

  • GET 路由没有任何中间件。
  • POST 路由具有 auth 中间件。
  • DELETE 路由具有 authadmin 中间件。

控制器命名空间

默认情况下,所有 Controller@method 回调定义都将使用 App\Http\Controllers 作为命名空间。

使用RouteNode的namespace方法将向该命名空间追加一个段并将其继承到其子节点。可以通过在命名空间前加反斜杠来覆盖继承。

RouteTree::node('account', function (RouteNode $node) {
    $node->namespace('Account');
    $node->child('address' function (RouteNode $node) {
        $node->get('AddressController@get');
        // will point to `App\Http\Controllers\Account\AddressController`
    })
    $node->child('password' function (RouteNode $node) {
        $node->get('\My\Other\Namespace\PasswordController@get');
        // will point to `My\Other\Namespace\PasswordController`
    })
});

路由参数

以下代码将生成路由en/user/{id}de/user/{id}

RouteTree::node('user', function (RouteNode $node) {
    $node->child('id', function (RouteNode $node) {        
        $node->parameter('id');
        $node->get('id', function ($id) {
            return 'User '.$id;
        });
    });
});

您还可以为参数设置正则表达式约束。

$node->parameter('id')->regex('[0-9]+');

当使用parameterresource节点时,您可能还希望能够翻译路由键(例如,实现博客文章的语言切换菜单,不同语言有不同的slug)。

有两种实现方式

  • 您可以使用此语法为每种语言声明参数的可能路由键的静态列表(通过数组键(0,1,' whatever')启用translation
$node->parameter('blog_category')->routeKeys(LanguageMapping::create()
    ->set('en', [
        0 => 'search-engine-optimization',
        1 => 'web-development'
    ])
    ->set('de', [
        0 => 'suchmaschinen-optimierung',
        1 => 'web-entwicklung'
    ])
);
  • 您还可以通过Eloquent模型来翻译路由键。这有两个要求
  1. 必须使用RouteParameterRouteResourcemodel方法来声明Eloquent模型
    $node->resource('blog_category', 'BlogCategoryController')->model('App\BlogCategory');
    $node->parameter('blog_category')->model('App\BlogCategory');
  2. 模型必须实现接口Webflorist\RouteTree\Interfaces\TranslatesRouteKey及其随后的translateRouteKey方法。以下是一个示例实现
public static function translateRouteKey(string $value, string $toLocale, string $fromLocale): string
{
    return BlogCategory::bySlug($value, $fromLocale)->slugs->where('locale', $toLocale)->first()->slug ?? $value;
}

资源路由节点

类似于Laravel的Route::resource()方法,RouteTree也可以注册资源路由

RouteTree::node('photos')->resource('photo', 'PhotoController');

这将生成所有语言的完整资源路由集

还支持使用onlyexcept方法使用部分资源路由

$node->resource('photo', 'PhotoController')->only(['index', 'show']);

$node->resource('photo', 'PhotoController')->except(['create', 'store', 'update', 'destroy']);

资源节点也可以有子节点。在这种情况下,在$node->resource上调用child方法而不是$node

RouteTree::node('photos', function (RouteNode $node) {
    $node->resource('photo', 'PhotoController')
    $node->resource->child('featured', function (RouteNode $node) {
        $node->get('PhotoController@featured');
    });
});

以上代码将额外生成以下路由

  • 路由en.photos.featured.get,URI为en/photos/{photo}/featured
  • 路由de.photos.featured.get,URI为de/photos/{photo}/featured

从 RouteTree 检索节点

现在我们已经定义了RouteTree,可以在应用程序的任何地方使用route_node()助手来访问其RouteNodes

  • route_node()
    route_node()RouteTree::getCurrentNode()的快捷方式,将返回当前活动的RouteNode。
  • route_node('company.team.contact')
    route_node('company.team.contact')RouteTree::getNode('company.team.contact')的快捷方式,将返回ID为company.team.contact的RouteNode

如果RouteTree无法找到当前/指定的节点,它将抛出NodeNotFoundException,除非在配置中设置了回退节点routetree.fallback_node。默认配置将回退节点设置为根节点,因为在生产环境中您可能希望抑制NodeNotFoundExceptions

生成 URL

RouteTree的一个主要用例是创建语言无关的链接。RouteNodes和RouteActions都有一个getUrl()方法,该方法返回一个RouteUrlBuilder对象,该对象在转换为字符串时将生成相应的URL。

(string) route_node('company.team.contact')->getUrl()将返回RouteNode动作的URL。如果节点有多个动作,它将返回到其第一个get动作(或资源中的index动作)的链接。

返回的RouteUrlBuilder对象有几个流畅的设置器来修改生成的链接

  • ->locale ( ?string $locale=null ) : RouteUrlBuilder
    (string) route_node('company')->getUrl()->locale('en')将返回英文语言的URL(例如,en/company)。(默认为当前语言环境)

  • ->absolute ( ?bool $absolute=null ) : RouteUrlBuilder
    (string) route_node('company')->getUrl()->absolute(false)将返回一个相对路径而不是包含域的绝对URL(默认可以配置在routetree.absolute_urls中)

  • ->action (字符串 $locale) : RouteUrlBuilder
    (字符串) route_node('photos')->action('create') 将返回资源操作 create 的 URL(默认情况下,在 en 区域设置下将 '/create' 添加到 URL)。有关详细信息,请参阅资源化路由节点表格。默认情况下将使用 index 或第一个 GET 操作。注意,对于 showeditupdatedestroy 操作,您还必须指定设置 URL 参数 的路由键(见下文)。

  • ->parameters (数组 $parameters) : RouteUrlBuilder
    (字符串) route_node('photos')->action('edit')->parameters(['photo' => 'my-slug']) 将产生 URL /en/photos/my-slug/edit 使用区域设置 en。任何包含一个或多个参数的路由 URL 都需要填充这些参数的值,因此需要在传递的数组中指定一个键。例如,photo/{photo_id}/comments/{comment_id} 需要传递 ['photo_id' => $photoId, 'comment_id' => $commentId]。任何缺失的路由键(即参数值或别名)将来自当前活动的 Laravel Request - 如果可能的话。

路由 Payload

您可以使用关联的 RoutePayload 对象来定义任何想要传递给路由节点的信息,该对象可以通过节点的 payload 属性公开访问。

定义 Payload

您可以使用以下语法选项直接在 RoutePayload 对象中设置负载项:

  • 通过调用 RoutePayloadset 方法
    $node->payload->set('title', 'My photos');
  • 通过调用名为您想要设置的键的魔法设置器
    $node->payload->title('My photos');
  • 通过简单的属性定义
    $node->payload->title = 'My photos';

负载项的值可以是任何数据类型,以及 Closure。闭包将接收两个参数

  • route parameter => route key 对的数组,用于检索负载项(这样可以使负载项依赖于当前的路由参数)。
  • 要检索负载项的语言的区域设置。

与路径段一样,任何负载项也可以使用 LanguageMapping 对象进行多语言处理

$node->payload->title = LanguageMapping::create()
        ->set('en', 'My photos')
        ->set('de', 'Meine Photos')
);

您还可以通过使用自动翻译功能来处理负载项的翻译。

如果您想要根据操作有不同的负载项值,您可以覆盖路由节点的负载项,使用路由操作的负载项。以下是一个示例

$node->getAction('edit')->payload->set('title', 'Edit photo');

对于 parameter/resource 节点,还有从 Eloquent 模型获取负载项的可能性。为此有两个要求

  1. 必须使用RouteParameterRouteResourcemodel方法来声明Eloquent模型
    $node->resource('photos', 'PhotoController')->model('App\Photo');
    $node->parameter('photo')->model('App\Photo');
  2. 该模型必须实现接口 Webflorist\RouteTree\Interfaces\ProvidesRoutePayload 并随后实现 getRoutePayload 方法。以下是一个示例实现
public static function getRoutePayload(string $payloadKey, array $parameters, string $locale, ?string $action)
{
    if ($payloadKey === 'title' && $action === 'show')
    {
        return self::find($parameters['photo'])->title;
    }
}

检索 Payload

负载项可以在应用程序的任何位置通过 RoutePayloadget 方法检索。以下是一个使用当前路由节点和路由操作的示例

route_node()->payload->get('title');

这将按照以下顺序查找 title 负载项

  1. 在此类中直接设置的负载项。
  2. 在路由节点的 RoutePayload 中设置的负载项(仅当此 RoutePayload 是特定于路由操作的。)
  3. 从 Eloquent 模型返回的负载项(仅当路由节点与一个关联的路由参数相关联,并且该路由参数实现了 ProvidesRoutePayload 接口。)
  4. 通过自动翻译在相对于路由节点 ID 的翻译键中查找(见自动翻译)。

有很多用例,其中这种负载项功能非常有用。这对于例如非常有用。

  • 设置图标的类,使其在页面标题旁边的菜单中可见。
  • 为每个页面设置特定语言的内容摘要,在网站地图中显示。
  • 还有更多...

特殊的 titlenavTitle Payload

页面标题(用于元标签、规范标签、链接标题属性、导航菜单、面包屑、h1标签等)可能是最常用的负载应用之一。你也可能想要为导航菜单中的页面设置一个特殊的(较短的)标题。为了简化处理,RouteNodes 和 RouteActions 有特殊的 getTitle()getNavTitle() 方法,这些方法添加了一些额外的回退魔法。

  • 未设置 navTitle 将回退到 title
  • 最后的回退总是 RouteNode 的名称的大写(例如 Photos)。
  • 资源节点的一些操作已经带有有意义的默认页面标题(例如,为 create 操作的 '创建资源')。

要利用这个魔法,始终使用例如 route_node()->getTitle() 而不是 route_node()->payload->get('title'),以及使用 route_node()->getNavTitle() 而不是 route_node()->payload->get('navTitle')

自动翻译

RouteTree 还包括有关自动翻译的一些魔法。基本概念是将 RouteTree 的层次结构映射到本地化文件夹内的文件夹结构。

配置键 localization.base_folder 设置了 RouteTree 使用的本地化文件和文件夹的基本文件夹。默认值是 pages,这表示文件夹 \resources\lang\%locale%\pages

有 2 个独立的自动翻译功能。

  1. 自动翻译节点的路径段和负载(例如,标题、navTitle、描述等)。
  2. 自动翻译常规页面内容。

自动翻译节点路径段和 Payload

这提供了一种简单直观的方式来配置通过 Laravel 的本地化文件的多语言路径段、页面标题或任何其他自定义信息。

每个 RouteNode 都表示为一个文件夹,并且节点所在的文件夹中包含所有自动翻译信息。该文件的命名方式是在配置键 localization.file_name 下配置的。默认值是 pages,这意味着所有一级页面的信息都应该放在这个文件中:\resources\lang\%locale%\pages\pages.php

示例:假设你已定义以下 RouteNodes(为了简单起见,省略了任何操作或其他选项)

    RouteTree::node('company', function (RouteNode $node) {
        $node->child('history', ...);
        $node->child('team', function (RouteNode $node) {
            $node->child('office', ...);
            $node->child('service', ...);
        });
    });
    RouteTree::node('contact', ...);

请注意,任何节点上都没有定义路径段、页面标题或自定义信息。我们将为此使用自动翻译。

要使用自动翻译,应在每个区域定义的基本文件夹中存在以下文件和文件夹结构(默认为 \resources\lang\%locale%\pages

 .
 ├── pages.php
 ├── company
     ├── pages.php
     └── team
         └── pages.php

每个 pages.php 文件都包括对应于其所在文件夹的节点的子节点的自动翻译信息。以下是一个德语语言文件的示例内容

./pages.php

<?php
return [
    'segment' => [
        'company' => 'firma',
        'contact' => 'kontakt',
    ],
    'title' => [
        'company' => 'Über unsere Firma',
        'contact' => 'Kontaktieren Sie uns!',
        '' => 'Startseite',
    ],
    'abstract' => [        
        'company' => 'Hier finden Sie allgemeine Informationen über unsere Firma.',
        'contact' => 'Hier finden Sie Möglichkeiten, mit uns in Kontakt zu treten.',
    ]
];

注意,在标题数组中有一个额外的条目,其键为空字符串,值为 "Home"。这是根节点的标题(因为根节点的 ID 和名称始终是空字符串 '')。

./company/pages.php

<?php
return [
    'segment' => [
        'history' => 'geschichte',
        'team' => 'mitarbeiter',
    ],
    'title' => [
        'history' => 'Die Firmengeschichte',
        'team' => 'Unsere Mitarbeiter',
    ],
    'description' => [
        'history' => 'Hier finden Sie die Entstehungsgeschichte unserer Firma.',
        'team' => 'Hier sind unsere Mitarbeiter zu finden.',
    ]
];

./company/team/pages.php

<?php
return [
    'segment' => [
        'office' => 'buero',
        'service' => 'kundendienst',
    ],
    'title' => [
        'office' => 'Büro',
        'service' => 'Kundendienst',
    ],
    'description' => [
        'office' => 'Hier finden Sie unsere Büro-Mitarbeiter.',
        'service' => 'Hier finden Sie unsere Service-Mitarbeiter.',
    ]
];

使用此设置,语言文件中定义的段将自动用于对应节点的路由路径。

标题也将通过每个针对特定节点提交的 getTitle-call 来检索(例如,如果当前区域是 de,则 route_node('company.team.service')->getTitle() 将返回 Büro)。

相同的事情也适用于描述(或任何其他负载)。(例如,如果当前区域是 de,则 route_node('company.team.service')->payload->get('description') 将返回 Hier finden Sie unsere Service-Mitarbeiter.)。

您还可以通过在节点名称后附加下划线和操作来设置特定于操作的标题或 navTitles 通过自动翻译。这对于资源节点非常有用。以下是一个示例

<?php
return [
    'title' => [
        'users' => 'Users',
        'users_create' => 'Create new user',
        'users_show' => 'User :userName',
        'users_edit' => 'Edit user :userName',
    ],
];

自动翻译常规页面内容

在大多数网站上,您都希望将视图中的页面内容进行翻译。RouteTree 包含一个方便的辅助函数 trans_by_route(),该函数将使用相同的文件夹结构,但语言文件的名称是最后一个 RouteNode。

使用上面的示例,对于 office 页面,此文件的路径会是: ./company/team/office.php

缓存

如果您使用 Laravel 的路由缓存,RouteTree 也必须缓存自己的数据。所以,不要使用 'artisan route:cache',而要使用 RouteTree 的缓存命令,这个命令也会处理 Laravel 路由的缓存。

php artisan routetree:route-cache

XML 站点地图

拥有一个最新的 sitemap.xml 文件是现代搜索引擎优化网站的一个重要标准。RouteTree 包含创建此类文件的功能。

以下 artisan 命令将创建一个静态的 XML 网站地图文件

php artisan routetree:generate-sitemap

默认情况下,输出文件将位于 'public/sitemap.xml'。但是,您可以在 RouteTree 的配置文件中配置此路径。

您还可以启用一个路由来动态提供网站地图(请参阅 routetree.sitemap.route 下的配置选项)。

网站地图中的任何 URL 都会自动使用 config('app.url') 作为基础 URL。但是,您也可以在 routetree.sitemap.base_url 配置下指定不同的值。

默认情况下,所有使用 RouteTree 创建的路由都将包含在网站地图中。尽管有一些排除标准

  • 只有 GET 路由将被包含。
  • 使用在 routetree.sitemap.excluded_middleware 下配置的中间件的路由将被自动排除(默认为 ['auth'])。
  • 重定向路由将被自动排除。
  • 具有 parameters 的路由只有在 RouteTree 可以检索这些参数的所有可能值时才能被包含。有两种实现方式
    • 使用 routeKeys() 方法(请参阅 路由参数
    • 通过声明一个实现接口 Webflorist\RouteTree\Interfaces\ProvidesRouteKeyListEloquent 模型,并因此拥有 getRouteKeyList() 方法。默认实现包含在特性 Webflorist\RouteTree\Interfaces\Traits\ProvidesRouteKeyListDefault
    public static function getRouteKeyList(string $locale = null, ?array $parameters = null): array
    {
        return self::pluck(
            (new self())->getRouteKeyName()
        )->toArray();
    }

此外,您还可以明确从网站地图中排除一个 RouteNode(及其所有子节点)

$node->sitemap->exclude();

sitemap.xml 还允许为搜索引擎定义额外的信息(请参阅 https://www.sitemaps.org/protocol.html#xmlTagDefinitions)。您可以使用以下代码为节点声明此数据

$node->sitemap
    ->lastmod(Carbon::parse('2019-11-16T17:46:30.45+01:00'))
    ->changefreq('monthly')
    ->priority(1.0);

此外,您还可以使用负载翻译(通过 Eloquent 模型或语言文件)自动检索这些值。

API (需要至少 Laravel 5.6!)

RouteTree 还包括一个 API,允许检索与 RouteTree 注册的路由相关的信息。必须通过配置 routetree.api.enabled 启用 API,默认基本 URL 为 api/routetree/(也可以配置)。

目前有两个端点

  • GET api/routetree/routes:
    返回注册到 Routetree 的路由集合。
  • GET api/routetree/routes/{route_name}:
    返回有关注册到 Routetree 的路由的信息。

事件

RouteTree 在各种情况下调度事件

  • \Webflorist\RouteTree\Events\LocaleChanged
    RouteTreeMiddleware 保存到会话中的区域设置更改时,将调度。旧的区域设置可通过事件的 $oldLocale 属性访问,新的区域设置可通过 $newLocale 访问。

  • \Webflorist\RouteTree\Events\NodeNotFound
    当调用 route_node() 时,如果当前或指定的节点找不到,将调度。指定的 RouteNode ID 可通过事件的 $nodeId 属性访问,如果没有找到当前节点,则为 null

  • \Webflorist\RouteTree\Events\Redirected
    RouteTreeMiddleware 执行自动重定向时,将调度。目标 URI 可通过事件的 $toUri 属性访问,源 URI 可通过 $fromUri 访问。

重要的 RouteTree 方法

对于已经提及和解释的 root()node() 方法,请参阅上述相应部分。

以下是 RouteTree 类的其他一些有用方法

  • getRootNode:获取根节点,它也是整个 RouteTree。
  • getCurrentNode:获取当前活动的 RouteNode。(使用 route_node() 作为快捷方式)
  • getCurrentAction:获取当前活动操作。
  • doesNodeExist:检查RouteTree中是否存在节点。它接受一个参数,即要检查的节点ID。(例如:RouteTree::doesNodeExist('company.team.office')
  • getNode:获取并返回通过其ID的RouteNode。(例如:RouteTree::getNode('company.team.office');可以使用route_node('company.team.office')作为快捷方式)

重要的 RouteNode 方法

关于已提及并解释的方法getUrlgetTitlegetNavTitle,请参见上面的相应部分。

以下是RouteNode类的其他一些有用方法

  • getParentNode:获取此节点的父节点。(例如:route_node('company.team.office')->getParentNode()将检索ID为company.team的节点。)
  • getParentNodes:获取此节点所有层级父节点(以根节点为第一个元素)的数组。(例如:route_node()->getParentNodes()将检索从当前活动节点到根节点的所有祖先节点。这对于网站地图或面包屑非常有用。)
  • hasChildNodes:检查此节点是否有任何子节点。
  • getChildNodes:获取所有子节点的数组(例如,对于子菜单很有用)。
  • hasChildNodes:检查此节点是否有任何子节点。
  • getChildNode:检查此节点是否有具有指定名称的子节点。
  • getId:获取此节点的完整ID。
  • isActive:检查当前节点是否当前活动(可选地带有所需参数)(例如,用于向活动链接应用CSS类)。
  • nodeOrChildIsActive:检查当前节点或其子节点是否当前活动(可选地带有所需参数)(例如,用于向活动链接应用CSS类)。

辅助函数

此包包含几个辅助函数

  • route_tree:从Laravel的服务容器中获取RouteTree单例。您可以在应用的任何地方(控制器、视图等)使用它来访问RouteTree服务。

  • route_node:

    • 如果没有参数调用:获取当前活动的RouteNode。
    • 如果有参数调用:route_node('company.team.contact')将返回ID为'company.team.contact'的RouteNode。
  • route_node_url:是route_node()->getUrl()的快捷方式。

  • trans_by_route:使用当前节点的内容语言文件翻译页面内容(请参见上面的自动翻译常规页面内容部分)。