Use PostgreSQL's own types and functions in Doctrine

Map arrays, JSONB, ranges, PostGIS geometries, pgvector embeddings and over 100 column types to your entities, and call over 450 PostgreSQL functions and operators straight from DQL.

composer require martin-georgiev/postgresql-for-doctrine

Set it up with Doctrine, Symfony or Laravel.

The query you would write in PostgreSQL, and the Doctrine code that produces it.

PostgreSQL
SELECT id FROM products
WHERE attributes ->> 'color' = 'red'
DQL
SELECT p.id FROM App\Entity\Product p
WHERE JSON_GET_FIELD_AS_TEXT(p.attributes, 'color') = 'red'

What you can map and query

Column types

Arrays
Of nearly every core type, from integer[] and text[] to jsonb[], uuid[] and inet[]
JSON and JSONB
Read back as PHP arrays, scalars and nested structures included
Ranges
Date, timestamp and numeric ranges and multiranges as value objects, infinite bounds included
PostGIS
Geometry and geography columns, with their geometry type and SRID
pgvector
vector, halfvec and sparsevec embeddings for similarity search
Hierarchies
ltree paths, and lquery and ltxtquery patterns to match them
Your own types
PostgreSQL enums backed by PHP enums, and composite types
And more
Network addresses, geometric shapes, bit strings, money, XML, hstore, citext, cube and ULID

Functions and operators in DQL

Arrays and JSON
Containment and overlap, JSON paths, and aggregation with ordering and FILTER
Text search
Full-text search, regular expressions, trigram similarity and fuzzy matching
Dates and ranges
Range operators, date arithmetic and time series
PostGIS
Spatial relationships, measurements, constructors and validation
Window functions
Rankings, running totals and moving averages with OVER
Statistics
Medians, percentiles and other statistical aggregates, plus trigonometry and rounding
And more
Network addresses, hstore, XML and XPath, UUIDs and formatting

From install to your first query

  1. Install the package

    composer require martin-georgiev/postgresql-for-doctrine
  2. Register what you use

    Register each type and function with Doctrine, or list them in your Symfony or Laravel configuration.

    use Doctrine\DBAL\Types\Type;
    use MartinGeorgiev\Doctrine\DBAL\Types\TextArray;
    use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Contains;
    
    Type::addType('text[]', TextArray::class);
    $configuration->addCustomStringFunction('CONTAINS', Contains::class);
  3. Map the column and query it

    #[ORM\Column(type: 'text[]')]
    private array $tags;
    
    $em->createQuery('
        SELECT p FROM App\Entity\Product p
        WHERE CONTAINS(p.tags, ARRAY(:tag)) = TRUE
    ')->setParameter('tag', 'postgres')->getResult();

Tested in CI against

PHP8.2 to 8.5
PostgreSQL16 to 18
PostGIS3.4 to 3.6
Doctrine ORM2.14, 2.18 and 3
Doctrine Lexer1.2, 2.1 and 3