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

Youtube Laravel Package

cable8mm/youtube

cable8mm/youtube is a Laravel/PHP package for integrating YouTube content into your app. It provides convenient helpers for parsing YouTube URLs, extracting video IDs, and generating embed and thumbnail links, making it easy to work with videos in Blade views or application code.

View on GitHub
Deep Wiki
Context7

Getting Started

  • composer require cable8mm/youtube — the service provider and facade are auto-discovered, so there is usually nothing to register in config/app.php.
  • Look first at the package's config/ and its service provider (vendor/cable8mm/youtube/src/...ServiceProvider.php). Publish config only if you need to override transport/cache/locale behaviour: php artisan vendor:publish --provider="Cable8mm\Youtube\...ServiceProvider".
  • v5.1.1 changed the internal shape of the package (see Gotchas). Before writing new code, open the installed src/ directory rather than copying snippets from older blog posts or the pre-5.1 README — the old monolithic Youtube class is now split into a client, a decoder, and resource objects.
  • First use case: a "paste a YouTube link, get its metadata" flow. Take a user-supplied URL, resolve it through the client, and read the resulting resource:
use Cable8mm\Youtube\Facades\Youtube; // verify exact facade namespace in 5.1.x

$video = Youtube::get($request->input('url'));

$video->title;
$video->duration;     // check whether seconds or formatted string
$video->thumbnail;

Persist the normalised fields on your model and you have the classic "link preview / video card" feature working in an afternoon.

Implementation Patterns

Inject the client, don't reach for the facade. The v5.1.1 split into client/decoder/resources exists precisely so you can type-hint the client in a constructor and let the container resolve it. This makes unit testing trivial and survives future internal reshuffles better than static calls scattered through controllers.

final class VideoMetadataService
{
    public function __construct(private \Cable8mm\Youtube\Client $client) {}

    public function forUrl(string $url): VideoData
    {
        $resource = $this->client->get($url);

        return new VideoData(
            id: $resource->id,
            title: $resource->title,
            duration: (int) $resource->duration,
        );
    }
}

Map the package resource to your own DTO. Never let the package's resource object leak into Blade templates or API responses. Extract the handful of fields you actually use into your own value object or Eloquent cast. When the package renames a property, you fix one mapper instead of forty views.

Normalise URLs before calling. Accept youtu.be/…, /shorts/…, /embed/…, /live/…, and URLs with ?t=/&list= noise, then reduce to the bare video ID. A small YoutubeUrl::videoId($input) helper at the edge of your app keeps the client call predictable and lets you reject junk before it costs you a request.

Cache aggressively, keyed by video ID. Public video metadata changes rarely. Cache::remember("yt:{$id}", now()->addHours(6), fn () => $service->forUrl($url)) cuts latency and dodges throttling on list pages that render many thumbnails.

Push bulk work onto the queue. Importing a channel, backfilling thumbnails, or re-checking dead links should be a job with $tries, backoff(), and failed() handling. One job per video ID, not one job for a list — you get per-item retries and useful failure records.

Wrap calls in a single boundary with your own exception type. Catch whatever the client throws (network, decode, unsupported URL) and rethrow as VideoUnavailableException. Your controllers and jobs then never need to know the package's exception hierarchy — which is exactly the kind of thing a refactor release like 5.1.1 can quietly rearrange.

Testing. Bind a fake implementation of the client interface (or a stub decoder, if the package exposes one) in the container during tests. Because the decoder is now a separate concern, you can also unit-test parsing against a stored fixture response without any HTTP at all — a genuine improvement over the pre-5.1 monolithic design.

Gotchas and Tips

  • A patch release (5.1.1) performed a structural refactor. Semver says nothing here should break, but splitting one class into three commonly breaks: subclasses of Youtube, instanceof checks, container bindings that resolved the concrete class, and PHPUnit mocks of the facade root. Run your suite and grep for extends Youtube and new Youtube( before deploying. If you subclassed anything, pin 5.1.0 until you've migrated.
  • Five bugs were fixed in this release. If you have workarounds in your codebase — regex hacks for a URL form, manual str_replace on a duration, a guarded isset() on a property that was sometimes missing — search for them and remove them; they may now be actively wrong.
  • Duration format is the classic trap. Some YouTube wrappers return seconds, others PT1H2M3S (ISO 8601), others a pre-formatted string. Don't assume; verify once and store your canonical form (integer seconds) in the database. Formatting belongs in your presenter.
  • Deleted, private, age-restricted, and region-blocked videos all fail differently. Decide deliberately: for a stored link, keep the row and mark it unavailable rather than throwing on render. A dead embed should degrade to a placeholder, not a 500.
  • YouTube is not a stable API. Anything that scrapes player response data will break when YouTube ships changes. Keep the package reasonably current, keep a fixture-based test so you notice breakage, and never let a metadata failure block the primary user action.
  • Extension points. With the decoder now isolated, prefer swapping/binding the decoder (or the underlying transport) in a service provider over copying package code into your app — that's the seam 5.1.1 opened up.
  • Debugging empty results. Dump the raw decoder output before blaming your mapping; the resource layer may be filtering fields it considers absent. Also confirm the HTTP layer has a user agent and isn't getting a consent/redirect page instead of video data.
  • Config cache. If you publish and edit the config, remember php artisan config:clear locally — a stale cached config is the usual reason "the package ignores my setting".
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.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core