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

Hstore Bundle Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

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.

  • The package's real payload is one small DBAL type class implementing getSQLDeclaration, convertToDatabaseValue, convertToPHPValue, getName, and requiresSQLCommentHint. That logic is framework-agnostic.
  • Laravel does not use Doctrine DBAL types unless the team has adopted 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.
  • The Symfony bundle plumbing (DI extension, compiler pass, bundle class) is dead weight in a Laravel app and cannot be autoloaded into a Laravel kernel meaningfully.

Integration feasibility — low for the package, moderate for the pattern.

  • Direct composer require intaro/hstore-bundle in a Laravel app is technically possible (MIT, autoloadable) but yields no behavior. There is no register()/boot() path.
  • The viable path is to vendor the ~100 lines of type logic into 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.
  • The alternative — and the one most TPMs should push for — is to not use hstore at all. PostgreSQL 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, explicitly. The repository description leads with [Deprecated]. There is no maintained successor referenced by this package.
  • Abandoned since 2014-11-10. Eleven-plus years without a commit. No PHP 8 compatibility work, no response to Doctrine DBAL 2.x→3.x→4.x API breaks (Type became an abstract with different signatures; getName() is deprecated in favor of class-as-identifier).
  • Near-zero signal. 5 stars, 0 dependents, composite score 0.375. There is no installed base to surface regressions, no issue triage, and no third-party forks with traction. If it breaks, we are the only ones who will ever know.
  • Supply-chain posture. MIT license is permissive and safe to fork/vendor; the repository itself is a dormant but low-blast-radius dependency if vendored rather than installed.
  • Data-model risk dominates code risk. hstore is a flat 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:

  1. Is there an existing PostgreSQL schema using hstore today (legacy DB, acquired system, read-only reporting replica)? If no, the answer is jsonb and this evaluation ends.
  2. If hstore exists, is it load-bearing (indexed, queried with @>, ?, -> operators in application SQL) or incidental?
  3. Are we on Doctrine ORM (laravel-doctrine/orm) or pure Eloquent? This determines whether a DBAL type is even reachable.
  4. What are the PHP and PostgreSQL versions in production? hstore requires the hstore extension (CREATE EXTENSION hstore); on managed services (RDS, Cloud SQL, Supabase) this is a parameter-group or extension-allowlist question with lead time.
  5. Who owns the vendored fork long-term, and is there a test fixture that exercises hstore round-tripping?
  6. Is there a write path back to hstore (dual-write during migration), or can we treat it as read-only?

Integration Approach

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.

  • Add jsonb columns, expose them through Eloquent casts ('array' or a custom cast), and get typed access, nesting, and GIN indexing for free.
  • Backfill with 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.
  • This removes the dependency question entirely and is the lowest-total-cost option by a wide margin.

Fallback path: port the type into application code.

  • Do not add 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.
  • Add CREATE EXTENSION IF NOT EXISTS hstore; to the schema baseline if it isn't already present.
  • Wrap the type in a feature flag so the read path can be toggled per environment during rollout.

Migration path and sequencing.

  1. Inventory (week 1): 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.
  2. Decision gate (week 1): if no production hstore data exists → jsonb, done. If it exists and is load-bearing → fallback path with a jsonb exit plan documented up front.
  3. Spike (week 2): one engineer, one hstore column, prove read/write/round-trip against a production-like snapshot, including null, empty map (''), and non-ASCII values.
  4. Additive schema (week 3): introduce the target column, dual-write from the application, verify parity with a nightly diff job.
  5. Cutover (week 4–5): flip reads, run for a full business cycle, drop the old column and the feature flag.

Compatibility considerations.

  • Pin to a vendored copy, never a floating version constraint — there will be no upstream patches.
  • Verify the type's 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.
  • Confirm requiresSQLCommentHint behavior, or schema-diff tooling will perpetually propose column type changes.

Operational Impact

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.

  • hstore itself scales acceptably for flat key/value at moderate row counts, but indexing requires the gin_hstore_ops operator class and extension availability, which is a managed-database configuration dependency rather than a schema-only concern.
  • Every read deserializes the entire map into PHP memory. Wide maps on high-cardinality tables will show up as allocation pressure before they show up as query latency.
  • All values are 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.

  • Silent type registration failure: the DBAL type isn't registered before the first query → Unknown column type "hstore" at runtime, not at boot. Assert registration in a health check.
  • String coercion drift: values that were written as numbers return as strings after a round-trip; downstream code that assumed an int gets a "0" truthiness surprise.
  • Null vs empty-map ambiguity: an empty hstore serializes as '', which is not distinguishable from null in some parse paths.
  • Key ordering loss: hstore does not preserve insertion order; any code relying on iteration order is a latent bug.
  • Migration stall: dual-write parity checks fail on edge-case rows, the cutover is delayed, and the temporary dual-write becomes permanent architecture.

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.

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