webflorist / routetree
RouteTree: Advanced Route Management for Laravel (>=v5.5)
Installs: 4 326
Dependents: 0
Suggesters: 0
Security: 0
Stars: 3
Watchers: 2
Forks: 5
Open Issues: 1
Requires
- laravel/framework: >=5.5
Requires (Dev)
- orchestra/testbench: >=3.5
README
This package includes a special API for creating and accessing Laravel-routes and route-related information. It's main concept is to create a hierarchical multi-language RouteTree using an expressive syntax (mostly mimicking Laravel's own). Using that hierarchy, RouteTree can be used to easily create:
- Any kind of navigation.
- Language-agnostic links.
- Language-switching menus.
- Breadcrumb-menus.
- Sitemap-menus.
Here is a complete feature overview:
- Automatic path generation of routes for all configured languages with the locale as the first path-segment (e.g.
en/company/team/contact
). - Automatic route name generation of expressive route names (e.g.
en.company.team.contact.get
). - Automatic inheritance of various route-settings (mimicking Laravels
Route::group()
). Payload
functionality to set any custom data for your routes (e.g. page title, meta description,includeInMenu
) and retrieve it anywhere in your application.- Automatic translation via various data-sources (e.g. using structured language-files within a folder-tree mirroring the hierarchical RouteTree structure). This is used for:
- Localized path-segments (e.g.
en/company/team/contact
for english andde/firma/team/kontakt
for german). - Localized route keys for parameter- or resource-routes using the corresponding Eloquent Models.
- Localized
Payload
(page-titles and any other custom information) - also for parameter- or resource-routes using the corresponding Eloquent Models. - You can also utilize this structure for page-content using the included
trans_by_route()
helper.)
- Localized path-segments (e.g.
- Unique language-agnostic route IDs (e.g.
company.team.contact
) to be used for various purposes anywhere in your app. Examples using theroute_node()
helper function:- Link in current language:
route_node('company.team.contact')->getUrl()
. - Link in specific language:
route_node('company.team.contact')->getUrl()->locale('de')
. - Access hierarchical parents/siblings/children:
route_node('company.team')->getChildNodes()
- Access the page title using:
route_node('company.team')->getTitle()
(falling back to upper cased route name - e.g.Team
). - Access any other kind of custom information (via a
Payload
):route_node('company.team')->payload->get('icon/description/keywords/author/layout/last_update/whatever')
.
- Link in current language:
- Automatic locale setting:
- From the first segment of the current route name (e.g.
en.company.news.get
). - From a (automatically saved) session value.
- From a
HTTP_ACCEPT_LANGUAGE
header sent by the client.
- From the first segment of the current route name (e.g.
- Automatic redirects:
- From the web root
/
to the language-specific home page (e.g./en
). - From paths with omitted locale (e.g. from
/company/team/contact
toen/company/team/contact
).
- From the web root
- XML-Sitemap
- Generate static file via
artisan
command. - Option to register a route delivering a dynamic sitemap.
- Automatic exclusion of
auth
routes and redirects. - Manual exclusion of routes and children.
- Resolving of all possible route keys for parameter/resource routes.
- Setting of optional tags (lastmod, changefreq, priority) via fluent setters, or by accessing an Eloquent Model (for parameter/resource routes).
- Generate static file via
- Cacheable (in combination with Laravel's route caching).
- REST-API to retrieve list of routes or various information or
Payload
from specific routes. (requires at least Laravel 5.6!)
Table of Contents
- RouteTree: Advanced Route Management for Laravel (>=v5.5)
Installation
- Require the package via composer:
php composer require webflorist/routetree
- Publish config:
php artisan vendor:publish --provider="Webflorist\RouteTree\RouteTreeServiceProvider"
- Define all locales you want to use on your website under the key
locales
inside yourroutetree.php
config file.
E.g.:'locales' => ['en','de']
.
(Alternatively you can set it tonull
to enforce a single-language app (using configapp.locale
).)
Note that this package is configured for automatic discovery for Laravel. Thus the package's Service Provider Webflorist\RouteTree\RouteTreeServiceProvider
as well as the RouteTree
alias will be automatically registered with Laravel.
Accessing the RouteTree-service
There are several ways to access the RouteTree service:
- via helper function:
route_tree()
- via Laravel facade:
\RouteTree::
- via Laravel container:
app('Webflorist\RouteTree\RouteTree')
orapp()['Webflorist\RouteTree\RouteTree']
The following code examples will use the facade RouteTree::
.
Defining the RouteTree
Just like with Laravel's own routing, your can define the RouteTree in your routes/web.php
.
For better comparability of syntaxes, the following examples will correspond to the ones presented in Laravel's Routing documentation where possible. They will also assume 2 configured languages ('en','de'
) - if not otherwise stated.
Basic Routing
RouteTree::node('foo', function (RouteNode $node) { $node->get(function() { if (\App::getLocale() === 'de') { return 'Hallo Welt'; } return 'Hello World'; }); });
The node()
method creates a RouteNode with name (and ID) foo
and is then setup using the closure in it's second parameter.
A RouteNode itself is comparable to Laravel's Route Groups. It does not per se result in any registered routes, but centralizes and shares various data (e.g. path, middleware, namespace, etc.) with it's actions and inherits them to any child nodes.
The $node->get()
call adds a RouteAction named get
using the HTTP request method GET
and a closure as it's callback.
A RouteAction results in one generated Laravel Route per configured language.
The above code will register the following routes:
- Route with name
de.foo.get
and pathde/foo
- Route with name
en.foo.get
and pathen/foo
As with Laravel's syntax you can also state the action's callback using Controller@method
:
RouteTree::node('foo')->get('Controller@method');
In the above example, the RouteNode's setup closure is skipped and instead the get
call is directly chained to the node
call. This is an alternative way to setup (which returns a RouteNode and thus allows chaining of various fluent methods), resulting in a more readable one-liner. Once a RouteNode becomes a little more complex and has several child-nodes, using a setup-closure is recommended instead. Also be wary, that action-creating methods (such as get
, post
, redirect
, view
, etc.) return the RouteAction object instead of the RouteNode.
Both syntax variants will be used in the following examples.
Available RouteActions
RouteNodes provide public methods to register RouteActions that respond to any HTTP verb:
RouteTree::node('foo', function (RouteNode $node) { $node->get($callback); $node->post($callback); $node->put($callback); $node->patch($callback); $node->delete($callback); $node->options($callback); });
Redirect Actions
You can also define redirecting nodes and state the target nodes by their ID:
RouteTree::node('here')->redirect('there'); RouteTree::node('there', function (RouteNode $node) { $node->get(function() { return 'You are now there'; }); });
By default, $node->redirect()
returns a 302 status code.
You can customize the status code using the optional second parameter:
$node->redirect('there', 301);
.
You can also use $node->permanentRedirect()
to return a 301 status code.
View Actions
If a RouteNode should only return a view, you can use the view
method:
RouteTree::node('welcome')->view('welcome');
You can pass data to the view via the second parameter of the view
method.
Configuring the Root Node
The RouteTree::node()
method used in the above examples automatically creates nodes with the root node as parent. You can configure the root node itself using the root
method instead:
RouteTree::root()->view('welcome');
You cannot state a name for the root node. It's name and ID will always be an empty string (''
).
Adding Child Nodes
There are several ways to create a node as a child of another node:
- by calling
$node->child($childName, $childCallback)
within the parent's setup-callback. - by stating the parent RouteNode's ID as the third parameter of the
node
method:RouteTree::node($childName, $childCallback, $parentId);
- by using
RouteTree::getRoute('parent')->child('child', $childCallback)
The first variant will be used in any further examples. It builds the RouteTree using nested closures, which has the benefit of representing the hierarchical RouteTree within the defining code indentation.
Child nodes will automatically receive a unique node ID representing the hierarchy of it's ancestors. For example a child with name bar
of a parent called foo
will have the ID foo.bar
.
The same happens with path segments, resulting in for example en/foo/bar
.
You can disable inheriting the segment to it's descendants by calling $node->inheritSegment(false)
. This is useful, if you want to use a RouteNode simply for grouping purposes without a representation in the URL-path.
As with Laravel's Route groups, middleware and (controller-)namespaces will be also inherited by default.
Path Segments
By default a RouteNode's name will also be it's path segment. But you can also state a different segment for a node by calling the RouteNode's segment
method:
RouteTree::node('company', function (RouteNode $node) { $node->segment('our-great-company'); $node->get($callback); });
The above code will register the following routes:
- Route with name
de.company.get
and pathde/our-great-company
- Route with name
en.company.get
and pathen/our-great-company
You can define localized path segments by handing a LanguageMapping
object including segments for all languages:
$node->segment( Webflorist\RouteTree\LanguageMapping::create() ->set('en', 'our-great-company') ->set('de', 'unsere-tolle-firma') );
This will register the following routes:
- Route with name
de.company.get
and pathde/our-great-company
- Route with name
en.company.get
and pathen/unsere-tolle-firma
You can also handle segment-translations via your language-files using the Automatic Translation functionality.
Middleware
You can assign middleware to RouteNodes using:
$node->middleware('auth');
This will attach the auth
middleware to all of the RouteNode's actions and inherit it to all descendant nodes.
Middleware-parameters can be stated in the second parameter of the middleware
method.
Inheritance of middleware can be disabled by handing boolean false
as the third parameter of the middleware
method.
In case you want a descendant node to NOT use an inherited middleware, simply state the following in the descendant's callback:
$node->skipMiddleware('auth');
There might also be situations, where you want a specific action of a RouteNode to have additional middleware or skip a middleware defined on the RouteNode. You can achieve this by chaining the middleware
call to the action-call. Here is an example:
RouteTree::node('user', function (RouteNode $node) { $node->middleware('auth'); $node->get($callback)->skipMiddleware('auth'); $node->post($callback); $node->delete($callback)->middlware('admin'); });
This will register the following routes:
GET
Routes with no middleware.POST
Routes with theauth
middleware.DELETE
Routes with both theauth
andadmin
middleware.
Controller Namespaces
By default all Controller@method
callback definitions will use App\Http\Controllers
as the namespace.
Using a RouteNode's namespace
method will append a segment to that namespace and inherit it to it's descendants. Inheritance can be overruled by simply prefixing the namespace with a backslash.
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` }) });
Route Parameters
The following code will result in the creation of the routes en/user/{id}
and 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; }); }); });
You can also set regular expression constraints for parameters:
$node->parameter('id')->regex('[0-9]+');
When using parameter
or resource
nodes, you might also want to be able to translate a route key (e.g. to realize a language-switching menu for a blog-article, which has different slugs for different languages.)
There are two ways to achieve this:
- You can state a static list of possible route keys of a parameter for each language using this syntax (enabling
translation
through the array-keys (0, 1, 'whatever')):
$node->parameter('blog_category')->routeKeys(LanguageMapping::create() ->set('en', [ 0 => 'search-engine-optimization', 1 => 'web-development' ]) ->set('de', [ 0 => 'suchmaschinen-optimierung', 1 => 'web-entwicklung' ]) );
- You can also translate the route key via an
Eloquent
model. There are two requirements for this:
- An
Eloquent
model must be stated using themodel
method of aRouteParameter
orRouteResource
:
$node->resource('blog_category', 'BlogCategoryController')->model('App\BlogCategory');
or
$node->parameter('blog_category')->model('App\BlogCategory');
- The model must implement the interface
Webflorist\RouteTree\Interfaces\TranslatesRouteKey
and subsequently thetranslateRouteKey
method. Here is an example implementation:
public static function translateRouteKey(string $value, string $toLocale, string $fromLocale): string { return BlogCategory::bySlug($value, $fromLocale)->slugs->where('locale', $toLocale)->first()->slug ?? $value; }
Resourceful RouteNodes
Akin to Laravel's Route::resource()
method, RouteTree can also register resourceful routes:
RouteTree::node('photos')->resource('photo', 'PhotoController');
This will generate a full set of resourceful routes in all languages:
Partial resource routes are also supported using the only
or except
methods:
$node->resource('photo', 'PhotoController')->only(['index', 'show']); $node->resource('photo', 'PhotoController')->except(['create', 'store', 'update', 'destroy']);
Resource nodes can also have child-nodes. In this case call the child
method on $node->resource
instead of $node
:
RouteTree::node('photos', function (RouteNode $node) { $node->resource('photo', 'PhotoController') $node->resource->child('featured', function (RouteNode $node) { $node->get('PhotoController@featured'); }); });
The above code will additionally generate the following routes:
- Route
en.photos.featured.get
with the URIen/photos/{photo}/featured
. - Route
de.photos.featured.get
with the URIde/photos/{photo}/featured
.
Retrieving Nodes from the RouteTree
Now that we have defined the RouteTree, it's RouteNodes can be accessed anywhere in your application using the route_node()
helper:
route_node()
is a shortcut forRouteTree::getCurrentNode()
and will return the currently active RouteNode.route_node('company.team.contact')
is a shortcut forRouteTree::getNode('company.team.contact')
and will return the RouteNode with IDcompany.team.contact
If RouteTree fails to find the current/specified node, it will throw a NodeNotFoundException
, except a fallback node is set in the config routetree.fallback_node
. The default config sets the fallback node to the root node, since you will probably want to inhibit NodeNotFoundExceptions
in a production environment.
Generating URLs
One of RouteTree's central use cases is to create language-agnostic links. Both RouteNodes and RouteActions have a getUrl()
method, that returns a RouteUrlBuilder
object, which will generate the corresponding URL when cast to a string.
(string) route_node('company.team.contact')->getUrl()
will return the URL of the RouteNode's action. If a node has multiple actions, it will return the link to it's first get
action (or index
actions with resources
).
The returned RouteUrlBuilder
object has several fluent setters to modify the generated link:
-
->locale ( ?string $locale=null ) : RouteUrlBuilder
(string) route_node('company')->getUrl()->locale('en')
will return the URL in english language (e.g.en/company
). (defaults to current locale) -
->absolute ( ?bool $absolute=null ) : RouteUrlBuilder
(string) route_node('company')->getUrl()->absolute(false)
will return a relative path instead of an absolute URL inkl. the domain (default can be configured inroutetree.absolute_urls
) -
->action ( string $locale ) : RouteUrlBuilder
(string) route_node('photos')->action('create')
will return the URL of theresource
actioncreate
(effectively appending'/create'
to the URL by default inen
locale). See the table at Resourceful RouteNodes for details. By default theindex
or the firstGET
action will be used. Note that with the actionsshow
,edit
,update
anddestroy
you will also have to state the route keys to set for the urlparameter(s)
(see just below). -
->parameters ( array $parameters ) : RouteUrlBuilder
(string) route_node('photos')->action('edit')->parameters(['photo' => 'my-slug'])
would result in the URL/en/photos/my-slug/edit
using the localeen
. Any URL to a Route containing one or more parameters will need values to fill in for those parameters, and thus a key within the handed array. E.g.photo/{photo_id}/comments/{comment_id}
would require['photo_id' => $photoId, 'comment_id' => $commentId]
to be passed. Any missing route keys (aka parameter-values aka slugs) are taken from the currently active LaravelRequest
- if possible.
Route Payload
You can define an access any information you want to a RouteNode using it's associated RoutePayload
object, which is publicly accessible via a node's payload
property.
Defining Payload
You can set a payload item directly in the RoutePayload
object using the following syntax-options:
- by calling a
RoutePayload
'sset
method:
$node->payload->set('title', 'My photos');
- by calling a magic setter named like the key you'd like to set:
$node->payload->title('My photos');
- by simple property definition:
$node->payload->title = 'My photos';
The value of a payload can be any data type as well as a Closure
. The Closure will receive two parameters:
- Array of
route parameter => route key
pairs, to retrieve the payload for (this way you can have payload depend on the current route parameters). - Locale of the language to retrieve the payload for.
As with path segments, any payload-item can also be multilingual using a LanguageMapping
object:
$node->payload->title = LanguageMapping::create() ->set('en', 'My photos') ->set('de', 'Meine Photos') );
You can also handle payload translations via your language-files using the Automatic Translation functionality.
If you want to have different values of a payload depending on an action, you can override a RouteNode's payload using a RouteAction's payload. Here is an example:
$node->getAction('edit')->payload->set('title', 'Edit photo');
For parameter/resource
nodes there is also the possibility to fetch payload from an Eloquent
model. There are two requirements for this:
- An
Eloquent
model must be stated using themodel
method of aRouteParameter
orRouteResource
:
$node->resource('photos', 'PhotoController')->model('App\Photo');
or
$node->parameter('photo')->model('App\Photo');
- The model must implement the interface
Webflorist\RouteTree\Interfaces\ProvidesRoutePayload
and subsequently thegetRoutePayload
method. Here is an example implementation:
public static function getRoutePayload(string $payloadKey, array $parameters, string $locale, ?string $action) { if ($payloadKey === 'title' && $action === 'show') { return self::find($parameters['photo'])->title; } }
Retrieving Payload
Payload can be retrieved anywhere in your app. using the get
method of a RoutePayload
. Example using the current RouteNode and RouteAction:
route_node()->payload->get('title');
This will look for the title
payload using the following order:
- Payload set directly in this class.
- Payload set in the RouteNode's RoutePayload (only if this RoutePayload is RouteAction-specific.)
- Payload returned from an Eloquent Model (only if RouteNode has a RouteParameter associated with an Eloquent Model, that implements ProvidesRoutePayload)
- Using Auto-Translation by searching for payload at a translation-key relative to the RouteNode's ID (see Automatic Translation).
There are multiple use-cases, where this payload functionality can be useful This is very useful to e.g.:
- Set the class of an icon, that should be visible in the menu next to the page-title.
- Set a language-specific abstract for each page, displayed on a sitemap.
- and much much more...
Special title
and navTitle
payloads
Page titles (for meta tags, canonical tags, title attributes of links, navigation menus, breadcrumbs, h1-tags, etc.) are probably one of the most used applications for payloads. Also quite often you might want to have a special (shorter) title for pages in navigation menus. To simplify handing of this, RouteNodes and RouteActions have special getTitle()
and getNavTitle()
methods, that add some additional fallback magic:
- Not set
navTitle
falls back totitle
. - Last fallback is always the upper-cased name of the RouteNode (e.g.
Photos
) - Various actions of resource nodes already come with meaningful default page titles (e.g.
'Create Resource'
forcreate
actions).
To utilize this magic, always use e.g. route_node()->getTitle()
instead of route_node()->payload->get('title')
and route_node()->getNavTitle()
instead of route_node()->payload->get('navTitle')
.
Automatic Translation
RouteTree also includes some magic regarding automatic translation. The basic concept is to map the hierarchy of the RouteTree to a folder-structure within the localization-folder.
The config-key localization.base_folder
sets the base-folder for the localization-files- and folders utilized by RouteTree. The default value is pages
, which translates to the folder \resources\lang\%locale%\pages
.
There are 2 seperate auto-translation-functionalities:
- Auto-translation of a node's path-segment and payload (e.g. title, navTitle, description, etc.)
- Auto-translation of regular page-content.
Auto-translation of a node's path-segment and payload
This provides an easy and intuitive way of configuring multi-language variants of the path-segment, page-title, or any other custom information for routes through Laravel's localization-files.
Each RouteNode is represented as a folder, and within the folder for a node resides a file, that contains all auto-translation-information. How this file is named is configured under the config-key localization.file_name
. The default value is pages
, which means information on all 1st-level-pages should be placed in this file: \resources\lang\%locale%\pages\pages.php
Example: Let's assume, you have defined the following RouteNodes (any actions or other options are missing for simplicity's sake):
RouteTree::node('company', function (RouteNode $node) { $node->child('history', ...); $node->child('team', function (RouteNode $node) { $node->child('office', ...); $node->child('service', ...); }); }); RouteTree::node('contact', ...);
Please note, that no path-segment, page-titles or custom information is defined on any node. We will use auto-translation for this.
To use auto-translation, the following file- and folder-structure should be present within the defined base-folder for each locale (per default \resources\lang\%locale%\pages
):
.
├── pages.php
├── company
├── pages.php
└── team
└── pages.php
Each pages.php-file includes auto-translation information for the child-nodes of the node, which corresponds to the folder it resides in. Let's see a german-language example of the contents of these files:
./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.', ] ];
Note that there is an additional entry in the title-array with an empty string as the key and "Home" as the value. This is title of the root-node (as the root-node's ID and name is always an empty string ''
).
./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.', ] ];
With this setup, the segments defined in the language-files will automatically be used for the route-paths of their corresponding nodes.
Also the title will be fetched with each getTitle-call submitted for a specific node (e.g. route_node('company.team.service')->getTitle()
would return Büro
, if the current locale is de
.
The same thing is possible with the description (or any other payload). (e.g. route_node('company.team.service')->payload->get('description')
would return Hier finden Sie unsere Service-Mitarbeiter.
, if the current locale is de
.
You can also set action-specific titles or navTitles via auto-translation by appending an underscore and the action to the node-name. This is very useful for resource nodes. Here is an example:
<?php return [ 'title' => [ 'users' => 'Users', 'users_create' => 'Create new user', 'users_show' => 'User :userName', 'users_edit' => 'Edit user :userName', ], ];
Auto-translation of regular page-content
With most websites you will want to translate page-content in your views. RouteTree includes a handy helper-function called trans_by_route()
, that will use the same folder-structure but with the language-file named as the last RouteNode.
Using the example above the location of this file for the office
page would be : ./company/team/office.php
Caching
If you are using Laravels route caching, RouteTree must cache it's own data too. So instead of 'artisan route:cache'
use RouteTree's caching-command, which will also take care of caching Laravel's routes:
php artisan routetree:route-cache
XML Sitemap
Having an up-to-date sitemap.xml
file is an important criterion for a modern search engine optimized website. RouteTree includes functionality to create such a file.
The following an artisan command will create a static XML sitemap file:
php artisan routetree:generate-sitemap
Per default the output-file will be at 'public/sitemap.xml'
. You can however configure this in RouteTree's config file.
You can also enable a route to provide the sitemap dynamically (see config-options under routetree.sitemap.route
).
Any URL's in the sitemap will use config('app.url')
as the base url automatically. But you can also state a different value unfer the routetree.sitemap.base_url
config.
Per default all routes created with RouteTree will be present in the sitemap. There are some exclusion criteria though:
- Only
GET
routes will be included. - Routes using the a middleware configured under
routetree.sitemap.excluded_middleware
will be automatically excluded (defaults to['auth']
). - Redirect routes will be automatically excluded.
- Routes with
parameters
can only be included, if RouteTree can retrieve all possible values for these parameters. There are two ways to achieve this:- using the
routeKeys()
method (see Route Parameters) - by stating an
Eloquent
model implementing the interfaceWebflorist\RouteTree\Interfaces\ProvidesRouteKeyList
and thus the methodgetRouteKeyList()
. A (single-language) default implementation is included in the traitWebflorist\RouteTree\Interfaces\Traits\ProvidesRouteKeyListDefault
:
- using the
public static function getRouteKeyList(string $locale = null, ?array $parameters = null): array { return self::pluck( (new self())->getRouteKeyName() )->toArray(); }
Furthermore you can also explicitly exclude a RouteNode (and all it's children) from the sitemap:
$node->sitemap->exclude();
A sitemap.xml
also allows the definition of additional information for search engines (see https://www.sitemaps.org/protocol.html#xmlTagDefinitions). You can state this data for a node using the following code:
$node->sitemap ->lastmod(Carbon::parse('2019-11-16T17:46:30.45+01:00')) ->changefreq('monthly') ->priority(1.0);
Furthermore you can also use payload translation (either via an Eloquent
model or via language files) to automatically retrieve these values.
API (requires at least Laravel 5.6!)
RouteTree also includes an API, that allows fetching information about routes registered with RouteTree. The API must be enabled via config routetree.api.enabled
and has the default base-url api/routetree/
(also configurable).
At the moment there are 2 endpoints:
GET api/routetree/routes
:
Returns collection of routes registered with Routetree.GET api/routetree/routes/{route_name}
:
Returns information about a route registered with Routetree.
Events
RouteTree dispatches events in various cases:
-
\Webflorist\RouteTree\Events\LocaleChanged
Is dispatched, when the locale saved in session by theRouteTreeMiddleware
is changed. The old locale is available via the$oldLocale
property of the event, and the new locale via$newLocale
. -
\Webflorist\RouteTree\Events\NodeNotFound
Is dispatched, whenroute_node()
is called and the current or specified node could not be found. The specified RouteNode ID is available via the$nodeId
property of the event, and isnull
in case no current node was found. -
\Webflorist\RouteTree\Events\Redirected
Is dispatched, when theRouteTreeMiddleware
performs an automatic redirect. The destination URI is available via the$toUri
property of the event, and the source URI via$fromUri
.
Important RouteTree-methods
For the already mentioned and explained methods root()
, node()
please see the corresponding sections above.
Here are some other useful methods of the RouteTree-class:
- getRootNode: Get the root-node which is also the whole RouteTree.
- getCurrentNode: Get the currently active RouteNode. (use
route_node()
as shortcut) - getCurrentAction: Get the currently active action.
- doesNodeExist: Checks, if a node within the RouteTree. It takes one parameter, which is the node-id to be checked. (e.g.:
RouteTree::doesNodeExist('company.team.office')
) - getNode: Get's and returns the RouteNode via it's Id. (e.g.:
RouteTree::getNode('company.team.office')
; useroute_node('company.team.office')
as shortcut)
Important RouteNode-methods
For the already mentioned and explained methods getUrl
, getTitle
and getNavTitle
please see the corresponding sections above.
Here are some other useful methods of the RouteNode-class:
- getParentNode: Gets the parent node of this node. (e.g.:
route_node('company.team.office')->getParentNode()
would retrieve the node with the IDcompany.team
.) - getParentNodes: Gets an array of all hierarchical parent-nodes of this node (with the root-node as the first element). (e.g.:
route_node()->getParentNodes()
would retrieve an array of all ancestral-nodes of the currently active node up to to the root-node. This is very useful for site-maps or breadcrumbs.) - hasChildNodes: Checks, if this node has any child-nodes.
- getChildNodes: Get an array of all child-nodes (e.g. useful for sub-menus).
- hasChildNodes: Checks, if this node has any child-nodes.
- getChildNode: Checks, if this node has a child-node with the stated name.
- getId: Get the full Id of this node.
- isActive: Checks, if the current node is currently active (optionally with the desired parameters) (e.g. useful to apply a CSS-class to an active link).
- nodeOrChildIsActive: Checks, if the current node or one of it's children is currently active (optionally with the desired parameters) (e.g. useful to apply a CSS-class to an active link).
Helper functions
Several helper-functions are included with this package:
-
route_tree: Gets the RouteTree singleton from Laravel's service-container. It can be used anywhere in your application (controllers, views, etc.) to access the RouteTree service.
-
route_node:
- If called with no parameter: get the currently active RouteNode.
- If called with a parameter:
route_node('company.team.contact')
will return the RouteNode with ID'company.team.contact'
.
-
route_node_url: Shortcut for
route_node()->getUrl()
. -
trans_by_route: Translates page-content using the current node's content-language-file (see section
Auto-translation of regular page-content
above).