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

Symfony Doctrine Encrypt Laravel Package

precision-soft/symfony-doctrine-encrypt

A Symfony bundle that adds transparent field-level encryption to Doctrine ORM entities. Protect sensitive database columns at rest with configurable encryption, simple entity mapping, and seamless integration into Symfony applications.

View on GitHub
Deep Wiki
Context7

Getting Started

Start with the .example/ directory in the package. It is now a runnable micro-kernel app that installs the bundle from the working tree via a path repository and exercises every public capability on real engines. Copy its bundle registration and configuration block into your own skeleton rather than reading the source first; it is the shortest path to a working setup.

Minimum steps:

  1. Require the bundle and register it in the kernel (the example shows the exact bundles.php / provider entry).
  2. Publish or hand-write the bundle config: list the encrypted entity fields, the active salt versions, and the salt version new writes use. Every entity you intend to encrypt must have its encrypted fields declared here — the commands and the ORM subscriber both read this list.
  3. Run the schema so stored encryption columns exist with the type the bundle expects (text/blob depending on your driver), then do a single write-and-read through the ORM before touching any command.
  4. First real use case: database:encrypt --dry-run over a legacy plaintext table. It performs the walk and reports what it would change without touching rows. Only after that is clean do you run without --dry-run.

For an existing encrypted dataset, your first command is database:rotate --dry-run, not database:rotate. Confirm the cursor and salt version it plans to write before running it for real.

Implementation Patterns

Rotate in the foreground, verify in a separate process. The documented post-rotation check is database:rotate --dry-run --verify. It writes nothing, reads back the stored columns, and fails naming the fields and the row counts still on another salt version. Run it as a distinct invocation after the rotation exits, not chained with && in the same command — a rotation that fails validation should not silently proceed to the next stage.

Treat checkpoints as state you own. Checkpoints now carry a scope: command, entity manager, and salt version. A database:rotate checkpoint cannot be resumed by database:encrypt, against a different manager, or toward a salt version that has since changed. This is a guardrail, not a limitation — if you genuinely need to switch commands or managers mid-migration, finish the current run or delete the checkpoint deliberately, and know that deleting means the whole table is walked again. In CI, mount the checkpoint directory on persistent storage if you expect long runs to resume across job retries.

Resume safely with --from-id. Identifier values are now rebuilt through the identifier's DBAL type, so bigint binds as an integer, and date_immutable/uid identifiers bind as the objects the mapping expects. You can persist a cursor yourself (e.g. in a job payload) and hand it back later. Values beyond PHP_INT_MAX stay the string DBAL returns — do not cast them yourself before passing them in. An identifier the type cannot rebuild is refused with the type and field named; that is a configuration problem, not a data problem.

Scope --verify runs to one class in SINGLE_TABLE hierarchies. Under SINGLE_TABLE inheritance, --verify now counts only the rows of the selected class and its subclasses — the rows the walk could actually see. A sibling class still on an older salt version is not the selected class's failure. If you have a hierarchy, verify each concrete class separately rather than expecting one --verify to be authoritative for the table.

Resolve commands from the container but do not cache their run state. A command instance reads its checkpoint afresh on every run, because as a container service it outlives a single run(). This means repeated invocations within one process (a worker, a long-lived test kernel, a queued job that calls the command twice) are now correct. If you have code that assumed a command object held the previous cursor, drop that assumption — but also stop reusing the same instance as a shortcut to resume; pass --from-id or let the checkpoint file do it.

Failures name the row and carry the cause. A batch that fails to load now reports the entity and the cursor it was loading after, and preserves the original exception. When a run dies on a row whose salt version was dropped from configuration, the message tells you exactly which cursor to inspect. Log the full exception, not just the message.

Gotchas and Tips

  • Checkpoint format is version 2. A version 1 file written by v4.6.0 is refused with a message telling you to finish with the release that wrote it or delete it. Do not upgrade mid-run. Before upgrading in production, drain any in-flight checkpointed migration.
  • Do not upgrade and resume in one deploy. The one hand-holding case in this release: a checkpointed run started on v4.6.0 must be finished on v4.6.0. Bake a "no checkpoint files present" precondition into the deploy, or delete the file knowingly.
  • --batch-size is sanitized. Values that saturate to PHP_INT_MAX are rejected rather than turning into one batch over the whole table. If you previously passed an absurd sentinel value to mean "no batching", pick a real number.
  • Checkpoint writes are now durable. The byte count is compared and the data is synced before the rename over the previous good file. A short write is no longer reported as success. If you see failures here, look at disk pressure and filesystem semantics, not the bundle.
  • The keyset walk stops when the cursor does not advance. If your custom keyset adds no predicate — or adds a predicate that does not order by a strictly increasing key — the run now stops instead of returning the same rows forever. It will look like an early, incomplete run; check your keyset for a missing or non-monotonic column.
  • Identifier objects in cursors are restricted. A Stringable identifier is stored as its string form and rebuilt through its type; anything else is refused both when the cursor is written and when it is read. A DateTimeImmutable or uid cursor is now rebuilt properly rather than bound back as a JSON array or a string. If you persist cursors yourself, store the Stringable's string form and nothing more.
  • CheckpointService constructor signature changed — the scope is now the first argument. If you instantiate or decorate it, update the call site. setIdentifierValues() accepts only integers and strings; castIdentifierValue() may now return an object. Any subclass overriding the cast must respect that return contract.
  • Messages are lowercased and class names are quoted. AbstractDatabaseCommand, DatabaseRotateCommand and EntityService changed their message formatting. Any log-scraping or alerting regex that matched the old casing will need updating.
  • .example/ is export-ignored. It is a development and reference artefact, not shipped in vendor/. Read it from the repository or a source checkout, and gate your own equivalent with .dev/validate/all.sh --example if you maintain one.
  • MSI is now 95, up from 81. If you run mutation testing against a fork of this suite, expect the threshold to bite; the score is measured, not aspirational.
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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin