martin-georgiev/postgresql-for-doctrine
Adds PostgreSQL-specific power to Doctrine DBAL/ORM: rich native types (jsonb, arrays, ranges, network, geometric, etc.) plus DQL functions/operators for JSON and array querying. Supports PostgreSQL 9.4+ and PHP 8.2+.
Jsonb, Geometry, Range) aligns with Laravel’s entity-driven model. Each type is self-contained, reducing coupling and enabling selective adoption (e.g., use only Jsonb or PostGIS without migrating all types).ST_Distance, to_tsvector) enable native PostgreSQL operations in queries, avoiding raw SQL and reducing vendor lock-in. This is critical for Laravel apps with complex spatial/text search logic.registerTypes() in Doctrine\DBAL\Types\Type.Attribute/Cast system (e.g., #[Attribute] for Jsonb columns).DB::select("SELECT ST_Distance(..., ...)")).PostGIS, pg_trgm, pgvector) to be enabled. Laravel’s .env can manage this via DB_CONNECTION=pgsql + extension setup in migrations.Jsonb, then add Geometry).Jsonb parsing) may require manual type casting in Laravel models. Mitigation: Use Doctrine’s Platform abstraction to handle platform-specific conversions.GeometryArray) may introduce serialization overhead. Benchmark with PostGIS vs. raw SQL for spatial queries.pgvector) will cause runtime errors. Solution: Document required extensions in Laravel’s README and use migration hooks to enable them.Jsonb/Array types hydrate correctly in Eloquent’s hydrate().ST_Distance) may bypass Laravel’s cache. Use query tags or cache versioning.PostGIS, Ltree) or selectively (e.g., only Jsonb)?pgvector in 12+).services: postgres).Geometry) fails to hydrate?#[Attribute] and Cast traits.DB::raw().PostGIS, pg_trgm) must be enabled. Laravel’s .env can configure this:
DB_CONNECTION=pgsql
DB_POSTGRES_EXTENSIONS=postgis,pg_trgm
ST_Distance), improving maintainability and type safety.composer.json:
composer require martin-georgiev/postgresql-for-doctrine
// config/app.php
'providers' => [
MartinGeorgiev\Doctrine\Laravel\PostgresServiceProvider::class,
],
jsonb → Jsonb):
Schema::table('posts', function (Blueprint $table) {
$table->jsonb('metadata')->change(); // If using Laravel migrations
});
use MartinGeorgiev\Doctrine\DBAL\Type as PostgresType;
Schema::create('geocoded_places', function (Blueprint $table) {
$table->geometry('location', 4326); // PostGIS type
});
use MartinGeorgiev\Doctrine\DBAL\Type as PostgresType;
class Post extends Model {
protected $casts = [
'tags' => PostgresType::TEXT_ARRAY,
'coordinates' => PostgresType::POINT,
];
}
Jsonb), use accessors:
public function getMetadataAttribute($value) {
return json_decode($value, true); // Or use package's JsonbArray
}
// Before (raw SQL)
DB::select("SELECT ST_Distance(..., ...) FROM ...");
// After (DQL)
$query = Post::query()
->selectRaw('ST_Distance(location, ?) as distance', [$point])
->get();
use MartinGeorgiev\Doctrine\Laravel\Query\PostgresFunctions;
$results = Post::where(PostgresFunctions::ST_Distance('location', $point), '<', 1000)
->get();
PostGIS (for geometry/geography types).pg_trgm (for trigram similarity).pgvector (for vector search).Jsonb, Array, or UUID (low risk).Geometry, Range, or Ltree after validating core functionality.ST_Distance).How can I help you explore Laravel packages today?