dekalee/cdn77
PHP client for the CDN77 API. Wraps endpoints in Query classes to list, create and delete resources, purge resources or specific files, and fetch resource logs. Suitable for integrating CDN77 management actions into your app (incl. Symfony via bundle).
Installation:
composer require dekalee/cdn77
Configuration:
Create a Laravel service provider to bind the Query class and configure CDN77 credentials:
// app/Providers/Cdn77ServiceProvider.php
namespace App\Providers;
use Dekalee\Cdn77\Query;
use Illuminate\Support\ServiceProvider;
class Cdn77ServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(Query::class, function ($app) {
return new Query(
config('cdn77.zone_id'),
config('cdn77.api_key'),
config('cdn77.endpoint', 'https://api.cdn77.com')
);
});
}
}
Add to config/app.php under providers.
First Use Case: Purge a file after upload in a controller or service:
use Illuminate\Support\Facades\App;
$cdnQuery = App::make(\Dekalee\Cdn77\Query::class);
$cdnQuery->purgeFile('/path/to/file.jpg');
Purging Assets:
$cdnQuery->purgeFile('path/to/file.jpg');
$cdnQuery->purgeResources(['/path/to/file1.jpg', '/path/to/file2.jpg']);
storage:uploaded) in EventServiceProvider:
public function boot()
{
Storage::disk('public')->addListener('uploaded', function ($event) {
$cdnQuery = app(\Dekalee\Cdn77\Query::class);
$cdnQuery->purgeFile($event->path);
});
}
Resource Management:
$resources = $cdnQuery->listResources();
$cdnQuery->createResource('new-zone', ['origin' => 'https://example.com']);
$logs = $cdnQuery->getResourceLog('zone-id', 10); // Last 10 entries
Integration with Laravel Storage:
Use the Storage facade to trigger purges post-upload:
use Illuminate\Support\Facades\Storage;
Storage::disk('public')->put('file.jpg', $content);
app(\Dekalee\Cdn77\Query::class)->purgeFile('file.jpg');
Facade for Cleaner Usage: Create a facade to simplify calls:
// app/Facades/Cdn77.php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Cdn77 extends Facade
{
protected static function getFacadeAccessor()
{
return \Dekalee\Cdn77\Query::class;
}
}
Usage:
Cdn77::purgeFile('file.jpg');
Configuration:
Store credentials in .env:
CDN77_ZONE_ID=your_zone_id
CDN77_API_KEY=your_api_key
Load in config/cdn77.php:
return [
'zone_id' => env('CDN77_ZONE_ID'),
'api_key' => env('CDN77_API_KEY'),
'endpoint' => env('CDN77_ENDPOINT', 'https://api.cdn77.com'),
];
Symfony Dependencies:
HttpClient. Replace it with Laravel’s Http facade or Guzzle:
// In Query class constructor, replace:
$client = new Client(['base_uri' => $endpoint]);
// With:
$client = new \Illuminate\Support\Facades\Http;
Error Handling:
Query class to throw Laravel exceptions:
try {
$cdnQuery->purgeFile('file.jpg');
} catch (\Dekalee\Cdn77\Exception\Cdn77Exception $e) {
throw new \RuntimeException('CDN purge failed: ' . $e->getMessage());
}
Rate Limiting:
Retry helper:
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Retry\Retryable;
Retryable::retry(3, function () {
Http::post('cdn77-endpoint', ['data' => $payload]);
});
Configuration Quirks:
config/cdn77.php is published and updated. Default values may not match your CDN77 setup.Log API Calls: Add middleware to log requests/responses:
// app/Http/Middleware/LogCdnRequests.php
public function handle($request, Closure $next)
{
if ($request->isCdn77()) {
\Log::info('CDN77 Request', $request->all());
}
return $next($request);
}
Validate API Responses:
CDN77 may return non-200 responses (e.g., 404 for invalid zones). Parse responses explicitly:
$response = $cdnQuery->listResources();
if ($response->getStatusCode() !== 200) {
\Log::error('CDN77 API error:', $response->getBody());
}
Custom Query Builder:
Extend the Query class to add Laravel-specific methods:
class LaravelCdn77Query extends Query
{
public function purgeAfterUpload($path)
{
$this->purgeFile($path);
event(new AssetPurged($path));
}
}
Queueable Jobs: Offload CDN operations to queues to avoid blocking requests:
// app/Jobs/PurgeCdnJob.php
class PurgeCdnJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable;
public $path;
public function handle()
{
app(\Dekalee\Cdn77\Query::class)->purgeFile($this->path);
}
}
Usage:
PurgeCdnJob::dispatch('file.jpg')->onQueue('cdn');
Event Listeners:
Trigger CDN purges on model events (e.g., saved):
// app/Listeners/PurgeAssetOnUpload.php
public function handle($event)
{
if ($event->asset->isUploaded()) {
app(\Dekalee\Cdn77\Query::class)->purgeFile($event->asset->path);
}
}
Batch Purges: For large numbers of files, use bulk endpoints or chunk requests:
$files = ['file1.jpg', 'file2.jpg', /* ... */];
array_chunk($files, 100)->each(function ($chunk) {
$cdnQuery->purgeResources($chunk);
});
Fallback Mechanism: Implement a fallback to serve assets directly if CDN fails:
try {
$cdnQuery->purgeFile('file.jpg');
} catch (\Exception $e) {
\Log::warning('CDN purge failed, serving from origin: ' . $e->getMessage());
}
Testing:
Mock the Query class in tests:
$mock = Mockery::mock(\Dekalee\Cdn77\Query::class);
$mock->shouldReceive('purgeFile')->once();
$this->app->instance(\Dekalee\Cdn77\Query::class, $mock);
How can I help you explore Laravel packages today?