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

Reconstitutor Laravel Package

rekalogika/reconstitutor

Rekalogika Reconstitutor is a PHP library for rebuilding objects from persisted data. It maps database rows or arrays to typed objects through a simple reconstitution API, helping keep persistence logic separate from domain models.

View on GitHub
Deep Wiki
Context7

Getting Started

rekalogika/reconstitutor is a framework-agnostic Doctrine ORM helper: you write a small class per entity that maps a plain array (request payload, CSV row, queue message) onto a managed entity, and the library handles the plumbing around identifiers, associations and collections. In Laravel you pair it with laravel-doctrine/orm (or your own EntityManager binding) — there is no Laravel service provider in this package, the Symfony bundle lives in a separate repo.

Minimal steps:

  1. composer require rekalogika/reconstitutor alongside your Doctrine ORM setup.
  2. Look first at the Reconstitutor interface and ReconstitutionContext in src/, then read tests/ — the test suite doubles as the best usage documentation.
  3. Define one reconstitutor per entity, keyed by getClass():
final class BookReconstitutor implements Reconstitutor
{
    public function __construct(private EntityManagerInterface $em) {}

    public static function getClass(): string
    {
        return Book::class;
    }

    public function reconstitute(object $book, array $data, ReconstitutionContext $context): void
    {
        if (array_key_exists('title', $data)) {
            $book->setTitle($data['title']);
        }

        if (array_key_exists('authorId', $data)) {
            $book->setAuthor($this->em->getReference(Author::class, $data['authorId']));
        }
    }
}
  1. Register your reconstitutors as singletons in a service provider and collect them into a small registry keyed by class name.

First use case: a PUT/PATCH endpoint that accepts a JSON body with scalars plus relation IDs and needs a managed entity back — without hand-writing a setter for every field and without the serializer's ORM hydrator.

Implementation Patterns

  • One reconstitutor per entity, resolved through a registry. A ReconstitutorRegistry (map getClass() → instance) lets a single generic controller handle many resources: resolve the class from the route, $em->find() or new, reconstitute, flush.
  • Create and update share one code path. The reconstitutor only mutates; it never persists. $book = $em->find(Book::class, $id) ?? new Book(); then reconstitute, then $em->flush(). This keeps write logic in exactly one place.
  • Partial payloads (PATCH). Guard every field with array_key_exists() so an absent key means "leave alone" rather than "set to null". Agree on this convention early — it's the single biggest source of accidental data wipes.
  • Associations by identifier. $em->getReference(Author::class, $id) avoids a SELECT and is the idiomatic way to satisfy a ManyToOne. For nested writes (creating a new related entity from a nested array), delegate to that entity's own reconstitutor via the context.
  • Collections. For to-many updates, clear and re-add through getReference() proxies, or diff by ID. Watch orphan removal — an empty array plus orphanRemoval: true deletes rows.
  • Transaction shape. Validate with a Laravel FormRequest first, then wrap reconstitute + flush in $em->transactional(fn () => ...) or DB::transaction(). Flush once at the end, not per entity.
  • Bulk/import jobs. Reconstitution shines for CSV/JSON upserts: you already have IDs, so find() + reconstitute + batched flush is far cheaper than per-row serializers.
  • Pair with an authorization layer. Reuse the same policy checks you'd use for a normal update — the reconstitutor is a mapping layer, not a security boundary.

Gotchas and Tips

  • You own the wiring. No Laravel auto-discovery here; bind reconstitutors explicitly and tag/collect them, otherwise your registry will be empty at runtime.
  • The entity must be managed. If the object isn't attached to the EntityManager, changes never flush. Equally, calling $em->clear() or detach() mid-loop drops pending changes — 2.5.0 added fixes specifically for detach-during-transaction and begin/flush/clear/commit sequences, so upgrade if you hit that.
  • No validation, no mass-assignment protection. Everything written inside reconstitute() is reachable from request data. Validate and authorize before calling it.
  • Identifiers. Use the context's identifier helpers rather than assigning the ID property directly when the payload carries an ID — that's what lets the library reconcile with an already-managed instance.
  • Missing keys become ErrorException in Laravel. Undefined array keys are converted to exceptions by Laravel's error handler; always array_key_exists() / ??.
  • Proxies hide bad IDs. getReference() never validates existence; a bogus foreign key only fails on flush() as a constraint violation (or on first proxy initialization). Map that to a 422, not a 500.
  • Debug at flush time. Failures surface during flush(), not during reconstitution. Log the payload plus entity class, and inspect $em->getUnitOfWork()->getScheduledEntityUpdates() when changes "disappear".
  • 2.5.0 is a safe upgrade. It's bug fixes (transaction edge cases, negative tests), cleanup, and a widened symfony/* constraint to allow Symfony 8 — no API breaks, no deprecations. Re-run anything touching transactions or detached entities, then bump.
  • Extension points: implement Reconstitutor per class; use ReconstitutionContext for EntityManager access, nested reconstitution and identifier assignment; wrap the registry in your own service so controllers never reference concrete reconstitutor classes.
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.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo