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

Entity Resource Mapper Bundle Laravel Package

whitedigital-eu/entity-resource-mapper-bundle

Symfony bundle for mapping entities to resource/DTO objects and back. Configure mappings and attribute metadata to keep API and service layers clean, decoupled, and maintainable. A lightweight helper for REST APIs and domain-to-resource transformations.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and enable

composer require whitedigital-eu/entity-resource-mapper-bundle

The bundle is Symfony Flex-friendly, so it should register itself in config/bundles.php. If not, add it manually. Prerequisites are the usual stack this targets: PHP 8.1+, Symfony 6/7, API Platform 3, and Doctrine ORM. Check composer.json in the repo before installing — this is a single-maintainer package with one star and no dependents, so confirm the API Platform constraint matches your project rather than trusting Flex to sort it out.

Where to look first

  1. README.md — it is the only documentation. Read it end to end; it is short.
  2. src/Attributes/ (or equivalent) — the mapping attribute is the whole public surface. Its constructor signature tells you what is configurable.
  3. src/DependencyInjection/ — shows what the bundle wires into API Platform and which services you can decorate.
  4. The underlying whitedigital-eu/entity-resource-mapper library — the attribute handling and reflection logic live there, not in the bundle.

Because the package is small and lightly documented, treat the source as the reference. Spend ten minutes reading the mapper service before writing your first resource.

First use case

The canonical job is decoupling your API resource from your Doctrine entity. Instead of annotating Product with #[ApiResource], you create a DTO and attach the bundle's mapping attribute so the mapper hydrates the entity for writes and projects it to the DTO for reads:

#[ApiResource(operations: [new Get(), new Post()])]
#[MapEntity(Product::class)] // exact attribute name per README
final class ProductResource
{
    public int $id;
    public string $name;
    public int $priceInCents;
}

Start with a single Get operation on one entity. Once you see the provider return a populated DTO, add a Post and verify the mapper writes through Doctrine. Only then generalise.

Implementation Patterns

Read-only DTO resources. The most common and lowest-risk adoption: leave writes on your existing entity-based endpoints, and use the mapper purely to shape responses. You avoid mass-assignment risk entirely and still get stable, versionable output contracts.

Input/output separation. Use one DTO for Post/Put (fields the client may set) and a different DTO for Get (fields you expose, including computed or joined data). This is the main reason to reach for the package at all — API Platform can do DTOs natively, but this bundle centralises the entity↔DTO translation so you are not writing a state provider/processor per resource.

Write flow. The reliable pattern is: validate the DTO first, then map. Let the bundle's processor resolve the entity, but for Put/Patch confirm it loads the existing managed entity by identifier rather than constructing a new one — otherwise Doctrine sees an insert and you get duplicate-key errors instead of updates.

Reusing DTOs across operations. Build one resource class per entity per direction, and use serialization groups or #[Ignore] rather than cloning classes. Duplicating DTOs is the fastest route to drift.

Custom mapping. Where the mapper's convention-based reflection is not enough (value objects, enums, money types, computed fields), keep the transformation in the DTO's constructor or in a small dedicated mapper you call from a decorator. Do not fork the bundle for one special case.

Testing. Write an integration test per resource: boot the kernel, issue a request through API Platform's test client, assert the JSON shape and the database state. The bundle's behaviour is reflection-driven and therefore easy to break silently on upgrade; request-level tests catch that cheaply.

Gotchas and Tips

Assume no support. One star, zero dependents, last release July 2024. Pin the exact version in composer.json, and budget for the possibility that you are the maintainer of your fork. Read the diff of any upgrade.

API Platform 3 metadata. Resources are DTOs, so #[ApiResource] lives on the DTO — but filters, security expressions, and pagination often still need the entity in mind. Filters that reference entity properties will not work against a DTO without adjustment.

Doctrine proxies. If you inspect the class of a mapped object, get_class() may return a proxy class name. Use Doctrine\Common\Util\ClassUtils::getClass() anywhere your own code branches on type; the mapper generally handles this, custom decorators may not.

Identifiers and mass assignment. Never let a client-set id flow into the entity. Explicitly exclude it from input DTOs. Any field on an input DTO is a writable field on your entity — review those DTOs with the same scrutiny as a form type.

Lazy loading and N+1. Mapping a collection of entities to a collection of DTOs will touch every association the DTO reads. Use fetch joins or #[MaxDepth] on the query; the mapper cannot batch for you.

Validation ordering. Apply constraints to the DTO, not only to the entity. If you validate after mapping, failed input has already mutated a managed entity in the unit of work, which makes error paths confusing.

Debugging. When a DTO comes back empty or a write silently no-ops, check in this order: is the attribute on the DTO class, does the operation point at the DTO, is the mapper service registered (debug container), then step into the library's mapping method. Enable the Symfony profiler and inspect the Doctrine unit of work to see whether the entity was actually persisted.

Extension points. Decorate the bundle's provider/processor services rather than subclassing — the class names are not part of a stable contract. A decorator is also the cheapest way to add per-resource post-processing without waiting for upstream.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
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