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

Craftable Media Laravel Package

dejwcake/craftable-media

Media library and file management for the Craftable admin panel: upload, browse, organize, and attach images and files to your Eloquent models with a ready-made admin UI, keeping media handling consistent across your Laravel application.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What this actually is (scope of evidence). The package is not a standalone media library. It is a fork of brackets/media (namespace Brackets\Media), part of the Craftable admin ecosystem, and it is a thin wrapper over spatie/laravel-medialibrary. That gives us three layers to reason about: Spatie's media library (data model, conversions, disk abstraction — battle-tested, widely deployed), brackets/media (Craftable-specific ergonomics: fluent MediaCollection rules, request-driven add/update/delete, thumbnails, upload and private-file controllers), and dejwcake/craftable-media (this fork, at 2.0.1, zero stars). The Score: 16 is star-driven and therefore not informative on its own; the decision-relevant signals are the transitive dependency and the CI/QA posture described in AGENTS.md.

Architecture fit. Conventional Laravel service-provider package: binds container services, attaches to Eloquent models via HasMediaCollectionsTrait, persists to configured filesystem disks, and exposes HTTP controllers for upload and private file viewing. Adoption is incremental — one model, one collection — with no imposed architectural pattern. Two design details matter for us: AutoProcessMediaTrait hooks the saving event, so conversions can be triggered by any model write (a coupling point between our write path and media processing); and the package ships its own controllers and routes, which means it owns part of our HTTP attack surface, including a private-file viewer.

Integration feasibility. Composer install, publish/verify migrations, configure a disk. Mechanically easy. The gate is environmental, not structural: the documented toolchain is PHP ^8.5, Laravel 13, PHPUnit 13, Orchestra Testbench 11. Unless our target application is already on Laravel 13, this fork will not resolve — and if we back-port or pin to an older line, we are maintaining a fork of a fork. That is the first thing to establish and it is a hard gate, not a preference.

Technical risk. Low-to-moderate, with one severe supply-chain item.

  • Lock-in (lower than it appears). Because persistence, the media table, and conversion machinery belong to Spatie, the exit path is materially cheaper than a bespoke package: we can migrate to spatie/laravel-medialibrary directly and keep the data, disks, and generated URLs largely intact. The Craftable layer is ergonomics, not the schema. This substantially de-risks the "sticky dependency" concern.
  • Supply chain (high). A zero-star fork under a personal namespace, forked from another package, wrapping a third. Two maintenance hops between us and the code that matters. We need to know who dejwcake is to us and whether this fork exists because of upstream changes we depend on.
  • Version ambiguity (flag). 2.0.1 conveys nothing about the 2.0.0 breaking surface, and we have no upstream changelog to diff the fork against. Divergence from brackets/media is unknown and unquantified.
  • Security surface (moderate). The private-file controller is access control implemented inside a dependency. That must be read, not assumed — a flaw there is an IDOR, not a broken image.
  • Code hygiene (positive but bleeding-edge). declare(strict_types=1), no facades, final readonly, #[Override], phpcs/phpstan/phpmd/phpunit all green as definition-of-done, and CI across MariaDB and PostgreSQL. That is a stronger engineering posture than most zero-star packages. It also includes a documented PHP 8.5.3 segfault workaround around #[Override] on trait methods, which tells you the toolchain is being absorbed at the leading edge — fine for a greenfield app, awkward for a regulated or long-LTS estate.

Key questions.

  1. What Laravel and PHP versions does our target application run today, and is a Laravel 13 upgrade on the roadmap? If no, this is disqualified as-is.
  2. Who is the releasing party relative to us, why does this fork exist, and what is the support commitment? Is it a stopgap pending an upstream fix?
  3. What is the diff against brackets/media and the pinned Spatie major? Can we diff it, and will the fork rebase or is it diverging permanently?
  4. Does the private-file controller enforce an authorization policy we can hook, or is access a check inside the package?
  5. Are conversions synchronous by default, and is a queue worker a hard prerequisite for our intended use?
  6. Which Spatie major is pinned, and what is the upgrade path when Spatie ships a breaking change through a wrapper two levels removed?

Integration Approach

Stack fit. This is the decisive constraint. The package targets PHP 8.5 / Laravel 13 — effectively next-generation. Most enterprise estates are on Laravel 10/11 with PHP 8.2/8.3, where this fork will not install. Confirm our runtime before any other work; everything below assumes either a Laravel 13 target or a willingness to accept the fork risk of back-porting. The CI matrix (PostgreSQL and MariaDB, healthchecked compose, dedicated laravel DB user) is genuinely useful evidence that persistence is exercised on both engines — relevant if we standardise on Postgres and are wary of MySQL-only assumptions.

Migration path. Treat as a contained pilot with an explicit go/no-go, not a platform decision.

  1. Resolve the runtime gate. If we are not on Laravel 13, stop and evaluate spatie/laravel-medialibrary directly instead — we would be reimplementing less than the wrapper's surface suggests.
  2. Read the private-file controller and the saving-hook trait before writing any code. These are the two places where a dependency can hurt us.
  3. Pin the exact version (not ^2.0) and install in one non-critical environment.
  4. Publish and review migrations before running; confirm the polymorphic columns and indexes in Spatie's media table match our modelling conventions, since that table is the part we keep forever.
  5. Attach the trait to one low-risk model with one collection; configure one disk; verify upload, retrieval, URL generation, and deletion end-to-end.
  6. Enable one conversion and confirm it dispatches and completes on a queue worker — do not accept the default if the default is synchronous.
  7. Only then expand model-by-model.

Compatibility. No breaking changes declared in 2.0.1 (app() → Container::getInstance()->make() in three classes, upgrade action "nothing to do"), and the two idioms resolve the same singleton in a bootstrapped app, so the patch itself is safe. Note a small internal inconsistency worth a question rather than a concern: the conventions document permits app() in models and traits, yet 2.0.1 removed it from ProcessMediaTrait — the changelog and the stated conventions are out of step, which suggests the doc trails the code. The real compatibility exposures are environmental: filesystem drivers and permissions, the image/processing binary for conversions, queue driver semantics, and Octane/long-running-worker behaviour given the container-resolution change. Run our existing suite against the pinned version rather than relying on the release note.

Sequencing. Two independent tracks. Track A: if we are already on Laravel 13, land 2.0.1 as a routine pinned dependency and pilot on one model — days, not weeks. Track B: if we are not on Laravel 13, the wrapper-adoption decision is blocked, and the correct next artefact is a one-page comparison of "adopt Spatie directly" versus "adopt this fork," because the irreversible item — data in the media table and objects on a disk — is identical either way, while the maintainable surface is smaller with Spatie alone.

Operational Impact

Maintenance. The QA posture is the strongest signal in the package. A change is only "done" when phpcs, phpstan, phpmd and the test suite are green; tests are organised per-method; the README documents per-database test commands and a full QA one-liner; everything runs in Docker. That is better than most commercial packages and means our engineers can validate a bump locally in minutes. Ongoing cost to us is a pinned-version bump per release plus a periodic re-verification of conversions and disk config — low and largely automatable. The unbounded cost is fork divergence: with no upstream changelog to diff, every bump is a review rather than a read.

Support. The weakest dimension and the one that decides whether this becomes load-bearing. Zero stars, personal namespace, fork-of-a-fork — expect best-effort, single-maintainer, unstated security response times. If this fork exists to carry a patch our product depends on, we own that patch in practice and should say so out loud. Mitigation is cheap here: because the schema and storage layout belong to Spatie, a documented fallback to Spatie directly (or a thin in-house read path over the same media table) is a realistic hedge to scope now rather than during an incident. Write that fallback down before go-live.

Scaling. Read-path cost is negligible — URL generation and collection lookups are cheap. Scaling pressure sits in conversions and storage. Conversions are CPU-bound and must run off-request on queue workers; the saving-hook trait makes it easy to accidentally trigger them inline on a model write, which will appear as request-latency spikes and worker starvation under upload bursts. Size worker capacity to peak upload volume, put a CDN in front of generated URLs so the app is not in the delivery path, and add a reconciliation job early for orphaned objects — rows deleted with files left on disk, or the inverse — which is the predictable long-run storage-growth problem.

Failure modes. (a) Runtime mismatch surfacing as an unresolvable composer graph rather than a clear error. (b) Private-file authorization assumed rather than verified — an access-control defect, not a broken image. (c) Disk misconfiguration or missing credentials degrading silently into broken URLs, invisible until users report it. (d) Conversion failures leaving records pending with no alert. (e) Partial writes on large uploads. (f) Silent divergence after a fork upgrade with nothing to diff against. All are covered by one control: an end-to-end smoke test in CI that uploads, converts, fetches through the private controller as an unauthorised user, and deletes, against a real storage driver.

Ramp-up. Low for anyone fluent in Laravel — trait-plus-service-provider needs no new mental model, and the container-resolution refactor is invisible to callers. Budget roughly half a day for a first integration on a single model, plus a day each if conversions or a non-local object-store disk are in scope. The larger cost is documenting our conventions — disk names, collection names, conversion presets — so the package is applied consistently instead of reinvented per feature. If the team is not already on PHP 8.5, add the toolchain upgrade to the estimate; that, not the package, is the real work.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib