Two values control everything: the canonical domain every URL is built from, and whether trailing slashes are trimmed. Both read from the environment, so publishing the config file is optional.
CANONICAL_DOMAIN=https://example.comCANONICAL_TRIM_TRAILING_SLASH=truereturn [ 'domain' => 'https://example.com', 'trim_trailing_slash' => true,];The config file
Section titled “The config file”The service provider merges its own config, so the package runs without publishing anything. Publish only to keep the defaults in your repo:
php artisan vendor:publish --tag="canonical-config"Directoryconfig/
- canonical.php
return [ // The domain every canonical URL is built from. Falls back to APP_URL, // then http://localhost, when CANONICAL_DOMAIN is unset. 'domain' => env('CANONICAL_DOMAIN', env('APP_URL', 'http://localhost')),
// Trim trailing slashes from generated URLs (/blog/ → /blog). @since 1.1.0 'trim_trailing_slash' => env('CANONICAL_TRIM_TRAILING_SLASH', true),];The canonical domain
Section titled “The canonical domain”Every generated URL is built from this value, never from the host the request arrived on:
CANONICAL_DOMAIN=https://example.comUnset, it falls back to APP_URL, then to http://localhost.
Trailing-slash handling
Section titled “Trailing-slash handling”Trailing slashes are trimmed by default, so /blog/ and /blog collapse to one
URL. Turn it off when the two are distinct routes:
CANONICAL_TRIM_TRAILING_SLASH=false| Input | true (default) |
false |
|---|---|---|
/blog/ |
https://example.com/blog |
https://example.com/blog/ |
/blog |
https://example.com/blog |
https://example.com/blog |
/ |
https://example.com |
https://example.com |
Query parameters are preserved under both settings.
Domain validation
Section titled “Domain validation”The domain is validated on first use. It must be a valid URL, use the http or
https scheme, and include a host:
CANONICAL_DOMAIN=https://example.comCANONICAL_DOMAIN=http://localhost:8000CANONICAL_DOMAIN=https://example.com/A trailing slash on the domain is stripped before validation, so the third form
behaves like the first. These throw CanonicalConfigurationException:
CANONICAL_DOMAIN=example.comCANONICAL_DOMAIN=ftp://example.comCANONICAL_DOMAIN=| Value | Why it fails |
|---|---|
example.com |
No scheme, so not a syntactically valid URL. |
ftp://example.com |
Valid URL, but only http and https are allowed. |
| (empty) | Canonical domain is not set in config. |
Version compatibility
Section titled “Version compatibility”| Package version | PHP version | Laravel version |
|---|---|---|
| 1.4.x+ | 8.4+ | 12.x, 13.x |
| 1.3.x+ | 8.4+ | 11.x, 12.x |
| 1.0.x – 1.2.x | 8.3+ | 11.x, 12.x |