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

Sonata Extra Admin Bundle Laravel Package

picoss/sonata-extra-admin-bundle

A Symfony bundle that adds practical extensions and utilities to Sonata Admin, helping developers customize admin panels with less boilerplate. It complements existing Sonata setups with reusable admin tools, templates, and helpers for faster backend development.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: this is a Symfony bundle, not a Laravel package. There is no service provider, no config/app.php entry, no php artisan vendor:publish. If you are a Laravel developer reading this because it appeared in a PHP package list, the only day-to-day leverage you get is pattern borrowing (fluent exporters, sortable list columns, dashboard blocks) — you will not install this into a Laravel app. Everything below assumes a Symfony + Sonata Admin codebase, or a legacy hybrid. Treat "how do I use this in Laravel" as out of scope; use Filament, Nova, or a Livewire table instead.

For a Symfony/Sonata developer, the honest first step is confirm it installs against your Sonata version before you read any docs. With 18 stars, zero dependents, and no visible release cadence, the version matrix is the whole decision. Spin a throwaway branch:

composer require picoss/sonata-extra-admin-bundle --dry-run

If Composer resolves cleanly against your current sonata-project/admin-bundle constraints, continue. If it fights them, stop — the cost of a fork will exceed the value of the conveniences.

Where to look first, in order:

  1. composer.json — which Symfony/Sonata majors does it pin? This tells you if it is even alive on your stack.
  2. DependencyInjection/Configuration.php — what is actually configurable under the sonata_extra_admin namespace (exporter formats, default page size, block registration).
  3. Resources/config/services.yml — the service IDs and interfaces you will inject or implement: Exporter, PositionType, ExportableAdminInterface, SortableInterface, AdminBlockInterface (names vary by version — read the actual file).
  4. The source of the specific feature you want (exporter or sortable) — the bundle is thin enough that source is the documentation.

Register the bundle (Symfony 4+ config/bundles.php, Symfony 3 AppKernel):

Picoss\SonataExtraAdminBundle\SonataExtraAdminBundle::class => ['all' => true],

First use case — add CSV export to an existing admin. This is the highest-value, lowest-risk feature and the best smoke test that the bundle loaded:

class ProductAdmin extends AbstractAdmin implements ExportableAdminInterface
{
    protected function configureExportFields(Exporter $exporter): void
    {
        $exporter
            ->setFormats(['csv', 'xls'])
            ->add('id')
            ->add('name')
            ->add('price', 'price', ['format' => '%.2f']);
    }
}

If ?_export=csv on the list page produces a file, the bundle is wired correctly and you can evaluate the rest.

Implementation Patterns

Export as a decorator on Admin, not controller logic. The bundle's design is: implement ExportableAdminInterface, and the Exporter service builds a field list via a fluent add($field, $label, $options) chain. Treat it like League\Csv\Writer — a builder you configure per admin, not per request. Centralize in a base admin so every screen gets consistent behaviour:

abstract class BaseAdmin extends AbstractAdmin implements ExportableAdminInterface
{
    protected array $exportFormats = ['csv'];

    public function getExportFormats(): array
    {
        return $this->exportFormats;
    }

    public function getExportFields(): array
    {
        return array_map(fn ($m) => $m->getName(), $this->getList()->getElements());
    }
}

Then ProductAdmin extends BaseAdmin and only overrides configureExportFields() when a screen needs custom columns or formatting. This keeps the surface area small and makes the eventual fork trivial to reason about.

Sortable entities are a three-piece wiring job. There is no single "sortable" switch. The pattern across every version is:

  1. Add an integer position column to the entity (migration required).
  2. Implement SortableInterface on the entity — typically just getPosition()/setPosition().
  3. Register PositionType on the admin's list fields and point the sortable controller/route at the entity.
// ProductAdmin::configureListFields
$listMapper->add('position', PositionType::class, ['sortable' => true]);

Admin blocks follow an interface contract. Blocks are registered as services tagged for the bundle and implement AdminBlockInterface (or a similar contract — read the shipped interfaces). Each block renders independently, so a failing block degrades one dashboard tile rather than the whole page. This is the most reusable pattern to steal if you later fork: define a block interface, tag services, render each in isolation.

Integration tips that pay off day-to-day:

  • Build a BaseAdmin early. Every admin extending it gets export and consistent list behaviour, and you only pay the Sonata wiring once.
  • Register the bundle's services under a named namespace in config so it does not collide with a future native Sonata feature of the same name.
  • Use the exporter for internal reporting and audit exports — it is not a compliance-grade pipeline. Do not route PII or payments through it.
  • Wrap the entire integration in a feature flag at the admin-class level (configureListFields conditionally adds the PositionType) so you can disable the bundle in one place if it breaks.

Gotchas and Tips

Version compatibility is the real gotcha. The bundle targets an older Symfony/Sonata generation. Composer constraints are the most likely failure, and they will fail silently until you actually run a page. If composer require succeeds but admin list pages throw ServiceNotFoundException, check that the bundle's services.yml names match the Sonata version you are on — Sonata renames services between majors. Diff the file against your vendor/sonata-project/admin-bundle service aliases.

?_export=csv is the smoke test. If the query parameter does nothing, either (a) the admin does not implement ExportableAdminInterface, (b) the Exporter service is not wired, or (c) the bundle did not register. Enable Symfony's container debug (bin/console debug:container | grep -i export) to confirm the service exists before touching your admin class.

The exporter only knows about configureListFields. Fields added via configureFormFields or show are invisible to the exporter. If a column is missing from your export, it is not in the list mapper — either add it there or add it explicitly in configureExportFields().

position needs a deterministic initial value or your first drag breaks sort order. Seed the column with sequential values in the migration (UPDATE product SET position = id or a row-number update) before registering PositionType. Otherwise all rows share 0 and the drag handler produces arbitrary ordering.

Sortable lists and pagination are coupled. Reordering only the current page is fine; reordering across pages is not supported by the drag handler. If your use case needs cross-page ordering, that is a build-your-own, not a configure-the-bundle.

The bundle is effectively unmaintained. Treat it as a fork-and-own dependency from day one. With 18 stars, no CI, no tests, and a single low-activity maintainer, plan for:

  • Pinning an exact commit in composer.json, not a caret range.
  • A named internal owner who reads the source when a Sonata upgrade breaks it.
  • Vendoring via a repositories entry pointing at your fork, so upstream disappearance does not block a release.
  • A README note in your repo explaining why the fork exists — future you will not remember.

Keep it out of customer-facing and regulated surfaces. This is admin-tool glue: an unpatched bundle in the render path of an admin screen that surfaces PII, payments, or audit data is a compliance liability. Internal dashboards only, and preferably read-mostly.

Do not let the "PHP package" label fool a Laravel evaluation. If a stakeholder asks "can we use this in our Laravel app?" the answer is no — it would mean adopting Symfony and Sonata, which is a migration, not a dependency. The correct fallback on Laravel is to reimplement the two patterns you actually want (a fluent exporter and a sortable list) in Filament or a Livewire table in an afternoon.

When it stops earning its keep, fork the specific feature you use. If you only ever use the exporter, the fork is one service class and a Twig template. That is cheaper to own than the whole bundle, and it removes the version-matrix question permanently.

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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource