Installation
composer require mosufy/url-shortener
Publish the config file:
php artisan vendor:publish --provider="Mosufy\UrlShortener\UrlShortenerServiceProvider"
Configuration
Edit config/url-shortener.php to define:
http://short.example.com)6)database)First Use Case Generate a shortened URL:
use Mosufy\UrlShortener\Facades\UrlShortener;
$shortUrl = UrlShortener::shorten('https://laravel.com/docs');
echo $shortUrl; // e.g., "http://short.example.com/abc123"
Where to Look First
Mosufy\UrlShortener\Facades\UrlShortener (primary entry point)config/url-shortener.php (customize behavior)vendor/mosufy/url-shortener/database/migrations/ (if using DB driver)Generating Short URLs
// Basic usage
$shortUrl = UrlShortener::shorten('https://example.com');
// Custom slug length (if configured)
$shortUrl = UrlShortener::shorten('https://example.com', 8);
// Force regeneration (if slug already exists)
$shortUrl = UrlShortener::shorten('https://example.com', 6, true);
Retrieving Original URLs
$originalUrl = UrlShortener::getOriginalUrl('abc123');
// or via route (if using web middleware)
Custom Slugs
$shortUrl = UrlShortener::shorten('https://example.com', null, false, 'my-custom-slug');
Batch Processing
$urls = ['https://example.com', 'https://google.com'];
$shortUrls = UrlShortener::shortenBatch($urls);
Middleware for Redirects
Add to app/Http/Kernel.php:
protected $routeMiddleware = [
'shorten' => \Mosufy\UrlShortener\Http\Middleware\ShortenUrl::class,
];
Route definition:
Route::get('/{slug}', ['middleware' => 'shorten'])->name('short.url');
API Endpoints
Route::post('/shorten', 'UrlShortenerController@shorten');
Route::get('/{slug}', 'UrlShortenerController@redirect');
Custom Storage
Extend the Mosufy\UrlShortener\Contracts\UrlShortenerRepository interface to implement a new storage driver (e.g., Redis, DynamoDB).
Event Listeners
Listen for UrlShortened events to log or notify:
UrlShortener::shorten('https://example.com');
// Fires: Mosufy\UrlShortener\Events\UrlShortened
Slug Collisions
forceRegenerate: true or implement a custom slug generator.Database Driver Assumptions
urls table with id, slug, original_url, and created_at columns.UrlShortenerRepository binding in the service provider.Base URL Validation
/). Missing it causes redirect loops.config/url-shortener.php has:
'base_url' => 'http://short.example.com/',
Case Sensitivity
ABC123 and abc123 are treated as different URLs.Rate Limiting
Check Slug Existence
if (UrlShortener::exists('abc123')) {
// Slug already taken
}
Log Shortened URLs
Override the UrlShortenerRepository to log calls:
public function save($slug, $originalUrl)
{
Log::info("Shortened URL: {$slug} -> {$originalUrl}");
// ... original logic
}
Test Locally
Use a local base URL (e.g., http://short.test/) and configure your hosts file:
127.0.0.1 short.test
Custom Slug Generator Bind a custom generator in the service provider:
$this->app->bind('url-shortener.slug-generator', function () {
return new \App\Services\CustomSlugGenerator();
});
Analytics Middleware
Extend the ShortenUrl middleware to track clicks:
public function handle($request, Closure $next)
{
$slug = $request->slug;
// Log click or increment counter
return $next($request);
}
Custom Storage
Implement the UrlShortenerRepository interface:
class RedisUrlShortenerRepository implements UrlShortenerRepository
{
public function save($slug, $originalUrl)
{
Redis::set("url:{$slug}", $originalUrl);
}
public function find($slug)
{
return Redis::get("url:{$slug}");
}
}
Bind it in the service provider:
$this->app->bind('url-shortener.repository', function () {
return new RedisUrlShortenerRepository();
});
Fallback for Missing Slugs Handle cases where a slug doesn’t exist:
if (!$originalUrl = UrlShortener::getOriginalUrl('nonexistent')) {
abort(404);
}
forceRegenerate sparingly.getOriginalUrl results if your use case allows it:
$originalUrl = Cache::remember("url:{$slug}", now()->addHours(1), function () use ($slug) {
return UrlShortener::getOriginalUrl($slug);
});
How can I help you explore Laravel packages today?