yoelpc4/laravel-cloudinary
A Laravel integration for Cloudinary that simplifies uploading, managing, and delivering images and videos through Cloudinary’s API. Configure credentials, generate transformations and URLs, and handle media storage within familiar Laravel conventions.
Architecture fit. The package occupies a narrow but legitimate seam: it registers a Cloudinary-backed disk with Laravel's Storage facade, so application code calls Storage::disk('cloudinary')->put(...) rather than the Cloudinary SDK directly. That is the right shape for Laravel — it preserves the framework's filesystem abstraction and keeps vendor calls out of domain code. The architectural concern is semantic, not structural: Laravel's filesystem contract assumes a path-keyed blob store (write, read, delete, list, url, temporaryUrl, exists, size, mimeType), while Cloudinary is an asset-management and transformation CDN keyed on public_id + resource_type + delivery type. Every filesystem operation has to be projected onto that model, and some projections are lossy. Filesystem-as-CDN is a common pattern, but it is an adapter over a different abstraction, not a drop-in S3 substitute.
Integration feasibility. Mechanically low effort: composer require, publish config, add a disk entry to config/filesystems.php, set CLOUDINARY_URL or discrete credentials. The real work is a behavior-verification matrix, not installation. Assume one to two engineering days for a spike plus a day of integration tests, contingent on which operations the product actually uses.
Technical risk.
get), directory listing, and metadata (size, mimeType) may be unimplemented, approximate, or Admin-API-backed and paginated. Products that only write and serve URLs are fine; products that treat storage as a general filesystem are not.resource_type=raw, which changes URL and deletion semantics. Confirm this against actual payload types before committing.composer.json corresponds to a real, reviewable commit before depending on it.Key questions for the maintainer (or to answer via source review).
League\Flysystem\FilesystemAdapter v3?get, readStream, listContents, size, mimeType, temporaryUrl?public_id prefixes), and how is resource_type / delivery type selected per disk?temporaryUrl backed by Cloudinary signed URLs, and what is the expiry behavior?resource_type at delete time)?Stack fit. Best fit is a Laravel 10/11 application on PHP 8.1+ that stores user-generated images or video and serves them through a CDN. Poor fit for applications using storage as a general-purpose filesystem, for compliance workloads needing object-lock or immutability guarantees, or for teams already standardized on S3/GCS where Cloudinary would be a second storage vendor rather than a CDN layer.
Migration path. Greenfield is low-risk: configure the disk, write integration tests against the operation matrix, ship. Brownfield S3→Cloudinary is a content migration, not a config swap — URLs change, transformation behavior changes, and any stored absolute URLs in the database need rewriting. If Cloudinary is being added purely as a delivery/transformation layer, the lower-risk pattern is to keep S3 as the system of record and use Cloudinary's fetch/auto-upload rather than migrating the filesystem disk at all. Decide explicitly which of these two you are doing before writing code.
Compatibility. Pin the package version exactly, record the supported Laravel/Flysystem matrix in the repo, and add a CI job that runs the storage test suite against the next Laravel major ahead of upgrade season. Treat this package as a platform dependency with a named owner, not a utility.
Sequencing.
MediaStore) so the Cloudinary disk is swappable; do not let Storage::disk('cloudinary') appear in domain code.Maintenance. The realistic maintenance posture is "adopt with a fork plan." Budget for periodic source review at each Laravel major, and keep the internal wrapper thin enough that replacing the adapter costs days, not a quarter. Do not plan on upstream responsiveness.
Support. No SLA, no vendor of record, no security advisory channel. Cloudinary supports Cloudinary; it does not support this package. Any incident bridges both vendors and lands on your team.
Scaling. Two cost/throughput axes matter more than raw storage: transformation and bandwidth charges (which scale with traffic, not bytes stored) and Admin API rate limits (which bite on listing and bulk deletion, since those are paginated control-plane calls, not data-plane operations). Upload concurrency and large-file handling — including whether chunked upload is supported — should be load-tested at expected peak before launch, not after.
Failure modes to instrument.
resource_type mismatch on delete, producing silent non-deletion and storage creep.public_id without CDN invalidation, serving stale assets.Ramp-up. Expect one to two days for an engineer fluent in Laravel to be productive, plus a half-day of Cloudinary concept training (public_id, resource_type, delivery types, transformations) for anyone touching media configuration. The team must understand both abstractions to debug this layer — that dual-knowledge requirement is the hidden cost of the package, and the reason the internal wrapper and operation-matrix tests are worth the modest upfront spend.
How can I help you explore Laravel packages today?