rayzenai/url-manager
Laravel package to manage URLs, redirects, SEO metadata, visit tracking, and XML sitemaps, with redirect-loop protection and automatic old→new slug redirects. Includes Filament 4 admin panel integration (UrlInput) and optional media SEO via file-manager.
Installation:
composer require rayzenai/url-manager
php artisan vendor:publish --tag=url-manager-config
php artisan vendor:publish --tag=url-manager-migrations
php artisan migrate
Configure Location Service (for visitor tracking):
config/location.php.envRegister Filament Plugin:
// In app/Providers/Filament/AdminPanelProvider.php
->plugin(UrlManagerPlugin::make())
Add Redirect Middleware (critical for slug updates):
// In bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->web(prepend: [
HandleUrlRedirects::class,
]);
});
First Model Integration:
php artisan url-manager:make-model Product
Then add use HasUrl to your model and implement webUrlPath().
Generate URLs:
php artisan urls:generate
old-product to new-product)/old-product are automatically redirected to /new-product (301 by default)// In your Eloquent model
use RayzenAI\UrlManager\Traits\HasUrl;
class Product extends Model
{
use HasUrl;
public function webUrlPath(): string
{
return 'products/' . $this->slug;
}
// Optional overrides
public function activeUrlField(): string
{
return 'is_published';
}
public function ogTags(): array
{
return [
'title' => $this->name,
'description' => $this->description,
'image' => $this->image_url,
];
}
}
Key Methods to Implement:
webUrlPath() (required) - Defines the URL structureactiveUrlField() (optional) - Customize active status fieldogTags(), getSeoMetadata()) - For rich SEO data// Creating redirects
Url::createRedirect('old-path', 'new-path', 301);
// Checking redirects in routes
Route::get('/legacy/{slug}', function ($slug) {
$redirect = Url::findRedirect('legacy/' . $slug);
if ($redirect) {
return redirect($redirect->destination, $redirect->status_code);
}
// Fallback logic
})->name('legacy.route');
// Generate sitemap
php artisan sitemap:generate
// Customize sitemap output location
config([
'url-manager.sitemap.path' => public_path('sitemaps'),
]);
// Include custom static routes
config([
'url-manager.sitemap.custom_routes' => [
['path' => '/about', 'priority' => 0.7],
['path' => '/contact', 'priority' => 0.6],
],
]);
// Track visits automatically (via middleware)
UrlManager::trackVisit($model, $userId);
// Manual tracking
UrlManager::trackVisit($product, auth()->id());
// Get visit analytics
$visits = UrlManager::getVisitAnalytics($product, 'last_7_days');
Middleware Order:
HandleUrlRedirects middleware to catch redirects before route resolutionTrimStrings, ConvertEmptyStringsToNull, and ValidateSignatureModel Events:
// In your model's boot method
static::saved(function ($model) {
if ($model->wasChanged('slug')) {
UrlManager::createRedirect(
$model->getPreviousUrl(),
$model->webUrlPath(),
301
);
}
});
Filament Customization:
// Extend the UrlInput component
use RayzenAI\UrlManager\Components\UrlInput;
UrlInput::macro('withCustomValidation', function () {
return $this->extraAttributes([
'data-validation' => 'required|url',
]);
});
Performance Optimization:
urls.path and urls.slug columns// In config/url-manager.php
'cache' => [
'enabled' => true,
'ttl' => 60, // Cache redirects for 60 seconds
]
Bulk URL Generation:
# For large datasets, process in chunks
php artisan urls:generate --chunk=1000
# Or use queue jobs
php artisan urls:generate --queue
Redirect Middleware Placement:
HandleUrlRedirects is prepended in middlewarehandle() methodCircular Redirects:
php artisan url-manager:check-loops
Sitemap Generation Failures:
php -d memory_limit=4G artisan sitemap:generatephp artisan sitemap:generate --chunk=5000php artisan sitemap:generate --queueSEO Metadata Conflicts:
getSeoMetadata() to merge data:
public function getSeoMetadata(): array
{
return array_merge(
parent::getSeoMetadata(),
['custom_tag' => 'value']
);
}
Visit Tracking Accuracy:
config/location.phpURL Generation Issues:
# Check model configuration
php artisan url-manager:check App\Models\Product
# View generated URLs
php artisan tinker
>>> \RayzenAI\UrlManager\Models\Url::where('model_type', 'App\Models\Product')->get();
Redirect Debugging:
// Add to HandleUrlRedirects middleware
public function handle($request, Closure $next)
{
$redirect = Url::findRedirect($request->path());
if ($redirect) {
\Log::info("Redirecting {$request->path()} to {$redirect->destination}");
}
return $next($request);
}
Sitemap Validation:
# Test sitemap generation
php artisan sitemap:generate --dry-run
# Validate against Google guidelines
composer require squizlabs/php_codesniffer
vendor/bin/phpcs --standard=Google sitemap.xml
Active URL Field:
is_active, but can be customized:
public function activeUrlField(): string
{
return 'published'; // For models using 'published' instead
}
Slug Generation:
config/url-manager.php:
'slug' => [
'separator' => '-',
'max_length' => 100,
'transliterate' => true,
]
Visit Tracking:
public function shouldTrackVisits(): bool
{
return false; // Opt out of tracking
}
SEO Metadata Priority:
// In config/url-manager.php
'seo' => [
'priority' => [
'model' => 10, // Highest
'route' => 5, // Middle
'fallback' => 1, // Lowest
],
]
// Extend the redirect finder
How can I help you explore Laravel packages today?