SonataAdminBundle Documentation

repository·4.x·Indexed 24 days ago

https://github.com/sonata-project/sonataadminbundle

A comprehensive administration generator for Symfony that provides a customizable back-office interface for managing application data and entities. It includes features for automating boilerplate management systems, creating custom CRUD controllers and actions, implementing DataMappers for entities without standard getters/setters, and customizing mosaic list views.

Tokens
84.1K
Snippets
199
Records
263
Agent score
79%

What's inside SonataAdminBundle

  1. Overview of SonataAdminBundle

    4.x
    SonataAdminBundle is a powerful administration generator for Symfony applications. It provides a structured way to manage your application's data through a customizable admin interface, automating much of the boilerplate required to build complex back-office management systems.
  2. Understand the Admin Pool service

    4.x

    The sonata.admin.pool service (an instance of the Pool class) is responsible for managing your Admin service definitions. It is loaded when Symfony starts and performs several key tasks:

    1. Lazy-loading: It handles Admin classes by loading them on demand to reduce system overhead.
    2. Grouping: It matches Admin classes to their respective groups.
    3. Global Configuration: It manages top-level template files, the administration panel title, and the logo.

    You can access this service from the Dependency Injection Container (DIC) using the ID sonata.admin.pool.

  3. How to handle file uploads in embedded Admins

    4.x

    When using sonata_type_admin to embed one Admin inside another (e.g., an ImageAdmin inside a PostAdmin), the child Admin's preUpdate() method is not automatically triggered when the parent form is submitted.

    To fix this, you must implement logic in the Parent Admin's prePersist and preUpdate methods to manually inspect the embedded entities and trigger their lifecycle updates.

    Implementation Steps

    1. In the Parent Admin, override prePersist and preUpdate.
    2. Iterate through the form field descriptions using $this->getFormFieldDescriptions().
    3. Identify fields of type sonata_type_admin that target your specific entity (e.g., App\Entity\Image).
    4. Use the field name to access the embedded object via its getter.
    5. If the embedded object has a new file ($image->getFile()), call a method to refresh its timestamp (e.g., $image->refreshUpdated()) to force the Doctrine lifecycle events to fire.
    6. (Optional) If the embedded object is empty, null the relationship to prevent creating empty records.
    // Inside Parent Admin (e.g., PostAdmin)
    public function preUpdate(object $page): void
    {
        $this->manageEmbeddedImageAdmins($page);
    }
    
    private function manageEmbeddedImageAdmins(object $page): void
    {
        foreach ($this->getFormFieldDescriptions() as $fieldName => $fieldDescription) {
            if ($fieldDescription->getType() === 'sonata_type_admin' &&
                ($associationMapping = $fieldDescription->getAssociationMapping()) &&
                $associationMapping['targetEntity'] === 'App\Entity\Image'
            ) {
                $getter = 'get'.$fieldName;
                $setter = 'set'.$fieldName;
    
                /** @var Image $image */
                $image = $page->$getter();
    
                if ($image) {
                    if ($image->getFile()) {
                        $image->refreshUpdated();
                    } elseif (!$image->getFile() && !$image->getFilename()) {
                        $page->$setter(null);
                    }
                }
            }
        }
    }
  4. Customize templates using BlockEvent

    4.x

    BlockEvent allows you to inject custom content into specific locations within the Sonata Admin templates. These events define 'blocks' where you can attach content.

    Available block events:

    • sonata.admin.dashboard.top / sonata.admin.dashboard.bottom
    • sonata.admin.list.table.top / sonata.admin.list.table.bottom
    • sonata.admin.edit.form.top / sonata.admin.edit.form.bottom
    • sonata.admin.show.top / sonata.admin.show.bottom

    For detailed implementation instructions, refer to the SonataBlockBundle documentation.

  5. Use Admin saving hooks for persistence lifecycle events

    4.x

    SonataAdmin provides lifecycle hooks that are triggered during the submission process. These hooks allow you to perform logic before or after persistence operations.

    Important distinction: Unlike Doctrine ORM events, Sonata Admin's preUpdate and postUpdate hooks are triggered whenever an Admin is successfully submitted, even if no actual changes were made to the database entity. This makes them reliable for triggering side effects (like updating canonical fields or passwords) that don't depend on database-level change detection.

    Available Hooks by Action:

    • New object: preValidate($object), prePersist($object), postPersist($object)
    • Edited object: preValidate($object), preUpdate($object), postUpdate($object)
    • Deleted object: preRemove($object), postRemove($object)

    Note: When using sonata_type_admin to embed one Admin within another, the child Admin's hooks are not fired.

  6. How the Dashboard and Admin list block work

    4.x
    The Dashboard is constructed using Blocks from the SonataBlockBundle. The default content is provided by the Admin list block (service: sonata.admin.block.admin_list), which is implemented by the Block\AdminListBlockService class. This block fetches information from the Admin service's Pool and renders it using the @SonataAdmin/Block/block_admin_list.html.twig template.
  7. Standardize AJAX form error format (v4.19+)

    4.x

    In version 4.19, AJAX form errors for creation or editing are now outputted using the standard Symfony JSON validation error format instead of a custom Sonata format. This allows forms to correctly highlight fields with errors.

    Requirement: To support this new format, you must have symfony/serializer installed in your project.

    {
        "type":"https://symfony.com/errors/validation",
        "title":"Validation Failed",
        "detail":"name: Form error message",
        "violations": [
            {
                "propertyPath":"name",
                "title":"Form error message",
                "parameters":[]
            }
        ]
    }
  8. How Admin routing works

    4.x

    Routing in SonataAdminBundle is managed via the Admin class. The Admin class provides two primary methods for interacting with routes:

    • getRoutes(): Returns all available routes for the admin.
    • generateUrl($name, $options): Generates a URL for a specific action. When using this method within the current Admin context, you only need to provide the action name (e.g., 'list'), not the full route prefix.

    Route names are internal identifiers used for URL generation, while route patterns define the actual URL structure.

  9. How global search works in SonataAdminBundle

    4.x

    SonataAdminBundle provides a global search feature located in the upper navigation menu. The search mechanism iterates through registered admin classes and identifies searchable filters by checking if they implement the Sonata\AdminBundle\Search\SearchableFilterInterface and if their isSearchEnabled() method returns true.

    If you are using SonataDoctrineORMBundle, the Sonata\DoctrineORMAdminBundle\Filter\StringFilter is automatically searchable and relies on the global_search configuration option.

    Note: The current implementation uses LIKE %query% OR LIKE %query% queries, which can be performance-intensive on large datasets.

  10. Configure a custom Filter Persister

    4.x

    When persist_filters is enabled, SonataAdmin uses Sonata\AdminBundle\Filter\Persister\SessionFilterPersister by default. To use a custom persistence strategy (e.g., saving filters to a database instead of a session), implement the Sonata\AdminBundle\Filter\Persister\FilterPersisterInterface and register your class as a service.

    You can apply your custom persister either globally for all Admins or specifically for a single Admin.

    # Global configuration
    # config/packages/sonata_admin.yaml
    
    sonata_admin:
        persist_filters: true
        filter_persister: filter_persister_service_id
    
    # Per-Admin configuration
    # config/services.yaml
    
    services:
        app.admin.user:
            class: App\Admin\UserAdmin
            tags:
                - { name: sonata.admin, model_class: App\Entity\User, manager_type: orm, filter_persister: filter_persister_service_id }
  11. Extend Admin configuration with ConfigureEvent

    4.x

    Use ConfigureEvent to modify the configuration of Admin components such as forms, lists, datagrids, or show pages. These events are dispatched when the respective component is being configured, allowing you to inject custom logic or modify existing settings.

    Available event names:

    • sonata.admin.event.configure.form
    • sonata.admin.event.configure.list
    • sonata.admin.event.configure.datagrid
    • sonata.admin.event.configure.show