heymoon/doctrine-psql-enum
A Doctrine DBAL type for PostgreSQL enums, making it easy to define and use native enum columns in Laravel/PHP applications. Provides seamless mapping and schema integration for cleaner, type-safe database models.
Architecture fit
This package is a Doctrine DBAL custom type, not a Laravel/Eloquent package. It solves one narrow problem: mapping a PHP 8.1+ backed enum to a native PostgreSQL CREATE TYPE ... AS ENUM column, with conversion handled at the DBAL layer instead of in application code.
That means fit is conditional on a decision most Laravel shops have already made:
casts + string/integer columns. Laravel's $table->enum() on PostgreSQL emits a varchar plus a CHECK constraint, not a native enum type. Adopting this package to close that gap would mean introducing Doctrine DBAL purely as an enum shim — a large dependency for a small ergonomic win. Recommendation: do not adopt; use backed-enum casts plus a check constraint or a lookup table.laravel-doctrine/orm): good fit. This is the intended audience, and the package removes hand-rolled Type subclasses that every Doctrine+Postgres team otherwise writes.Integration feasibility
Mechanically simple: composer require, register the type in the DBAL type registry / config/doctrine.php custom types, annotate or attribute the entity column with the type name. No service provider, no config publishing, no runtime middleware, no Laravel container coupling — low blast radius.
The 3.4.2 release ("Pass registered types to underlying platform") touches exactly the seam that matters here. DBAL's platform object is what the schema comparator and migration diff consult when reasoning about column types; a custom type that is registered but invisible to the platform is the classic cause of phantom ALTER statements and failed introspection. This release is plausibly a targeted fix for that class of problem — which, if it holds, retires the single largest open integration risk in the previous assessment. It is stated in one line with no detail, so treat it as "likely improved, unverified."
The non-trivial work is still not the package. It is the surrounding Postgres DDL lifecycle:
CREATE TYPE. Even with platform awareness, DBAL's comparator does not author CREATE TYPE statements. The team must hand-author the CREATE TYPE in an initial migration and ensure ordering (type before table), plus idempotent guards for fresh environments. Verify the 3.4.2 behavior against doctrine:migrations:diff in a scratch database rather than assuming the release closes the gap.Type contract materially, and "registered types to platform" is precisely a DBAL-4-era concern. Confirm the supported DBAL range against the project's lockfile before scoping, and confirm which line 3.4.2 was tested against.varchar column to a native enum requires ALTER TABLE ... ALTER COLUMN ... TYPE ... USING (...), which rewrites the table and takes an ACCESS EXCLUSIVE lock. On any non-trivial table this is a maintenance-window migration, not a deploy-time one.Technical risk
ALTER TYPE ... ADD VALUE (transaction-blocking caveats, and the new label is unusable in the same transaction that added it), while renaming or removing a value requires creating a replacement type, rewriting every dependent column, and dropping the old type. Under zero-downtime deploy constraints this is materially harder than a check constraint. The package makes the happy path pleasant and does nothing to soften the migration path.martin-georgiev/postgresql-for-doctrine covers Postgres enums plus ranges, IP types, and adjacent DBAL gaps with broader adoption and a larger test suite. Any build/buy decision should benchmark against it rather than against writing a type from scratch — and the 4-test disclosure strengthens that comparison.Key questions for the team
ALTER statements in doctrine:migrations:diff on our schema? Prove it in a scratch database before relying on it.CREATE TYPE in the migration chain, and has a fresh-database bootstrap been proven end to end?Stack fit
Requires PHP 8.1+ (native enums), PostgreSQL, Doctrine DBAL, and — for the intended use case — Doctrine ORM. In Laravel this implies laravel-doctrine/orm is already present and the team has accepted Doctrine's entity/metadata model alongside Eloquent. If the application is a hybrid (Eloquent for most models, Doctrine for a bounded context), scope this package strictly to the Doctrine-bounded entities; do not let it become the schema convention for the whole database.
Migration path
Three distinct paths, sequenced by risk:
CREATE TYPE in the same migration file ahead of Schema::create, register the type, done.varchar/text columns: treat as a data migration. Add the new type, add a temporary enum column, backfill with a CASE mapping, swap, drop the old column — or accept a locked rewrite. Validate that every existing value maps to a case; unmapped values must fail the migration loudly, not silently null out.CHECK-constrained columns: simplest of the three — the value domain is already enforced, so the conversion is a type change plus dropping the constraint.Compatibility
Pin the package exactly (not a caret range) — 3.4.2 specifically, given the changelog bundles 3.4.0 → 3.4.2 — and add a lockfile-diff review to the upgrade checklist for doctrine/dbal. Because 3.4.2 is a behavior change in how the platform sees registered types, re-run the comparator check after adopting it: confirm the type round-trips values and does not confuse doctrine:migrations:diff, which otherwise generates spurious ALTER statements on every diff — a slow-burn operational tax. Verify behavior under doctrine/dbal 3 and 4 if both appear across services; do not assume a single supported line, and do not assume 3.4.2 was exercised against both given the test count.
Sequencing
NULL handling, invalid-label rejection at the DB layer, fresh-schema bootstrap, and — new for this release — that migrations:diff produces an empty diff against a fully-migrated schema.pg_enum label set — this is the highest-value artifact in the whole integration and survives any future package swap. It is also the only realistic compensation for a 4-test upstream suite.Maintenance
The package is small and does one thing, so surface area for breakage is low — but the maintenance burden shifts to your migration code, which now carries hand-written Postgres DDL that DBAL cannot diff or reverse. Budget ongoing owner time for the enum-evolution runbook, not for the dependency. Pin the version, mirror the repository internally, and pre-agree a fork trigger (maintainer unresponsive >90 days with an open breaking issue). The 3.4.2 change increases the value of mirroring: a platform-registration fix is the kind of thing that can regress silently on a DBAL upgrade, and you want the ability to patch it yourself.
Support
No commercial support, no SLA, single maintainer, and a four-test suite. Escalation is a GitHub issue against a low-star project. Internal capability — someone who can read DBAL's Type contract, read a platform implementation, and write a Postgres DDL migration — is the real support plan. Confirm that person exists before adoption; if not, the cheap dependency is actually an expensive one.
Scaling
Read paths are unaffected. Write and DDL paths are where scale bites: enum changes take ACCESS EXCLUSIVE locks and, for renames/removals, rewrite dependent tables. At small table sizes this is invisible; at tens of millions of rows it becomes a scheduled maintenance event. Also confirm the connection pooler in use (PgBouncer, RDS Proxy) handles the prepared-statement patterns DBAL emits — a generic DBAL concern, not package-specific, but it surfaces at the same moment.
Failure modes
CREATE TYPE was added to an incremental migration but not to the base schema path.doctrine:migrations:diff still emits phantom ALTER statements. 3.4.2 plausibly reduces this, but with four tests and no described verification of the comparator path, treat it as open until proven on our schema.ALTER TYPE ... ADD VALUE inside a transactional migration fails or leaves the new label unusable in that transaction, breaking seeders that rely on the new case.Ramp-up
Low for a developer fluent in Doctrine metadata and Postgres DDL — roughly a day to a working spike. High for an Eloquent-only team, because the real learning curve is Doctrine's type system and Postgres enum DDL semantics, not this package. Estimate accordingly, and treat the contract test plus runbook as the deliverable, with the dependency as an implementation detail.
Recommendation: unchanged in direction, slightly improved in confidence. Adopt only inside an existing Doctrine ORM context, pinned to 3.4.2, with a fresh-schema test, an empty-diff test, and an enum-evolution runbook as gating prerequisites. The 3.4.2 platform change is directionally the right fix for the package's most painful integration risk, but a four-test suite means our own verification carries the weight — do not adopt on the strength of the release note. Otherwise, decline and use backed-enum casts with a check constraint.
How can I help you explore Laravel packages today?