@@ -347,6 +347,145 @@ $loader = new ArrayLoader([
347347$MediaEmbed->loadProvidersFromLoader($loader, reset: true);
348348```
349349
350+ ### Provider Collection
351+
352+ Get all providers as a filterable collection:
353+
354+ ``` php
355+ use MediaEmbed\Provider\ProviderCollection;
356+
357+ $MediaEmbed = new MediaEmbed();
358+
359+ // Get all providers
360+ $providers = $MediaEmbed->getProviders();
361+ echo count($providers); // e.g., 137
362+
363+ // Filter to specific providers
364+ $subset = $MediaEmbed->getProviders(['youtube', 'vimeo', 'dailymotion']);
365+
366+ // Filter by capabilities
367+ $withIframe = $providers->withIframeSupport();
368+ $withThumbnails = $providers->withThumbnailSupport();
369+
370+ // Iterate over providers
371+ foreach ($providers as $slug => $config) {
372+ echo $config->name . ' (' . $slug . ')' . PHP_EOL;
373+ }
374+
375+ // Chain filters
376+ $filtered = $providers
377+ ->withIframeSupport()
378+ ->whitelist(['youtube', 'vimeo', 'twitch']);
379+ ```
380+
381+ ### Caching
382+
383+ For better performance on repeated requests, use the cache support:
384+
385+ ``` php
386+ use MediaEmbed\Cache\ArrayCache;
387+ use MediaEmbed\Cache\CacheInterface;
388+
389+ // Using the built-in ArrayCache (in-memory, single request)
390+ $cache = new ArrayCache();
391+ $MediaEmbed = new MediaEmbed();
392+ $matcher = $MediaEmbed->getUrlMatcher();
393+ $matcher->setCache($cache);
394+
395+ // The domain index will be cached after first match
396+ $MediaEmbed->parseUrl('https://youtube.com/watch?v=abc');
397+ ```
398+
399+ For persistent caching, implement ` CacheInterface ` with your preferred cache backend (Redis, Memcached, filesystem, etc.):
400+
401+ ``` php
402+ use MediaEmbed\Cache\CacheInterface;
403+ use Psr\SimpleCache\CacheInterface as Psr16Cache;
404+
405+ class Psr16Adapter implements CacheInterface {
406+ public function __construct(private Psr16Cache $cache) {}
407+
408+ public function get(string $key, mixed $default = null): mixed {
409+ return $this->cache->get($key, $default);
410+ }
411+
412+ public function set(string $key, mixed $value, ?int $ttl = null): bool {
413+ return $this->cache->set($key, $value, $ttl);
414+ }
415+
416+ public function delete(string $key): bool {
417+ return $this->cache->delete($key);
418+ }
419+
420+ public function has(string $key): bool {
421+ return $this->cache->has($key);
422+ }
423+ }
424+
425+ // Use with any PSR-16 cache
426+ $cache = new Psr16Adapter($yourPsr16Cache);
427+ $MediaEmbed->getUrlMatcher()->setCache($cache, ttl: 3600);
428+ ```
429+
430+ ### oEmbed Discovery
431+
432+ For URLs not covered by built-in providers, use oEmbed auto-discovery:
433+
434+ ``` php
435+ use MediaEmbed\OEmbed\OEmbedDiscovery;
436+
437+ $discovery = new OEmbedDiscovery();
438+
439+ // Auto-discover and fetch oEmbed data
440+ $response = $discovery->discover('https://example.com/video/123');
441+
442+ if ($response !== null) {
443+ echo $response->title;
444+ echo $response->providerName;
445+
446+ if ($response->hasHtml()) {
447+ echo $response->html; // Ready-to-use embed code
448+ }
449+
450+ if ($response->hasThumbnail()) {
451+ echo $response->thumbnailUrl;
452+ }
453+ }
454+
455+ // With size constraints
456+ $response = $discovery->discover($url, maxWidth: 640, maxHeight: 480);
457+
458+ // Or fetch directly from a known endpoint
459+ $response = $discovery->fetch('https://example.com/oembed?url=...');
460+ ```
461+
462+ The ` OEmbedResponse ` provides typed access to all oEmbed fields:
463+
464+ ``` php
465+ $response->type; // 'video', 'photo', 'link', or 'rich'
466+ $response->version; // oEmbed version (usually '1.0')
467+ $response->title; // Content title
468+ $response->authorName; // Author/creator name
469+ $response->authorUrl; // Author URL
470+ $response->providerName; // Provider name (e.g., 'YouTube')
471+ $response->providerUrl; // Provider homepage
472+ $response->thumbnailUrl; // Thumbnail image URL
473+ $response->thumbnailWidth; // Thumbnail width
474+ $response->thumbnailHeight;// Thumbnail height
475+ $response->html; // Embed HTML (for video/rich types)
476+ $response->width; // Embed width
477+ $response->height; // Embed height
478+ $response->url; // Source URL (for photo type)
479+ $response->cacheAge; // Suggested cache duration in seconds
480+
481+ // Type checks
482+ $response->isVideo();
483+ $response->isPhoto();
484+ $response->isRich();
485+ $response->hasHtml();
486+ $response->hasThumbnail();
487+ ```
488+
350489### Example with BBCode
351490
352491#### Parse video content upon save (db input)
0 commit comments