PHPackages                             glueful/cdn - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Caching](/categories/caching)
4. /
5. glueful/cdn

ActiveGlueful-extension[Caching](/categories/caching)

glueful/cdn
===========

CDN / edge-cache integration for Glueful (edge headers, purge, provider adapters).

v1.0.0(2d ago)00MITPHPPHP ^8.3

Since Jun 7Pushed 2d agoCompare

[ Source](https://github.com/glueful/cdn)[ Packagist](https://packagist.org/packages/glueful/cdn)[ Docs](https://github.com/glueful/cdn)[ RSS](/packages/glueful-cdn/feed)WikiDiscussions main Synced 2d ago

READMEChangelog (1)Dependencies (4)Versions (3)Used By (0)

CDN / Edge Cache Extension for Glueful
======================================

[](#cdn--edge-cache-extension-for-glueful)

Overview
--------

[](#overview)

CDN adds edge-cache integration to your Glueful application: it generates edge cache-control headers, purges cached content (by URL, by tag, or all), and ships a pluggable provider-adapter system so you can target Cloudflare, Fastly, or any custom CDN.

It plugs into the framework through the `Glueful\Cache\Contracts\EdgeCacheInterface` seam: installing the extension binds that interface to a real edge-cache purger, and the framework's response caching (`ResponseCachingTrait`) consumes `generateCacheHeaders()` through the same interface automatically — no app code change required. When no CDN provider is configured, the extension degrades gracefully to a disabled no-op so response handling keeps working unchanged.

Features
--------

[](#features)

- **Edge cache headers**: generates cache-control headers for edge-cached responses, consumed automatically by the framework's response caching
- **Cache purging**: purge by URL, by tag, or purge everything, through the configured provider adapter
- **Pluggable adapters**: a `provider name → adapter class` map lets you target Cloudflare, Fastly, or any custom CDN
- **Third-party adapters**: any package can register its own adapter by merging an entry into the `cdn.adapters` map
- **Degrade-to-disabled**: never throws on misconfiguration — silently no-ops (exactly like a null edge cache) when no valid provider resolves
- **`cache:purge` command**: CLI purging by URL, tag, or all
- **Seam-based**: binds the core `EdgeCacheInterface`; the framework works with or without the extension installed
- **Configurable**: provider, TTL, and per-route rules via the `cdn` config + `EDGE_CACHE_*` env

Installation
------------

[](#installation)

### Installation (Recommended)

[](#installation-recommended)

**Install via Composer**

```
composer require glueful/cdn

# Rebuild the extensions cache after adding new packages
php glueful extensions:cache
```

Composer discovers packages of type `glueful-extension`, but **installing does not auto-enable** them — the provider must be added to `config/extensions.php`'s `enabled` allow-list. The CLI does that for you:

```
# Enable (adds the provider FQCN to config/extensions.php + recompiles the cache)
php glueful extensions:enable cdn

# Disable (removes it)
php glueful extensions:disable cdn
```

In production, manage the `enabled` list in config and run `php glueful extensions:cache` in your deploy step. The extension ships no migrations.

### Local Development Installation

[](#local-development-installation)

To develop the extension locally, register it as a Composer **path repository** in your app's `composer.json`, then require and enable it:

```
// composer.json
"repositories": [
    { "type": "path", "url": "extensions/cdn", "options": { "symlink": true } }
]
```

```
composer require glueful/cdn:@dev
php glueful extensions:enable cdn
```

Entries in `config/extensions.php` are plain string FQCNs (no `::class`) — prefer `extensions:enable` over editing by hand.

### Verify Installation

[](#verify-installation)

```
php glueful extensions:list
php glueful extensions:info cdn
php glueful extensions:diagnose
```

Post-install checklist:

- Rebuild cache after Composer operations: `php glueful extensions:cache`
- Confirm the seam is bound: resolving `Glueful\Cache\Contracts\EdgeCacheInterface` yields `Glueful\Extensions\Cdn\EdgeCachePurger`
- Set `EDGE_CACHE_ENABLED=true` and a `EDGE_CACHE_PROVIDER` mapped in `cdn.adapters` to activate purging

Configuration
-------------

[](#configuration)

Configuration is loaded from the extension's `config/cdn.php` and merged under the `cdn` key by the service provider. It reads the standard `EDGE_CACHE_*`environment variables:

```
return [
    // Master switch for edge caching.
    'enabled' => env('EDGE_CACHE_ENABLED', false),

    // CDN provider name. EMPTY by default — no vendor bias is shipped.
    // Must match a key in the `adapters` map below to resolve an adapter.
    'provider' => env('EDGE_CACHE_PROVIDER', ''),

    // Default TTL (seconds) for edge-cached responses.
    'default_ttl' => env('EDGE_CACHE_TTL', 3600),

    // Route-specific cache rules.
    'rules' => [
        // 'home' => ['ttl' => 600, 'vary_by' => ['Accept-Encoding']],
    ],

    // Provider name -> adapter class map (see "Registering an adapter").
    'adapters' => [],
];
```

`EdgeCachePurger` has its configuration **injected** (the `CdnServiceProvider`factory passes `config($context, 'cdn', [])`), so the `cdn` config key is the single source of truth and the purger stays unit-testable with any config array.

### Registering an adapter

[](#registering-an-adapter)

Provider resolution is driven by two config values:

1. **`cdn.provider`** — the active provider *name* (a string).
2. **`cdn.adapters`** — a `name => adapter-class` map.

On construction the purger looks up `adapters[provider]`, requires the class to exist and implement `CDNAdapterInterface`, and instantiates it with the full `cdn` config array. Enable an adapter by mapping its name to its class and selecting it:

```
// config/cdn.php
'provider' => 'cloudflare',
'adapters' => [
    'cloudflare' => \Glueful\Extensions\Cdn\Adapters\CloudflareAdapter::class,
],
```

### Third-party adapters

[](#third-party-adapters)

Any package can ship its own adapter. It registers by **merging its `name => class` entry into `cdn.adapters`** — for example from its own `ServiceProvider::register()`:

```
public function register(ApplicationContext $context): void
{
    $this->mergeConfig('cdn', [
        'adapters' => [
            'acme' => \Acme\Cdn\AcmeAdapter::class,
        ],
    ]);
}
```

The user then selects it by setting `EDGE_CACHE_PROVIDER=acme` (or `cdn.provider => 'acme'`). The adapter class must implement `Glueful\Extensions\Cdn\Adapters\CDNAdapterInterface` (extending `AbstractCDNAdapter` is the easy path).

### Degrade-to-disabled behavior

[](#degrade-to-disabled-behavior)

`EdgeCachePurger` **never throws** during adapter resolution. It silently degrades to a disabled state (every method no-ops exactly like a null edge cache) when:

- `cdn.provider` is unset/empty *(normal "off" config — not logged)*;
- `cdn.provider` names a key absent from `cdn.adapters` *(not logged)*;
- the mapped class does not exist, is not a `CDNAdapterInterface`, or its constructor throws *(logged as a warning via the PSR-3 logger, falling back to `error_log`)*.

While disabled: `isEnabled()` → `false`, `getProvider()` → `null`, `generateCacheHeaders()` → `[]`, and all purge calls → `false`. This means misconfiguration never breaks response handling. `isEnabled()` additionally requires `cdn.enabled` to be truthy *and* an adapter to have resolved.

Usage
-----

[](#usage)

### Purging via the container

[](#purging-via-the-container)

```
use Glueful\Cache\Contracts\EdgeCacheInterface;

$edge = container($context)->get(EdgeCacheInterface::class);

if ($edge->isEnabled()) {
    $edge->purgeUrl('https://example.com/page');
    $edge->purgeByTag('products');
    $edge->purgeAll();
}
```

Response caching consumes `generateCacheHeaders()` through the same interface automatically — no app code change is needed once the extension is installed and a provider is configured.

### Purging via the CLI

[](#purging-via-the-cli)

```
php glueful cache:purge --all
php glueful cache:purge --url=https://example.com/page
php glueful cache:purge --tag=products
```

Requirements
------------

[](#requirements)

- PHP 8.3 or higher
- Glueful 1.52.0 or higher

License
-------

[](#license)

MIT — licensed consistently with the Glueful framework.

Support
-------

[](#support)

For issues, feature requests, or questions, please create an issue in the repository.

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance99

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity49

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

2d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/95650726?v=4)[msowah](/maintainers/msowah)[@msowah](https://github.com/msowah)

---

Top Contributors

[![MichaelSowah](https://avatars.githubusercontent.com/u/24699905?v=4)](https://github.com/MichaelSowah "MichaelSowah (10 commits)")

---

Tags

cachecdnedge cacheglueful

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP\_CodeSniffer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/glueful-cdn/health.svg)

```
[![Health](https://phpackages.com/badges/glueful-cdn/health.svg)](https://phpackages.com/packages/glueful-cdn)
```

###  Alternatives

[psr/simple-cache

Common interfaces for simple caching

8.1k757.1M2.5k](/packages/psr-simple-cache)[psr/cache

Common interface for caching libraries

5.2k712.8M1.6k](/packages/psr-cache)[react/cache

Async, Promise-based cache interface for ReactPHP

444124.5M43](/packages/react-cache)[nexxai/laravel-cfcache

A handful of Cloudflare cache helpers for Laravel

13011.9k](/packages/nexxai-laravel-cfcache)[beste/in-memory-cache

A PSR-6 In-Memory cache that can be used as a fallback implementation and/or in tests.

2514.6M10](/packages/beste-in-memory-cache)[spekkionu/assetcachebuster

Prefixes asset urls with a unique hash which will allow invalidation of asset files cached by the browser.

3243.4k](/packages/spekkionu-assetcachebuster)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
