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

Doctrine Crud Api Bundle Laravel Package

wernerdweight/doctrine-crud-api-bundle

A Symfony bundle for quickly exposing Doctrine entities as CRUD REST API endpoints, with configurable operations, filtering, pagination, and serialization to reduce boilerplate in API development.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and enable. Require the bundle (composer require wernerdweight/doctrine-crud-api-bundle), then confirm it is registered in config/bundles.php (Symfony Flex may not auto-register third-party bundles at this size — add Wernerdweight\DoctrineCrudApiBundle\DoctrineCrudApiBundle::class => ['all' => true] manually if missing).
  2. Import the routes. The bundle ships routing that needs to be pulled into your app:
    # config/routes/wernerdweight_crud_api.yaml
    wernerdweight_doctrine_crud_api:
      resource: '@DoctrineCrudApiBundle/Resources/config/routing.yaml'
      prefix: /api
    
  3. Publish/read the config first. Copy the bundle's default config (php bin/console config:dump-reference doctrine_crud_api) — this is the single most important file to read before annotating anything, because it defines which entities are exposed, which operations (list/get/create/update/delete) are enabled, and the serialization groups used.
  4. Look at the source before the README. With three stars and one release, the src/ directory is the documentation. Start with the entity-level attribute/annotation class (e.g. something like #[CrudApi] or #[ApiResource] — check the actual namespace under Attribute/ or Annotation/) and the controller that resolves it. That one file tells you the entire contract.
  5. First use case. Take an existing Doctrine entity with simple scalar fields, add the bundle's entity attribute, give it a route slug, and hit GET /api/{slug} — you should get a paginated JSON collection. That single round-trip validates: routing import is correct, the entity is registered in config, the serializer is wired, and Doctrine metadata is being read.

The mental model: your Doctrine mapping is the API schema. Columns become fields, relations become nested/included resources, and the bundle turns metadata into routes + controllers + serializers. If it isn't in the mapping, it isn't in the API.

Implementation Patterns

Attribute-driven resource definition. The idiomatic pattern is to keep API concerns colocated with the entity: a class-level attribute (with the route slug and operations), plus field-level attributes/groups controlling visibility and writability. This is where you spend most of your configuration effort.

Per-operation overrides. Expect the bundle to let you disable operations per entity (read-only entities by omitting create/update/delete). Use this aggressively: exposing all five verbs on every entity is the fastest way to ship an accidental admin API.

Serialization groups. Most Doctrine-CRUD-API bundles lean on Symfony's serializer with groups. The pattern that scales: define a small set of named groups (list, detail, write) and tag properties with them. The list group should carry only the fields a table view needs (id, label, timestamps), the detail group the full record. Without this split you either leak columns or N+1 the relation graph on index endpoints.

Pagination + filtering via query params. Configure a default page size and max page size in the bundle config; rely on the bundle's built-in page, limit, sort, and filter[...]-style parameters rather than adding custom controllers. For anything the built-in filtering can't express (joins across relations, computed columns), reach for a custom controller — but keep the same response envelope so clients don't need to special-case.

Validation. If the bundle respects Symfony Validator constraints on your entity, annotate the entity with constraints and let the framework reject bad payloads with a 400 before Doctrine ever sees them. This is much cleaner than validating in a controller.

Integration with existing Doctrine mapping. For projects already using Doctrine relations, the key win is fetch=EAGER vs the bundle's serializer strategy. Test index endpoints with real data volumes — relation traversal is where these bundles typically blow up.

Overriding controllers. Most small bundles let you swap the generated controller class in config or via a service decorator. If you need custom security/authorization logic, decorate the bundle's controller service rather than copying it — copies drift on upgrade.

Gotchas and Tips

  • It is a 3-star, single-release bundle. Treat it as use-at-your-own-risk: pin the exact version ("wernerdweight/doctrine-crud-api-bundle": "1.x" with composer lock committed), vendor the source if you need to patch, and budget time to read src/ before assuming a feature exists. There is no ecosystem to fall back on.
  • Route collisions are the first failure mode. If you already have /api/{entity} routes or an API Platform install, importing this bundle's routing under the same prefix will silently shadow handlers. Use a distinct prefix (/admin/api, /internal/api) or verify with php bin/console debug:router.
  • Doctrine metadata caching. Because the bundle reads mapping metadata to build the schema, changes to attributes won't show up until you clear the cache: php bin/console cache:clear and, in prod, doctrine:cache:clear-metadata. This is the single most common "my change did nothing" cause.
  • Serialization loops. Bidirectional relations (Author.photos ↔ Photo.author) will cause circular reference errors unless you either exclude the inverse side from the read group or configure the serializer's circular-reference handler. Always test the detail endpoint, not just index.
  • N+1 queries on list endpoints. Generated list controllers rarely join-optimize relations. Add #[ORM\Index] on filter columns, and consider overriding the list action with a custom repository query (->leftJoin()->addSelect()) if the default one lazy-loads.
  • Security is your responsibility. The bundle generates endpoints; it does not understand your #[IsGranted] setup unless the routes it emits pass through your firewall and controller-level security. Verify with the Symfony profiler that security.access_control in security.yaml actually matches the generated paths — a wrong prefix here is the most damaging mistake, because a "working" API may be fully public.
  • Debugging tip. When a request returns an unexpected shape, dump the resolved ClassMetadata for the entity — the bundle is almost always faithfully serializing what Doctrine reports, and the field you expected may be a to-one association that needs a nested group.
  • Config quirks. The bundle's config tree often uses entity class names as keys. Typos produce no error, just a silently unexposed entity (404 on the route). Cross-check php bin/console debug:container --parameter or grep for the entity registration service if a route is missing.
  • Extension points worth knowing. Serializer normalizer overrides (to add computed fields), a doctrine_crud_api-scoped event dispatcher or subscriber for pre/post persistence, and the controller service ID for decoration. If none of these are documented, assume the bundle exposes services under an doctrine_crud_api.* prefix and inspect php bin/console debug:container | grep doctrine_crud.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager