Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Kayue Essence Bundle Laravel Package

kayue/kayue-essence-bundle

Symfony bundle integrating Essence, a PHP library for extracting media and metadata from web pages. Fetch titles, descriptions, images, and embedded media via Open Graph, Twitter Cards, oEmbed, and other providers—useful for link previews and content cards.

View on GitHub
Deep Wiki
Context7

Getting Started

The first thing to internalize is that this is a Symfony 2 bundle, not a Laravel package. It ships no service provider, no facade, no publishable config, and its composer.json pins symfony/symfony ~2.x with PHP 5.x-era constraints. composer require kayue/kayue-essence-bundle against a Laravel 9+ app will fail resolution. "Leveraging it day-to-day" therefore means porting its wiring into a first-party provider around the underlying essence/essence library, which is framework-agnostic and does the actual work.

Where to look first, in order:

  1. composer.json — confirm the Symfony/PHP constraints so you understand why direct install is a dead end.
  2. DependencyInjection/Configuration.php — the option shape (providers, cache, HTTP client, timeout) is the real artifact; it is essentially the config file you will recreate in Laravel.
  3. Resources/config/services.yml — shows how Essence is instantiated and which collaborators are injected. This is the wiring you port into a service provider.
  4. essence/essence's Essence.php — the API you will actually call: embed(), extract(), getProviders().

Minimal replacement setup:

composer require essence/essence
// app/Providers/EssenceServiceProvider.php
public function register(): void
{
    $this->app->singleton(\Essence\Essence::class, function ($app) {
        return new \Essence\Essence(
            new \Essence\Di\Container('DefaultProvider', [], [
                'cache' => new \App\Essence\LaravelCache($app['cache']->store()),
                'http'  => new \App\Essence\LaravelHttpClient($app['http']),
            ])
        );
    });
}

First use case — replace a pile of hand-rolled YouTube/Vimeo regexes with a single call:

$media = app(\Essence\Essence::class)->embed('https://www.youtube.com/watch?v=39e3KYAmXK4');

if ($media === null) {
    // unsupported provider or discovery failed — fall back to a link card
}

$media->html;          // provider iframe markup
$media->providerName;
$media->type;          // 'video', 'photo', 'rich', ...
$media->thumbnailUrl;

Implementation Patterns

Bind Essence as a singleton and inject by type. Resolve Essence\Essence in controllers, jobs, and Blade components via constructor injection — not app() inline — so tests can swap the binding cleanly.

Implement the two extension points over Laravel's own facilities. Essence ships no framework-aware cache or HTTP client:

  • Cache — adapt Illuminate\Contracts\Cache\Repository to Essence\Cache\CacheInterface (get/set/has). This is the highest-leverage piece: oEmbed discovery fetches the remote page, so an uncached lookup is slow and rate-limit-prone.
  • HTTP — adapt Illuminate\Support\Facades\Http to Essence\Http\ClientInterface, setting a connect timeout and a User-Agent. The bundle injected these as service ids; you inject collaborators in the constructor.

Mirror the bundle's configuration in config/essence.php. Provider allowlists, cache TTL, per-provider params (max width/height), and timeout all belong in config. The bundle's Configuration.php is your checklist.

Persist resolved embeds; never re-resolve on render. Store a row per URL (url, provider, type, html, title, author, thumbnail_url, width, height, fetched_at) and render from the row. Re-resolving on every page view invites throttling and couples your page latency to third parties. Refetch only when fetched_at is stale.

Resolve out-of-band. Do embed() in a queued job triggered when a URL is pasted, not in the request that saves the post. Set Http::timeout(3) and let failures land in a failed_embeds state rather than throwing into the request path.

Render through one Blade component. A single <x-oembed :media="$row" /> emits the provider HTML when present and falls back to a link card built from thumbnail_url and title otherwise. Centralizing output means one sanitization point.

Allowlist providers to skip discovery. Passing a known provider name avoids the discovery fetch entirely — faster, more predictable, and a natural place to enforce policy.

Test with faked HTTP and recorded fixtures. Http::fake() with canned oEmbed JSON per provider keeps your suite offline and lets you assert fallback behavior for the null case.

Gotchas and Tips

SSRF is the highest-severity risk here. User-supplied URLs are fetched server-side. Allowlist providers, reject private/reserved IP ranges post-DNS-resolution, and add egress controls. This is not optional if you accept arbitrary URLs.

Sanitize oEmbed HTML before output. $media->html can contain iframes and, from a compromised or malicious provider, scripts. Run it through an HTML sanitizer and consider iframe sandbox attributes regardless of provider trust.

embed() returns null, it does not throw — on unsupported URLs or discovery failure. Every call site needs a fallback path; a null dereference in a Blade partial is the most common production bug with this pattern.

Never resolve inline in a hot request path. Provider 5xx's and timeouts must degrade to a plain link card, never a 500. Cache negative results (with a shorter TTL) so you do not hammer a failing provider.

Cache with a sane TTL. 24h is a good default; oEmbed payloads rarely change. Cache the resolved media object, not the HTTP response.

Watch the Essence API version. The container/DI signature differs across Essence releases, and older Symfony 2-era examples won't match current essence/essence. Pin a version and read its README rather than the bundle's docs.

Provider HTML/discovery changes silently. Monitor resolution failure rate per provider; a provider changing its endpoint or discovery markup shows up as a spike, not a hard error.

Composer constraint hygiene is the medium-term cost. Essence may pin Guzzle or PSR interfaces that conflict with a future framework upgrade. Record the fork-or-replace trigger if upstream goes quiet, and budget any fork as an owned artifact.

Debugging tip. Log the resolved provider name and HTTP status per attempt — that separates "provider not supported" from "provider reachable but returned garbage," which determines whether you fix config or the fallback UX.

Extension point worth knowing. Custom providers can be registered in the Essence container; the bundle exposed this only through Symfony config, but in Laravel it's a straightforward entry in your config/essence.php and a matching provider registration in the service provider — useful when a vendor isn't in Essence's built-in list.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo