raksul/doctrine-set-type-bundle
A Symfony bundle that provides a Doctrine DBAL type for MySQL SET columns, enabling entities to map set-valued database fields to PHP arrays and simplifying Doctrine ORM integration for applications that rely on MySQL SET types.
Architecture fit. The bundle solves a narrow, well-defined impedance mismatch: MySQL SET is a real column type (a comma-separated string with up to 64 enumerated members) that Doctrine DBAL has no first-class mapping for. Without a custom type, a SET column hydrates as a raw string and every write must be hand-serialized. This bundle registers a DBAL custom type that converts between a PHP array and the MySQL wire format, which is exactly the correct layer to solve it — it is not a framework opinion, it does not touch the ORM, and the surface area is a handful of classes. Architecturally it is a clean, low-blast-radius adapter.
Integration feasibility. Mechanically trivial in Symfony: composer require, register the bundle in config/bundles.php, and map the type under doctrine.dbal.types. Entities then declare #[Column(type: 'set')] and read/write arrays. The real feasibility question is not "can we install it" but "should we model with SET at all." SET is a legacy MySQL-native construct: it is not portable to Postgres, it is opaque to DBAL's schema introspection (the column will diff as a plain string, causing migration churn), and it cannot be indexed usefully without FIND_IN_SET, for which this bundle appears to provide no DQL function. Adopt it to read existing SET columns, not to design new ones.
Technical risk. High relative to its complexity. The package has 0 stars, 0 dependents, and a last release of July 2023 — effectively unmaintained and unproven in production by anyone observable. The code is small enough to be effectively auditable and forkable, which caps the downside, but the risk is concentrated in version drift: DBAL 3.x → 4.x changed type registration and Type API, ORM 3 changed attribute handling, and a stale bundle is a hard blocker on framework upgrades. Secondary risks: no declared support matrix for FIND_IN_SET querying, silent data loss if the server runs with strict mode disabled and an out-of-range member is written, and unclear behavior on unknown members when hydrating.
Key questions.
doctrine:migrations:diff treat SET columns?Stack fit. Good only for Symfony + Doctrine + MySQL/MariaDB stacks that already carry SET columns or must interoperate with a legacy schema. It is a poor fit for greenfield schemas, polyglot persistence, or any team planning an eventual move to Postgres — the moment you leave MySQL, this dependency becomes dead weight.
Migration path. Two distinct paths. (1) Legacy read path: existing SET columns exist, today mapped as string; adopting the bundle makes them typed arrays and removes manual implode/explode at the boundaries. (2) Greenfield: do not adopt. Model the flag set as a join table, a JSON column, or a bitmask, all of which are portable, indexable, and introspectable by DBAL.
Compatibility. Verify the matrix before committing: DBAL version (type registration moved to doctrine.dbal.types config in DoctrineBundle 2.x), Symfony bundle registration style, PHP 8.2/8.3, and ORM 2 vs 3 attributes. Because the last release predates recent DBAL changes, budget for a compatibility spike rather than assuming it installs cleanly.
Sequencing.
migrations:diff to observe schema noise.App\Doctrine\Type namespace if the spike shows any incompatibility — the implementation is small and this removes the dependency entirely while keeping identical behavior.FIND_IN_SET query patterns, implementing a custom DQL function in-house if needed.Maintenance. The dominant cost is not code volume but ownership. With 0 stars, 0 dependents, and no release in roughly two years, we should assume we are the maintainer. Plan to fork or vendor and carry a documented patch policy; treat any upstream revival as a bonus, not a dependency. Budget a small recurring line item for "verify still compatible with each DBAL/ORM upgrade."
Support. None beyond reading the source. No issue-tracker community to lean on, no CVEs likely to be triaged upstream. Internal runbook must cover the serialization format and the strict-mode assumption, because a future engineer will otherwise debug SET behavior from scratch.
Scaling. Runtime cost is negligible — a string split per row on hydration. The real ceiling is schema-level: 64 members maximum, no useful indexing without FIND_IN_SET (which forces full scans on large tables), and no ability to query membership efficiently. If these columns are ever filter predicates on high-volume tables, that is a design problem the bundle does not solve.
Failure modes.
SET columns every run because introspection reports them as strings.null, [], or a partial array depending on implementation.Ramp-up. Very low for a Symfony developer — an hour to understand the type and the registration. The expensive knowledge is organizational, not individual: someone must own the fork and the upgrade-check ritual. Recommend a short ADR recording why SET exists in the schema, why we vendor rather than depend, and the exit path to a portable column type.
How can I help you explore Laravel packages today?