A Symfony Media manager bundle for EasyAdmin

Installs: 10 804

Dependents: 2

Suggesters: 0

Security: 0

Stars: 26

Watchers: 4

Forks: 12

Open Issues: 11


2.0.122 2024-05-29 09:45 UTC


Adeliom Quality gate

Easy Media Bundle

A VueJS media-manager for Easyadmin.


Repository Branch Version Symfony Compatibility PHP Compatibility Status
2.x 2.x 5.4, and 6.x 8.0.2 or higher New features and bug fixes
1.x 1.x 4.4, and 5.x 7.2.5 or higher No longer maintained


  • Image editor
  • Multi
    • Upload
    • Move
    • Delete
  • Upload by either
    • Using the upload panel
    • Drag&Drop anywhere
    • Click&Hold on an empty area "items container"
    • From a url "images only"
    • From a url rich embed element like Youtube video
  • Preview files before uploading
  • Toggle between random/original names for uploaded files
  • Bulk selection
  • Bookmark visited directories for quicker navigation
  • Change item/s visibility
  • Update the page url on navigation
  • Show audio files info "artist, album, year, etc.."
  • Dynamically hide files / folders
  • Restrict access to path
  • Download selected "including bulk selection"
  • Directly copy selected file link
  • Use the manager
    • from modal
    • with any wysiwyg editor
  • Auto scroll to selected item using "left, up, right, down, home, end"
  • Lock/Unlock item/s.
  • Filter by
    • Folder
    • Image
    • Audio
    • Oembed
    • Video
    • text/pdf
    • application/archive
    • Locked items
    • Selected items
  • Sort by
    • Name
    • Size
    • Last modified
  • Items count for
    • All
    • Selected
    • Search found
  • File name sanitization for
    • Upload
    • Rename
    • New folder
  • Disable/Enable buttons depend on the usage to avoid noise & keep the user focused
  • Shortcuts / Gestures
    • If no more rows available, pressing down will go to the last item in the list "same as native file manager".
    • When viewing a audio/video file in the preview card, pressing space will play/pause the item instead of closing the modal.
    • Double click/tap
      • any file of type audio/video/oembed will open it in the preview card "same as images".
      • any file of type application/archive will download it.
    • All the left/right gestures have their counterparts available as well.
    • Pressing esc while using the image editor wont close the modal but you can dbl click/tap the modal background to do so. "to avoid accidentally canceling your changes".

To stop interfering with other keydown events you can toggle the manager listener through'disable-global-keys', true/false).

Installation with Symfony Flex

Add our recipes endpoint

  "extra": {
    "symfony": {
      "endpoint": [
      "allow-contrib": true

Install with composer

composer require agence-adeliom/easy-media-bundle

Without Symfony Flex

# config/packages/easy_media.yaml

    - '@EasyMedia/form/easy-media.html.twig'

      easy_media_type: Adeliom\EasyMediaBundle\Types\EasyMediaType

      adapter: 'local'
        directory: '%kernel.project_dir%/var/storage/medias'

  media_entity: App\Entity\EasyMedia\Media
  folder_entity: App\Entity\EasyMedia\Folder
# config/routes/easy_media.yaml

  resource: '@EasyMediaBundle/Resources/config/routes.xml'
  prefix: /admin

  resource: '@EasyMediaBundle/Resources/config/public_routes.xml'
  prefix: /
// src/Entity/EasyMedia/Folder.php

namespace App\Entity\EasyMedia;

use Adeliom\EasyMediaBundle\Entity\Folder as BaseFolder;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Table(name: 'easy_media__folder')]
class Folder extends BaseFolder
// src/Entity/EasyMedia/Media.php

namespace App\Entity\EasyMedia;

use Adeliom\EasyMediaBundle\Entity\Media as BaseMedia;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Table(name: 'easy_media__media')]
class Media extends BaseMedia

Setup database

Using doctrine migrations

php bin/console doctrine:migration:diff
php bin/console doctrine:migration:migrate


php bin/console doctrine:schema:update --force


Manage medias in your Easyadmin dashboard

Go to your dashboard controller, example : src/Controller/Admin/DashboardController.php


namespace App\Controller\Admin;

class DashboardController extends AbstractDashboardController
    // Add the custom form theme
    public function configureCrud(): Crud
        return parent::configureCrud()
    public function configureMenuItems(): iterable
        yield MenuItem::linkToRoute('Medias', 'fa fa-picture-o', 'media.index');


Integrate with FOS CKEditor

            filebrowserBrowseRoute: media.browse
            filebrowserImageBrowseRoute: media.browse
                provider: 'image'
                        - 'image/*'
                    uploadSize: 5

Integrate with LiipImagineBundle

  data_loader: easy_media_data_loader
{{|resolve_media|imagine_filter('filter_name') }}

Field's usage


use Adeliom\EasyMediaBundle\Admin\Field\EasyMediaField;
yield EasyMediaField::new('property', "label")
    // Apply restrictions by mime-types
    ->setFormTypeOption("restrictions_uploadTypes", ["image/*"])
    // Apply restrictions to upload size in MB
    ->setFormTypeOption("restrictions_uploadSize", 5)
    // Apply restrictions to path
    ->setFormTypeOption("restrictions_path", "users/" . $userID)
    // Hide fiels with extensions (null or array)
    ->setFormTypeOption("hideExt", ["svg"])
    // Hide folders (null or array)
    ->setFormTypeOption("hidePath", ['others', 'users/testing'])
    // Enable/Disable actions
    ->setFormTypeOption("editor", true)
    ->setFormTypeOption("upload", true)
    ->setFormTypeOption("bulk_selection", true)
    ->setFormTypeOption("move", true)
    ->setFormTypeOption("rename", true)
    ->setFormTypeOption("metas", true)
    ->setFormTypeOption("delete", true)

Twig usage

# Render the media
{{ easy_media(, format, options) }} // By default format is the reference file and options

# Examples :
{{ easy_media(, "reference") }}

{{ easy_media(, "cover_full", {'class': 'myclass'}) }} 

## For images 
{{ easy_media(, "cover_full", {'loading': "lazy"}) }} 
{{ easy_media(, "cover_full", {'picture': ["cover_full__2xl","cover_full__xl","cover_full__lg","cover_full__sm","cover_full__xs"]}) }}
{{ easy_media(, "cover_full", {'srcset': ["cover_full__2xl","cover_full__xl","cover_full__lg","cover_full__sm","cover_full__xs"]}) }}
{{ easy_media(, "cover_full", {'loading': "lazy", 'srcset': {'(max-width: 500px)': 'cover_full__2xl', '(max-width: 1200px)': 'cover_full__xl'}}) }}

## For oembed 
{{ easy_media(, "reference") }}
{{ easy_media(, "reference", {'responsive': true}) }}

## For video 
{{ easy_media(, "reference") }}
{{ easy_media(, "reference", {"responsive" : true, "controls" : true, "autoplay" : true}) }}

# Get media path
{{ easy_media_path(, format) }} // By default format is the reference file

# Get media URL
{{|resolve_media }}

# Get media metadatas
{{|media_meta }}

# Get single media metadata
{{|media_meta('key') }}

# Get complete media informations
{{|media_infos }}

# Get test file type
# type_to_test: can be a mime_type or 
# oembed for any embed type
# image for any image type
# pdf for pdf files
# compressed for archives files
{{ file_is_type(, type_to_test) }}

# Get mimetype icon (font-awesome)
{{ mime_icon("text/plain") }}

You can override media render with twig

  • For images : @EasyMedia/render/image.html.twig
  • For oembed : @EasyMedia/render/oembed.html.twig
  • For video : @EasyMedia/render/oembed.html.twig

Manage medias and folders programmatically

/* @var EasyMediaManager $manager */

# Get media by id or null
$media = $manager->getMedia($id);

# Get folder by id or null
$folder = $manager->getFolder($id);

# Get folder by path
$folder = $manager->folderByPath($path);

# Create a folder
$folder = $manager->createFolder($folderName, $path = null)

# Create a media
# $source can be a UploadedFile, File, Image URL, Oembed URL, Base64 URI
$folder = $manager->createMedia($source, $path = null, $name = null)

# Save a folder or media
$manager->save($entity, $flush = true);

# Delete a folder or media
$manager->delete($entity, $flush = true);

Use the Doctrine type (optional)

It automatically converts the stored path into a Media entity

# config/packages/doctrine.yaml
      easy_media_type: Adeliom\EasyMediaBundle\Types\EasyMediaType

In your entity

class Article
    #[ORM\Column(type: 'easy_media_type', nullable: true)]
    private Media|string|null $file;


# config/packages/easy_media.yaml
    storage:              '%kernel.project_dir%/public/upload'
    base_url:             /upload/
    # ignore any file starts with "."
    ignore_files:         '/^\..*/'
    # remove any file special chars except
    # dot .
    # dash -
    # underscore _
    # single quote ''
    # white space
    # parentheses ()
    # comma ,
    allowed_fileNames_chars: '\._\-\''\s\(\),'
    # remove any folder special chars except
    # dash -
    # underscore _
    # white space
    # to add & nest folders in one go add '\/'
    # avoid using '#' as browser interpret it as an anchor
    allowed_folderNames_chars: _\-\s
    # disallow uploading files with the following mimetypes (
        # Defaults:
        - php
        - java
    # disallow uploading files with the following extensions (
        # Defaults:
        - php
        - jav
        - py

        # any extra mime-types that doesnt have "image" in it
        image:                # Required
            # Default:
            - binary/octet-stream
        # any extra mime-types that doesnt have "compressed" in it
        archive:              # Required
            # Defaults:
            - application/x-tar
            - application/zip
    # display file last modification time as
    last_modified_format: Y-m-d
    # hide file extension in files list
    hide_files_ext:       true
    # loaded chunk amount "pagination"
    pagination_amount:    50


type event-name description
modal-show when modal is shown
modal-hide when modal is hidden
file_selected (when inside modal) get selected file url
multi_file_selected (when inside modal) get bulk selected files urls
folder_selected (when inside modal) get selected folder path
em.file.uploaded($file_path, $mime_type, $options) get uploaded file storage path, mime type
em.file.saved($file_path, $mime_type) get saved (edited/link) image full storage path, mime type
em.file.deleted($file_path, $is_folder) get deleted file/folder storage path, if removed item is a folder
em.file.renamed($old_path, $new_path) get renamed file/folder "old & new" storage path
em.file.moved($old_path, $new_path) get moved file/folder "old & new" storage path




Thanks to