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

Resource Bundle Laravel Package

sylius/resource-bundle

SyliusResourceBundle provides format-agnostic CRUD controllers and persistence utilities for Symfony apps, built on Doctrine's ObjectManager and ObjectRepository interfaces. It simplifies listing, filtering, sorting, and displaying resources without duplicating controllers.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the bundle and register it:

composer require sylius/resource-bundle
// config/bundles.php
return [
    // ...
    Sylius\Bundle\ResourceBundle\SyliusResourceBundle::class => ['all' => true],
];

The fastest way to orient yourself is the official documentation at stack.sylius.com/resource (linked from the README) — the README itself only explains the philosophy, not the API. Then run the debug command to see what the bundle actually registered:

bin/console debug:resource

Pick one small entity as your first use case (a Book is the canonical example in the docs) and wire up the four moving parts:

  1. Resource config — describe the resource under sylius_resource.resources so the bundle generates the factory, repository, manager, and controller services:
# config/packages/sylius_resource.yaml
sylius_resource:
    resources:
        app.book:
            classes:
                model: App\Entity\Book
                repository: App\Repository\BookRepository
                factory: Sylius\Component\Resource\Factory\Factory
                controller: App\Controller\BookController
            driver: doctrine/orm
  1. Controller — extend the provided base controller (or the newer attribute-driven AbstractController) and only override what you need:
use Sylius\Bundle\ResourceBundle\Controller\ResourceController;

final class BookController extends ResourceController
{
    // index / show / create / update / delete are inherited
}
  1. Routing — expose the actions with the bundle's route loader (type: sylius_resource) or, on 1.11+, with operation attributes directly on the controller.

  2. Templates — provide templates/book/index.html.twig etc. following the bundle's naming convention.

Once this single CRUD works, you have the pattern for every resource in the app.

Implementation Patterns

Resource-per-feature configuration is the unit of work. Every resource you add is a self-contained YAML block that maps an entity to services and a controller. The naming convention for the generated services is <resource_name>.<role> — app.book.repository, app.book.factory, app.book.manager. Use those ids in your own services rather than constructing repositories yourself.

Thin controllers, fat operations. The controller is a dispatcher. Extend ResourceController for default CRUD and override a specific action only when the default flow doesn't fit. For anything more complex, the newer operation system lets you declare routes and handlers per action:

#[AsResource]
final class BookController
{
    #[GetCollection]
    public function indexAction(Request $request): Response { /* ... */ }

    #[Post]
    public function createAction(Request $request): Response { /* ... */ }
}

Note the attribute is AsResource, not Resource — the older name was renamed because Resource was a reserved-ish word.

Event hooks are the extension point for behaviour. Instead of overriding actions, listen to the lifecycle events (pre_create, post_create, pre_update, post_update, pre_delete, etc.) and keep controllers generic. This is also where the bundle exposes flash messages from processors (see "flash from event on processor" in the changelog) — the processor can emit a flash and the controller handles it, so your business logic doesn't have to know about Symfony's session.

Grids drive index pages. For list screens, configure a grid (filters, sorting, pagination) and mark the index operation as grid-aware, rather than hand-rolling query building in the controller. Grids are what turn the bundle from "a controller with a repository" into a real CRUD foundation — and they're the piece most teams underuse.

Multi-driver is a real feature, not marketing. Because everything is built on Doctrine's ObjectManager and ObjectRepository interfaces, the same controller and config work against ORM or ODM. If you're building something that might need a non-relational backend, stay on the ObjectManager APIs in your custom code so you don't paint yourself into a corner.

Templates and Twig helpers. The bundle ships Twig helpers for resource names and route generation (sylius_resource_name, path helpers). Use them so your templates stay portable when a resource's name or plural name changes — which is a config value, not a hard-coded string.

Format-agnostic controllers. The base controllers were designed to serve different presentations (HTML, JSON, XML) from the same logic. If you're building an API, implement a serializer/format layer rather than duplicating controllers — that's the original motivation for the bundle.

Gotchas and Tips

  • It is not an admin generator. The README is explicit: it won't create forms, filters, or grids for you. It gives you format-agnostic controllers plus basic sorting and filtering. If you want Sonata/EasyAdmin-style scaffolding, this is not that — plan for the extra work.

  • There is no main or master branch. Every PR targets the branch matching the minor version (1.10, 1.11). If you're forking or contributing, that's the first thing to know.

  • 1.11 moved a lot of namespaces. The changelogs are dominated by "Move some namespaces on …" refactors. If you're upgrading from 1.10, expect controller, context, Doctrine, grid, factory, Twig, and metadata namespaces to have shifted. Run the upgrade and let the autoloader tell you what broke — don't rely on old snippets from the internet.

  • Route naming and conflicts. Deleting a resource used to collide with other generated routes; the delete path name was changed to avoid this. If you're overriding routes manually, check the generated names with bin/console debug:router | grep book before adding yours.

  • HTTP method handling. The bundle now registers POST on update, delete, and bulk delete (for HTML forms that can't send PUT/DELETE), and fixes the response status for safe methods. If you're writing a REST client or an api-tests suite, verify the actual method/status matrix rather than assuming textbook REST semantics.

  • Debugging: bin/console debug:resource <FQCN> shows what the bundle knows about a resource — useful when a controller can't find its repository or when a route isn't generated. This was improved in recent versions.

  • Grid limits on the request grid provider had a bug fixed in 1.11.2; if you're on an older patch and see pagination limit overrides not applying, that's the fix.

  • Configuration quirks: the resource name is a dotted key (app.book), and the bundle derives the singular/plural name from it — override those explicitly if your entity doesn't match the humanizer's guesses. Likewise, data providers and data processing can be disabled per operation; the docs added sections for both ("Disable providing data", "Disable processing data") precisely because the defaults are surprising when you want a read-only or side-effect-free operation.

  • Extension points worth knowing: custom factories (for domain-specific construction), custom managers, request handlers, and the state machine integration (you can configure a specific state machine component per resource, per the 1.11 changelog). The state machine hook is the cleanest way to add transitions without bespoke controller logic.

  • Adoption reality check: this bundle is the CRUD substrate underneath Sylius itself, so it's battle-tested by a very large application — but almost nobody uses it standalone, and its docs live beside the Sylius Stack docs rather than on the repo. Treat it as infrastructure: expect to read source for edge cases, and budget time for the 1.10 → 1.11 namespace migration if you're starting from an older install.

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.
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc