saro0h/media-api-bundle
Symfony bundle that adds a REST API for media management, including upload, listing, retrieval, and deletion of media files and metadata. Configurable storage and Doctrine integration simplify adding media endpoints to your application.
Note up front: despite the name pattern, this is a Symfony bundle (...Bundle, PSR-4 under Saro0h\MediaApiBundle), not a Laravel package. There is no service provider, no config/mediaapi.php, no publishable migrations. If you're a Laravel dev, mentally map the workflow to: install a Composer dep → register it in the kernel/bundles.php → configure → hit a route.
composer require saro0h/media-api-bundle
Saro0h\MediaApiBundle\MediaApiBundle::class => ['all' => true] to config/bundles.php.new Saro0h\MediaApiBundle\MediaApiBundle() to AppKernel::registerBundles().src/Resources/config/routes.xml (or routing.yaml) first. With 12 stars and no docs, the routes file is the API surface. Look for the controller it points at and the HTTP verb/path (typically something like POST /api/media or /media/upload).DependencyInjection/Configuration.php for the real config keys — this is where upload directory, allowed MIME types, and max size are usually defined.curl -F "[email protected]" http://localhost:8000/<route-from-routes.xml> and see if a 200 with a stored path/URL comes back. That round-trip tells you more than any README will.Consume the JSON endpoint from a client. If the bundle exposes a controller, the intended usage is a thin client: authenticate (whatever security is configured on that route), multipart/form-data POST, parse the JSON response ({ "url": ..., "id": ... } or similar). Don't reinvent it — the whole value is the ready-made endpoint.
Call the underlying service from your own controllers. The most robust pattern with an unmaintained bundle is to bypass its routing and inject the uploader service directly:
public function upload(Request $request, MediaUploader $uploader)
{
$file = $request->files->get('file');
$media = $uploader->upload($file); // method name: check the interface
return $this->json(['id' => $media->getId(), 'url' => $media->getUrl()]);
}
This gives you full control over validation, response shape, and security without fighting the bundle's conventions.
Wire into a form + entity flow. Typical pattern: form submits a FileType, controller passes the uploaded file to the bundle's service, stores the returned path/ID on your entity ($post->setImage($media->getUrl())), and the bundle owns the filesystem concern. This separation is the reason to keep it rather than roll your own.
Configure storage via bundle config. Set the upload directory and allowed MIME list in config/packages/media_api.yaml, then reference the same directory elsewhere (VichUploader, LiipImagine, etc.) so you have one source of truth for where uploaded files land.
Guard the route. Add security.yaml access control or a firewall rule for the upload path — a file-upload endpoint with no auth is a classic abuse vector.
composer require to fail on Symfony 6/7 due to version constraints; if so, either --ignore-platform-reqs (dangerous) or copy the 2–3 relevant classes into your app. With this little code, inlining it is often cleaner than depending on it.Media/File entity, you must run its migration or map the entity yourself. Grep for @ORM\Entity and Resources/config/doctrine/.mkdir -p-style; if not, your first upload throws a FileException that looks like a permissions bug but is a missing-directory bug.File::getMimeType() uses finfo; extension checks alone are insufficient. If the bundle only checks extensions, add a File constraint with mimeTypes in your own controller as a belt-and-braces guard.bin/console debug:router | grep -i media — faster than reading YAML and tells you the actual generated route name and path.UploaderInterface, StorageInterface). Override the service alias in your services.yaml rather than forking the bundle. If no interface exists, that's your signal to stop using the bundle and wire it manually..php masquerading as .jpg before shipping.How can I help you explore Laravel packages today?