laravel-url-shortener maintained by mepsd
Laravel URL Shortener
A Laravel package to interact with the URL Shortener API service. Easily create, manage, and track short URLs in your Laravel application.
Features
- Create short URLs with optional custom keys
- List, retrieve, update, and delete short URLs
- Get detailed analytics and statistics
- Built-in retry mechanism for failed requests
- Comprehensive error handling
- Facade and dependency injection support
- Fully typed with PHP 8.1+ features
Requirements
- PHP 8.1 or higher
- Laravel 10.x, 11.x, or 12.x
- Guzzle HTTP Client
Installation
Install the package via Composer:
composer require mepsd/laravel-url-shortener
The package will auto-register its service provider and facade.
Publish Configuration
Publish the configuration file:
php artisan vendor:publish --tag=url-shortener-config
This will create a config/url-shortener.php file.
Configuration
Add the following environment variables to your .env file:
URL_SHORTENER_BASE_URL=https://your-shortener-domain.com
URL_SHORTENER_API_TOKEN=your-api-token-here
Full Configuration Options
// config/url-shortener.php
return [
// Base URL of your URL shortener service
'base_url' => env('URL_SHORTENER_BASE_URL', 'http://localhost:8000'),
// API token for authentication
'api_token' => env('URL_SHORTENER_API_TOKEN'),
// API version (default: v1)
'api_version' => env('URL_SHORTENER_API_VERSION', 'v1'),
// Request timeout in seconds
'timeout' => env('URL_SHORTENER_TIMEOUT', 30),
// Retry configuration
'retries' => [
'times' => env('URL_SHORTENER_RETRY_TIMES', 3),
'sleep' => env('URL_SHORTENER_RETRY_SLEEP', 100), // milliseconds
],
// Default options for creating short URLs
'defaults' => [
'track_visits' => true,
'is_single_use' => false,
],
];
Usage
Using the Facade
use Mepsd\UrlShortener\Facades\UrlShortener;
// Create a short URL
$shortUrl = UrlShortener::create('https://example.com/very-long-url');
echo $shortUrl->shortUrl; // https://short.url/abc123
echo $shortUrl->key; // abc123
echo $shortUrl->destinationUrl; // https://example.com/very-long-url
Using Dependency Injection
use Mepsd\UrlShortener\UrlShortener;
class MyController
{
public function __construct(
protected UrlShortener $urlShortener
) {}
public function shorten(Request $request)
{
$shortUrl = $this->urlShortener->create($request->url);
return response()->json($shortUrl);
}
}
Create Short URLs
use Mepsd\UrlShortener\Facades\UrlShortener;
// Basic usage
$shortUrl = UrlShortener::create('https://example.com/my-long-url');
// With custom options
$shortUrl = UrlShortener::create('https://example.com/my-long-url', [
'custom_key' => 'my-custom-key', // Custom short URL key
'title' => 'My Link', // Optional title
'track_visits' => true, // Track visit analytics
'is_single_use' => false, // Delete after first use
]);
// Using the alias method
$shortUrl = UrlShortener::shorten('https://example.com/my-long-url');
List URLs
use Mepsd\UrlShortener\Facades\UrlShortener;
// Get paginated list of URLs
$result = UrlShortener::list();
foreach ($result->items as $url) {
echo $url->shortUrl . ' -> ' . $url->destinationUrl;
}
// With pagination
$result = UrlShortener::list(
page: 2,
perPage: 25,
mineOnly: true // Only URLs created by current API token
);
// Check pagination info
echo "Page {$result->currentPage} of {$result->lastPage}";
echo "Total URLs: {$result->total}";
if ($result->hasMorePages()) {
// Fetch next page
}
Get URL Details
use Mepsd\UrlShortener\Facades\UrlShortener;
$shortUrl = UrlShortener::get('abc123');
echo $shortUrl->id;
echo $shortUrl->key;
echo $shortUrl->shortUrl;
echo $shortUrl->destinationUrl;
echo $shortUrl->title;
echo $shortUrl->trackVisits;
echo $shortUrl->isActive;
echo $shortUrl->totalClicks;
echo $shortUrl->uniqueVisitors;
echo $shortUrl->createdAt->format('Y-m-d');
// Using alias
$shortUrl = UrlShortener::find('abc123');
Get URL Statistics
use Mepsd\UrlShortener\Facades\UrlShortener;
// Get stats for last 30 days (default)
$stats = UrlShortener::stats('abc123');
// Get stats for custom period
$stats = UrlShortener::stats('abc123', days: 7);
echo $stats->totalClicks;
echo $stats->uniqueVisitors;
echo $stats->clicksToday;
// Detailed breakdowns
foreach ($stats->browsers as $browser => $count) {
echo "{$browser}: {$count} visits";
}
foreach ($stats->devices as $device => $count) {
echo "{$device}: {$count} visits";
}
foreach ($stats->operatingSystems as $os => $count) {
echo "{$os}: {$count} visits";
}
// Clicks over time
foreach ($stats->clicksOverTime as $day) {
echo "{$day['date']}: {$day['clicks']} clicks";
}
Update URLs
use Mepsd\UrlShortener\Facades\UrlShortener;
// Update specific fields
$shortUrl = UrlShortener::update('abc123', [
'title' => 'New Title',
'is_active' => true,
'track_visits' => false,
]);
// Activate/Deactivate shortcuts
$shortUrl = UrlShortener::activate('abc123');
$shortUrl = UrlShortener::deactivate('abc123');
Delete URLs
use Mepsd\UrlShortener\Facades\UrlShortener;
$deleted = UrlShortener::delete('abc123'); // Returns true on success
Health Check
use Mepsd\UrlShortener\Facades\UrlShortener;
// Get health status
$health = UrlShortener::health();
// Returns: ['status' => 'ok', 'tenant' => 'tenant-id', 'timestamp' => '...']
// Quick check
if (UrlShortener::isHealthy()) {
// API is accessible
}
Dynamic Configuration
use Mepsd\UrlShortener\Facades\UrlShortener;
// Change token at runtime
UrlShortener::setToken('new-api-token')
->create('https://example.com');
// Change base URL at runtime
UrlShortener::setBaseUrl('https://different-shortener.com')
->create('https://example.com');
// Chain configuration
$shortUrl = UrlShortener::setBaseUrl('https://shortener.com')
->setToken('token')
->create('https://example.com');
Creating a New Instance
use Mepsd\UrlShortener\UrlShortener;
// Create a completely new instance with custom config
$shortener = new UrlShortener(
baseUrl: 'https://custom-shortener.com',
apiToken: 'custom-token',
apiVersion: 'v1',
timeout: 60,
retryConfig: ['times' => 5, 'sleep' => 200]
);
$shortUrl = $shortener->create('https://example.com');
Error Handling
The package throws UrlShortenerException for all errors:
use Mepsd\UrlShortener\Facades\UrlShortener;
use Mepsd\UrlShortener\Exceptions\UrlShortenerException;
try {
$shortUrl = UrlShortener::create('https://example.com');
} catch (UrlShortenerException $e) {
// Handle specific error codes
switch ($e->getCode()) {
case 401:
// Unauthorized - invalid API token
break;
case 402:
// Insufficient credits in wallet
break;
case 404:
// URL not found
break;
case 422:
// Validation error
$errors = $e->getErrors();
break;
default:
// Other error
$message = $e->getMessage();
$response = $e->getResponse();
}
}
Data Transfer Objects
The package returns typed DTOs for all responses:
ShortUrl
class ShortUrl {
public readonly int $id;
public readonly string $key;
public readonly string $shortUrl;
public readonly string $destinationUrl;
public readonly ?string $title;
public readonly bool $trackVisits;
public readonly bool $isActive;
public readonly ?int $totalClicks;
public readonly ?int $uniqueVisitors;
public readonly ?DateTimeImmutable $createdAt;
public readonly ?DateTimeImmutable $updatedAt;
}
UrlStats
class UrlStats {
public readonly string $key;
public readonly int $totalClicks;
public readonly int $uniqueVisitors;
public readonly int $clicksToday;
public readonly array $clicksOverTime;
public readonly array $browsers;
public readonly array $devices;
public readonly array $operatingSystems;
public readonly array $referers;
}
PaginatedResult
class PaginatedResult implements Countable, IteratorAggregate {
public readonly array $items;
public readonly int $currentPage;
public readonly int $lastPage;
public readonly int $perPage;
public readonly int $total;
public function hasMorePages(): bool;
public function isEmpty(): bool;
public function isNotEmpty(): bool;
}
API Reference
| Method | Description |
|---|---|
create(string $url, array $options = []) |
Create a new short URL |
shorten(string $url, array $options = []) |
Alias for create() |
list(int $page = 1, int $perPage = 15, bool $mineOnly = false) |
List URLs with pagination |
get(string $key) |
Get URL details |
find(string $key) |
Alias for get() |
stats(string $key, int $days = 30) |
Get URL statistics |
update(string $key, array $data) |
Update a URL |
activate(string $key) |
Activate a URL |
deactivate(string $key) |
Deactivate a URL |
delete(string $key) |
Delete a URL |
health() |
Get API health status |
isHealthy() |
Check if API is healthy |
setToken(string $token) |
Set API token dynamically |
setBaseUrl(string $baseUrl) |
Set base URL dynamically |
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security
If you discover any security-related issues, please email dev@mepsd.com instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.