intaro/hstore-bundle
Symfony bundle that integrates PostgreSQL hstore with Doctrine, providing a custom DBAL type, schema support, and convenient entity mapping so you can store and query key-value data directly from your PHP applications.
Framing correction (read first). The request describes this as a Laravel/PHP package; intaro/hstore-bundle is a Symfony bundle, not a Laravel package. It does exactly two things: registers a Doctrine DBAL custom type named hstore, and wires it into the container via Intaro\HStoreBundle\IntaroHStoreBundle (registered in AppKernel/bundles.php). There is no service provider, no facade, no Eloquent integration, and no Laravel package discovery manifest. Any Laravel leverage is therefore a port, not an install.
Architecture fit — poor as delivered, adequate as a reference implementation.
getSQLDeclaration, convertToDatabaseValue, convertToPHPValue, getName, and requiresSQLCommentHint. That logic is framework-agnostic.laravel-doctrine/orm. In a standard Eloquent stack, this package contributes zero to the runtime; Eloquent talks to PostgreSQL through PDO and would surface hstore columns as raw strings.Integration feasibility — low for the package, moderate for the pattern.
composer require intaro/hstore-bundle in a Laravel app is technically possible (MIT, autoloadable) but yields no behavior. There is no register()/boot() path.app/Doctrine/Types/HStoreType.php, register it in a AppServiceProvider::boot() via Type::addType('hstore', HStoreType::class), and pair it with a platform-level registerDoctrineTypeMapping('hstore', 'hstore') if using Doctrine ORM. This is a same-day spike for one engineer.jsonb (available since 9.4, released the same month this package last shipped) covers the key/value use case with nesting, GIN indexing without an extension-specific operator class, and first-class Laravel support via $casts = ['meta' => 'array'].Technical risk — high.
[Deprecated]. There is no maintained successor referenced by this package.Type became an abstract with different signatures; getName() is deprecated in favor of class-as-identifier).text → text map. Every value round-trips as a string; integers, booleans, nulls, and nested structures are lost or require manual coercion at the application layer. This becomes a permanent product constraint, not a library concern.Key questions for the team before any commitment:
@>, ?, -> operators in application SQL) or incidental?laravel-doctrine/orm) or pure Eloquent? This determines whether a DBAL type is even reachable.hstore extension (CREATE EXTENSION hstore); on managed services (RDS, Cloud SQL, Supabase) this is a parameter-group or extension-allowlist question with lead time.Stack fit. Laravel 10/11 + Eloquent + PostgreSQL is a mismatch for this package and a good fit for the underlying capability via jsonb. The only configuration where the package's approach is defensible is Laravel + laravel-doctrine/orm + an existing hstore schema, i.e., a narrow legacy-integration scenario.
Recommended path (default): eliminate hstore.
jsonb columns, expose them through Eloquent casts ('array' or a custom cast), and get typed access, nesting, and GIN indexing for free.UPDATE t SET meta_jsonb = hstore_to_jsonb(meta) on modern PostgreSQL (or hstore_to_json(meta)::jsonb on older minors), then drop the hstore column in a follow-up release.Fallback path: port the type into application code.
intaro/hstore-bundle to composer.json. Copy the type class into the app namespace, add a header comment recording provenance (upstream URL, commit SHA, MIT license text retained), and register it in a service provider.CREATE EXTENSION IF NOT EXISTS hstore; to the schema baseline if it isn't already present.Migration path and sequencing.
grep for hstore in migrations, raw SQL, and reporting queries; confirm the extension is enabled in every environment; count rows and distinct keys per column.null, empty map (''), and non-ASCII values.Compatibility considerations.
convertToPHPValue behavior against your PDO settings; hstore arrives as a text literal and must be parsed into an associative array, and Doctrine's own hstore handling in DBAL 3.x+ differs from the 2014-era API this class was written against.requiresSQLCommentHint behavior, or schema-diff tooling will perpetually propose column type changes.Maintenance. No upstream maintenance exists and none will arrive. Every line of this package that survives into production becomes our code, permanently, with no CVE feed, no changelog, and no upgrade path. Budget it as owned code, not as a dependency: include it in static analysis, coding standards, and dependency-review scope so it isn't mistaken for a maintained third-party.
Support. Zero vendor support, zero community support (0 dependents means no Stack Overflow corpus, no GitHub issue history of value). Escalation path is internal: the engineer who ported it. Name that person and a backup in the runbook before merge.
Scaling.
gin_hstore_ops operator class and extension availability, which is a managed-database configuration dependency rather than a schema-only concern.text. Any numeric comparison, range query, or aggregation must cast in SQL ((meta->'price')::numeric), which defeats index usage and pushes logic into raw query builder calls. Expect this to be the first thing that hurts at scale.Failure modes to design against.
Unknown column type "hstore" at runtime, not at boot. Assert registration in a health check."0" truthiness surprise.'', which is not distinguishable from null in some parse paths.Ramp-up. Low for the port itself — a day for an engineer comfortable with PHP and PDO. Moderate for the team on the surrounding concepts: PostgreSQL extension management, GIN operator classes, raw-SQL type casting, and Eloquent cast strategies. The real ramp-up cost is organizational: explaining to future hires why a 2014 Symfony bundle's logic lives in app/Doctrine/Types/, which is why the provenance comment and an ADR are non-negotiable deliverables.
Recommendation. Do not adopt the package. Treat it as documentation of a pattern and either (a) eliminate hstore in favor of jsonb — the strong default given the 2014 deprecation date and jsonb's arrival in the same window — or (b) vendor the type into application code under an explicit ownership assignment, with a dated plan to exit to jsonb. Either way, record the decision and the owner before the first line lands.
How can I help you explore Laravel packages today?