From a3e945d71e6384620075538defa497eecf5a29c4 Mon Sep 17 00:00:00 2001 From: Martin Georgiev Date: Fri, 5 Sep 2025 00:59:12 +0300 Subject: [PATCH] chore: clean up docs --- docs/INTEGRATING-WITH-DOCTRINE.md | 157 ++++--- docs/INTEGRATING-WITH-LARAVEL.md | 382 +++++++++++++----- docs/INTEGRATING-WITH-SYMFONY.md | 239 ++++++++--- docs/RANGE-TYPES.md | 4 +- docs/TEXT-AND-PATTERN-FUNCTIONS.md | 1 + .../AST/Functions/WebsearchToTsqueryTest.php | 6 +- 6 files changed, 574 insertions(+), 215 deletions(-) diff --git a/docs/INTEGRATING-WITH-DOCTRINE.md b/docs/INTEGRATING-WITH-DOCTRINE.md index a30892e8..96768f1a 100644 --- a/docs/INTEGRATING-WITH-DOCTRINE.md +++ b/docs/INTEGRATING-WITH-DOCTRINE.md @@ -1,27 +1,30 @@ ## Integration with Doctrine +This guide covers integration with Doctrine DBAL 3.x/4.x and ORM 2.14+/3.x. For older versions, please refer to previous documentation versions. -*Register the DBAL types you plan to use* +### Register DBAL Types -Full set of the available types can be found [here](AVAILABLE-TYPES.md). +Register the DBAL types you plan to use. The **full set** of available types can be found in [AVAILABLE-TYPES.md](AVAILABLE-TYPES.md). ```php addCustomStringFunction('REGEXP', MartinGeorgiev\Doctrine\ORM\Qu $configuration->addCustomStringFunction('IREGEXP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\IRegexp::class); $configuration->addCustomStringFunction('NOT_REGEXP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NotRegexp::class); $configuration->addCustomStringFunction('NOT_IREGEXP', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\NotIRegexp::class); -$configuration->addCustomStringFunction('REGEXP_LIKE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\FlaggedRegexpLike::class); +$configuration->addCustomStringFunction('REGEXP_LIKE', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpLike::class); $configuration->addCustomStringFunction('REGEXP_COUNT', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpCount::class); $configuration->addCustomStringFunction('REGEXP_INSTR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpInstr::class); $configuration->addCustomStringFunction('REGEXP_SUBSTR', MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\RegexpSubstr::class); @@ -217,54 +222,102 @@ $configuration->addCustomStringFunction('TO_TIMESTAMP', MartinGeorgiev\Doctrine\ $em = EntityManager::create($dbParams, $configuration); ``` -*Then you need to register type mappings like below, based on [documentation](https://www.doctrine-project.org/projects/doctrine-orm/en/2.6/cookbook/custom-mapping-types.html)* +### Register Platform Type Mappings + +Register type mappings between PostgreSQL and Doctrine types. This is required for schema introspection and migrations. Based on the [Doctrine documentation](https://www.doctrine-project.org/projects/doctrine-orm/en/current/cookbook/custom-mapping-types.html). ```php +getConnection()->getDatabasePlatform(); -$platform->registerDoctrineTypeMapping('bool[]','bool[]'); -$platform->registerDoctrineTypeMapping('_bool','bool[]'); -$platform->registerDoctrineTypeMapping('smallint[]','smallint[]'); -$platform->registerDoctrineTypeMapping('_int2','smallint[]'); -$platform->registerDoctrineTypeMapping('integer[]','integer[]'); -$platform->registerDoctrineTypeMapping('_int4','integer[]'); -$platform->registerDoctrineTypeMapping('bigint[]','bigint[]'); -$platform->registerDoctrineTypeMapping('_int8','bigint[]'); - -$platform->registerDoctrineTypeMapping('double precision[]','double precision[]'); -$platform->registerDoctrineTypeMapping('_float8','double precision[]'); -$platform->registerDoctrineTypeMapping('real[]','real[]'); -$platform->registerDoctrineTypeMapping('_float4','real[]'); - -$platform->registerDoctrineTypeMapping('text[]','text[]'); -$platform->registerDoctrineTypeMapping('_text','text[]'); -$platform->registerDoctrineTypeMapping('jsonb','jsonb'); -$platform->registerDoctrineTypeMapping('jsonb[]','jsonb[]'); -$platform->registerDoctrineTypeMapping('_jsonb','jsonb[]'); - -$platform->registerDoctrineTypeMapping('cidr[]','cidr[]'); -$platform->registerDoctrineTypeMapping('_cidr','cidr[]'); -$platform->registerDoctrineTypeMapping('inet[]','inet[]'); -$platform->registerDoctrineTypeMapping('_inet','inet[]'); -$platform->registerDoctrineTypeMapping('macaddr[]','macaddr[]'); -$platform->registerDoctrineTypeMapping('_macaddr','macaddr[]'); - -$platform->registerDoctrineTypeMapping('point','point'); -$platform->registerDoctrineTypeMapping('point[]','point[]'); -$platform->registerDoctrineTypeMapping('_point','point[]'); -$platform->registerDoctrineTypeMapping('geometry','geometry'); -$platform->registerDoctrineTypeMapping('geometry[]','geometry[]'); -$platform->registerDoctrineTypeMapping('_geometry','geometry[]'); -$platform->registerDoctrineTypeMapping('geography','geography'); -$platform->registerDoctrineTypeMapping('geography[]','geography[]'); -$platform->registerDoctrineTypeMapping('_geography','geography[]'); - -$platform->registerDoctrineTypeMapping('daterange','daterange'); -$platform->registerDoctrineTypeMapping('int4range','int4range'); -$platform->registerDoctrineTypeMapping('int8range','int8range'); -$platform->registerDoctrineTypeMapping('numrange','numrange'); -$platform->registerDoctrineTypeMapping('tsrange','tsrange'); -$platform->registerDoctrineTypeMapping('tstzrange','tstzrange'); -... +// Array type mappings +$platform->registerDoctrineTypeMapping('bool[]', 'bool[]'); +$platform->registerDoctrineTypeMapping('_bool', 'bool[]'); +$platform->registerDoctrineTypeMapping('smallint[]', 'smallint[]'); +$platform->registerDoctrineTypeMapping('_int2', 'smallint[]'); +$platform->registerDoctrineTypeMapping('integer[]', 'integer[]'); +$platform->registerDoctrineTypeMapping('_int4', 'integer[]'); +$platform->registerDoctrineTypeMapping('bigint[]', 'bigint[]'); +$platform->registerDoctrineTypeMapping('_int8', 'bigint[]'); +$platform->registerDoctrineTypeMapping('double precision[]', 'double precision[]'); +$platform->registerDoctrineTypeMapping('_float8', 'double precision[]'); +$platform->registerDoctrineTypeMapping('real[]', 'real[]'); +$platform->registerDoctrineTypeMapping('_float4', 'real[]'); +$platform->registerDoctrineTypeMapping('text[]', 'text[]'); +$platform->registerDoctrineTypeMapping('_text', 'text[]'); + +// JSON type mappings +$platform->registerDoctrineTypeMapping('jsonb', 'jsonb'); +$platform->registerDoctrineTypeMapping('jsonb[]', 'jsonb[]'); +$platform->registerDoctrineTypeMapping('_jsonb', 'jsonb[]'); + +// Network type mappings +$platform->registerDoctrineTypeMapping('cidr', 'cidr'); +$platform->registerDoctrineTypeMapping('cidr[]', 'cidr[]'); +$platform->registerDoctrineTypeMapping('_cidr', 'cidr[]'); +$platform->registerDoctrineTypeMapping('inet', 'inet'); +$platform->registerDoctrineTypeMapping('inet[]', 'inet[]'); +$platform->registerDoctrineTypeMapping('_inet', 'inet[]'); +$platform->registerDoctrineTypeMapping('macaddr', 'macaddr'); +$platform->registerDoctrineTypeMapping('macaddr[]', 'macaddr[]'); +$platform->registerDoctrineTypeMapping('_macaddr', 'macaddr[]'); + +// Spatial type mappings +$platform->registerDoctrineTypeMapping('point', 'point'); +$platform->registerDoctrineTypeMapping('point[]', 'point[]'); +$platform->registerDoctrineTypeMapping('_point', 'point[]'); +$platform->registerDoctrineTypeMapping('geometry', 'geometry'); +$platform->registerDoctrineTypeMapping('geometry[]', 'geometry[]'); +$platform->registerDoctrineTypeMapping('_geometry', 'geometry[]'); +$platform->registerDoctrineTypeMapping('geography', 'geography'); +$platform->registerDoctrineTypeMapping('geography[]', 'geography[]'); +$platform->registerDoctrineTypeMapping('_geography', 'geography[]'); + +// Range type mappings +$platform->registerDoctrineTypeMapping('daterange', 'daterange'); +$platform->registerDoctrineTypeMapping('int4range', 'int4range'); +$platform->registerDoctrineTypeMapping('int8range', 'int8range'); +$platform->registerDoctrineTypeMapping('numrange', 'numrange'); +$platform->registerDoctrineTypeMapping('tsrange', 'tsrange'); +$platform->registerDoctrineTypeMapping('tstzrange', 'tstzrange'); +``` + +### Usage in Entities + +Once types are registered, you can use them in your Doctrine entities: + +```php + [ 'default' => [ - ... + // ... other configuration 'type_mappings' => [ + // Array type mappings '_bool' => 'bool[]', 'bool[]' => 'bool[]', 'smallint[]' => 'smallint[]', @@ -24,19 +40,20 @@ return [ 'integer[]' => 'integer[]', '_int4' => 'integer[]', 'bigint[]' => 'bigint[]', - '_int8' => 'bigint', - + '_int8' => 'bigint[]', 'double precision[]' => 'double precision[]', '_float8' => 'double precision[]', 'real[]' => 'real[]', - '_float4' => 'real', - + '_float4' => 'real[]', '_text' => 'text[]', 'text[]' => 'text[]', + + // JSON type mappings 'jsonb' => 'jsonb', '_jsonb' => 'jsonb[]', 'jsonb[]' => 'jsonb[]', - + + // Network type mappings 'cidr' => 'cidr', 'cidr[]' => 'cidr[]', '_cidr' => 'cidr[]', @@ -46,66 +63,91 @@ return [ 'macaddr' => 'macaddr', 'macaddr[]' => 'macaddr[]', '_macaddr' => 'macaddr[]', - + + // Spatial type mappings 'point' => 'point', 'point[]' => 'point[]', '_point' => 'point[]', + 'geometry' => 'geometry', + 'geometry[]' => 'geometry[]', + '_geometry' => 'geometry[]', + 'geography' => 'geography', + 'geography[]' => 'geography[]', + '_geography' => 'geography[]', + + // Range type mappings + 'daterange' => 'daterange', + 'int4range' => 'int4range', + 'int8range' => 'int8range', + 'numrange' => 'numrange', + 'tsrange' => 'tsrange', + 'tstzrange' => 'tstzrange', ], ], ], -]; -``` - - -*Add mapping between DBAL and PostgreSQL data types* -```php - [ + // Array types 'bool[]' => MartinGeorgiev\Doctrine\DBAL\Types\BooleanArray::class, 'bigint[]' => MartinGeorgiev\Doctrine\DBAL\Types\BigIntArray::class, 'integer[]' => MartinGeorgiev\Doctrine\DBAL\Types\IntegerArray::class, 'smallint[]' => MartinGeorgiev\Doctrine\DBAL\Types\SmallIntArray::class, - 'double precision[]' => MartinGeorgiev\Doctrine\DBAL\Types\DoublePrecisionArray::class, 'real[]' => MartinGeorgiev\Doctrine\DBAL\Types\RealArray::class, - 'text[]' => MartinGeorgiev\Doctrine\DBAL\Types\TextArray::class, + + // JSON types 'jsonb' => MartinGeorgiev\Doctrine\DBAL\Types\Jsonb::class, 'jsonb[]' => MartinGeorgiev\Doctrine\DBAL\Types\JsonbArray::class, - + + // Network types 'cidr' => MartinGeorgiev\Doctrine\DBAL\Types\Cidr::class, 'cidr[]' => MartinGeorgiev\Doctrine\DBAL\Types\CidrArray::class, 'inet' => MartinGeorgiev\Doctrine\DBAL\Types\Inet::class, 'inet[]' => MartinGeorgiev\Doctrine\DBAL\Types\InetArray::class, 'macaddr' => MartinGeorgiev\Doctrine\DBAL\Types\Macaddr::class, 'macaddr[]' => MartinGeorgiev\Doctrine\DBAL\Types\MacaddrArray::class, - + + // Spatial types 'point' => MartinGeorgiev\Doctrine\DBAL\Types\Point::class, 'point[]' => MartinGeorgiev\Doctrine\DBAL\Types\PointArray::class, + 'geometry' => MartinGeorgiev\Doctrine\DBAL\Types\Geometry::class, + 'geometry[]' => MartinGeorgiev\Doctrine\DBAL\Types\GeometryArray::class, + 'geography' => MartinGeorgiev\Doctrine\DBAL\Types\Geography::class, + 'geography[]' => MartinGeorgiev\Doctrine\DBAL\Types\GeographyArray::class, + + // Range types + 'daterange' => MartinGeorgiev\Doctrine\DBAL\Types\DateRange::class, + 'int4range' => MartinGeorgiev\Doctrine\DBAL\Types\Int4Range::class, + 'int8range' => MartinGeorgiev\Doctrine\DBAL\Types\Int8Range::class, + 'numrange' => MartinGeorgiev\Doctrine\DBAL\Types\NumRange::class, + 'tsrange' => MartinGeorgiev\Doctrine\DBAL\Types\TsRange::class, + 'tstzrange' => MartinGeorgiev\Doctrine\DBAL\Types\TstzRange::class, ], + + // ... other configuration ]; ``` -*Register the functions you'll use in your DQL queries* +### Register DQL Functions -Full set of the available functions and extra operators can be found in the [Available Functions and Operators](AVAILABLE-FUNCTIONS-AND-OPERATORS.md) documentation and its specialized sub-pages: +Register the functions you'll use in your DQL queries. The full set of available functions and operators can be found in the [Available Functions and Operators](AVAILABLE-FUNCTIONS-AND-OPERATORS.md) documentation and its specialized sub-pages: - [Array and JSON Functions](ARRAY-AND-JSON-FUNCTIONS.md) - [PostGIS Spatial Functions](SPATIAL-FUNCTIONS-AND-OPERATORS.md) - [Text and Pattern Functions](TEXT-AND-PATTERN-FUNCTIONS.md) - [Date and Range Functions](DATE-AND-RANGE-FUNCTIONS.md) - [Mathematical Functions](MATHEMATICAL-FUNCTIONS.md) +Add the function configuration to your `config/doctrine.php`: + ```php [ # alternative implementation of ALL() and ANY() where subquery is not required, useful for arrays 'ALL_OF' => MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\All::class, @@ -265,22 +307,23 @@ return [ ``` -*Create an EventSubscriber for the new data types* +### Alternative: Event Subscriber for Type Registration + +If you prefer to register types programmatically, you can create an event subscriber: ```php registerArrayTypes(); + $this->registerJsonTypes(); + $this->registerNetworkTypes(); + $this->registerSpatialTypes(); + $this->registerRangeTypes(); + } + + private function registerArrayTypes(): void + { + $this->addTypeIfNotExists('bool[]', \MartinGeorgiev\Doctrine\DBAL\Types\BooleanArray::class); + $this->addTypeIfNotExists('bigint[]', \MartinGeorgiev\Doctrine\DBAL\Types\BigIntArray::class); + $this->addTypeIfNotExists('integer[]', \MartinGeorgiev\Doctrine\DBAL\Types\IntegerArray::class); + $this->addTypeIfNotExists('smallint[]', \MartinGeorgiev\Doctrine\DBAL\Types\SmallIntArray::class); + $this->addTypeIfNotExists('double precision[]', \MartinGeorgiev\Doctrine\DBAL\Types\DoublePrecisionArray::class); + $this->addTypeIfNotExists('real[]', \MartinGeorgiev\Doctrine\DBAL\Types\RealArray::class); + $this->addTypeIfNotExists('text[]', \MartinGeorgiev\Doctrine\DBAL\Types\TextArray::class); + } + + private function registerJsonTypes(): void + { + $this->addTypeIfNotExists('jsonb', \MartinGeorgiev\Doctrine\DBAL\Types\Jsonb::class); + $this->addTypeIfNotExists('jsonb[]', \MartinGeorgiev\Doctrine\DBAL\Types\JsonbArray::class); + } + + private function registerNetworkTypes(): void + { + $this->addTypeIfNotExists('cidr', \MartinGeorgiev\Doctrine\DBAL\Types\Cidr::class); + $this->addTypeIfNotExists('cidr[]', \MartinGeorgiev\Doctrine\DBAL\Types\CidrArray::class); + $this->addTypeIfNotExists('inet', \MartinGeorgiev\Doctrine\DBAL\Types\Inet::class); + $this->addTypeIfNotExists('inet[]', \MartinGeorgiev\Doctrine\DBAL\Types\InetArray::class); + $this->addTypeIfNotExists('macaddr', \MartinGeorgiev\Doctrine\DBAL\Types\Macaddr::class); + $this->addTypeIfNotExists('macaddr[]', \MartinGeorgiev\Doctrine\DBAL\Types\MacaddrArray::class); + } + + private function registerSpatialTypes(): void + { + $this->addTypeIfNotExists('point', \MartinGeorgiev\Doctrine\DBAL\Types\Point::class); + $this->addTypeIfNotExists('point[]', \MartinGeorgiev\Doctrine\DBAL\Types\PointArray::class); + $this->addTypeIfNotExists('geometry', \MartinGeorgiev\Doctrine\DBAL\Types\Geometry::class); + $this->addTypeIfNotExists('geometry[]', \MartinGeorgiev\Doctrine\DBAL\Types\GeometryArray::class); + $this->addTypeIfNotExists('geography', \MartinGeorgiev\Doctrine\DBAL\Types\Geography::class); + $this->addTypeIfNotExists('geography[]', \MartinGeorgiev\Doctrine\DBAL\Types\GeographyArray::class); + } + + private function registerRangeTypes(): void + { + $this->addTypeIfNotExists('daterange', \MartinGeorgiev\Doctrine\DBAL\Types\DateRange::class); + $this->addTypeIfNotExists('int4range', \MartinGeorgiev\Doctrine\DBAL\Types\Int4Range::class); + $this->addTypeIfNotExists('int8range', \MartinGeorgiev\Doctrine\DBAL\Types\Int8Range::class); + $this->addTypeIfNotExists('numrange', \MartinGeorgiev\Doctrine\DBAL\Types\NumRange::class); + $this->addTypeIfNotExists('tsrange', \MartinGeorgiev\Doctrine\DBAL\Types\TsRange::class); + $this->addTypeIfNotExists('tstzrange', \MartinGeorgiev\Doctrine\DBAL\Types\TstzRange::class); + } + + private function addTypeIfNotExists(string $name, string $className): void + { + if (!Type::hasType($name)) { + Type::addType($name, $className); } } } ``` +Register this subscriber in your `config/doctrine.php`: + +```php +// config/doctrine.php +return [ + // ... other configuration + + 'managers' => [ + 'default' => [ + // ... other configuration + + 'events' => [ + 'subscribers' => [ + \App\Doctrine\EventSubscribers\PostgreSQLTypesSubscriber::class, + ], + ], + ], + ], +]; +``` + + +### Usage in Entities + +Once configured, you can use PostgreSQL types in your Laravel entities: + +```php +app->resolving('em', function ($entityManager) { + $this->registerPlatformTypeMappings($entityManager); + }); + } - $this->registerDoctrineTypeMapping(); + public function boot(): void + { + $this->registerCustomTypes(); } - private function registerDoctrineTypeMapping(): void + private function registerCustomTypes(): void { - $databasePlatform = $this->app->make('registry')->getConnection()->getDatabasePlatform(); - $entityManagers = $this->app->make('config')->get('doctrine.managers'); - foreach ($entityManagers as $entityManager) { - if (!array_key_exists('type_mappings', $entityManager)) { - continue; - } - foreach ($entityManager['type_mappings'] as $dbType => $doctrineName) { - $databasePlatform->registerDoctrineTypeMapping($dbType, $doctrineName); + // Register types if not already registered + $types = [ + 'jsonb' => \MartinGeorgiev\Doctrine\DBAL\Types\Jsonb::class, + 'text[]' => \MartinGeorgiev\Doctrine\DBAL\Types\TextArray::class, + 'point' => \MartinGeorgiev\Doctrine\DBAL\Types\Point::class, + 'numrange' => \MartinGeorgiev\Doctrine\DBAL\Types\NumRange::class, + // Add other types as needed... + ]; + + foreach ($types as $name => $class) { + if (!Type::hasType($name)) { + Type::addType($name, $class); } } } + + private function registerPlatformTypeMappings($entityManager): void + { + $platform = $entityManager->getConnection()->getDatabasePlatform(); + + $mappings = [ + 'jsonb' => 'jsonb', + '_text' => 'text[]', + 'text[]' => 'text[]', + 'point' => 'point', + '_point' => 'point[]', + 'numrange' => 'numrange', + // Add other mappings as needed... + ]; + + foreach ($mappings as $dbType => $doctrineType) { + $platform->registerDoctrineTypeMapping($dbType, $doctrineType); + } + } } ``` + +Register this provider in `config/app.php`: + +```php +// config/app.php +'providers' => [ + // ... other providers + App\Providers\PostgreSQLDoctrineServiceProvider::class, +], +``` + +### Artisan Commands + +You can use Laravel Doctrine's Artisan commands for schema management: + +```bash +# Generate migrations +php artisan doctrine:migrations:diff + +# Run migrations +php artisan doctrine:migrations:migrate + +# Generate entities from database +php artisan doctrine:generate:entities + +# Validate schema +php artisan doctrine:schema:validate +``` diff --git a/docs/INTEGRATING-WITH-SYMFONY.md b/docs/INTEGRATING-WITH-SYMFONY.md index 1b6b319c..a5e15794 100644 --- a/docs/INTEGRATING-WITH-SYMFONY.md +++ b/docs/INTEGRATING-WITH-SYMFONY.md @@ -1,91 +1,122 @@ ## Integration with Symfony +This guide covers integration with Symfony 6.4+ and 7.x using the DoctrineBundle. For older Symfony versions, please refer to previous documentation versions. -*Register the DBAL types you plan to use* +### Register DBAL Types -Full set of the available types can be found [here](AVAILABLE-TYPES.md). +Register the DBAL types you plan to use. The full set of available types can be found in [AVAILABLE-TYPES.md](AVAILABLE-TYPES.md). ```yaml -# Usually part of config.yml +# config/packages/doctrine.yaml doctrine: dbal: - types: # register the new types - bool[]: MartinGeorgiev\Doctrine\DBAL\Types\BooleanArray - smallint[]: MartinGeorgiev\Doctrine\DBAL\Types\SmallIntArray - integer[]: MartinGeorgiev\Doctrine\DBAL\Types\IntegerArray - bigint[]: MartinGeorgiev\Doctrine\DBAL\Types\BigIntArray - - double precision[]: MartinGeorgiev\Doctrine\DBAL\Types\DoublePrecisionArray - real[]: MartinGeorgiev\Doctrine\DBAL\Types\RealArray - - text[]: MartinGeorgiev\Doctrine\DBAL\Types\TextArray + types: + # Array types + 'bool[]': MartinGeorgiev\Doctrine\DBAL\Types\BooleanArray + 'smallint[]': MartinGeorgiev\Doctrine\DBAL\Types\SmallIntArray + 'integer[]': MartinGeorgiev\Doctrine\DBAL\Types\IntegerArray + 'bigint[]': MartinGeorgiev\Doctrine\DBAL\Types\BigIntArray + 'double precision[]': MartinGeorgiev\Doctrine\DBAL\Types\DoublePrecisionArray + 'real[]': MartinGeorgiev\Doctrine\DBAL\Types\RealArray + 'text[]': MartinGeorgiev\Doctrine\DBAL\Types\TextArray + + # JSON types jsonb: MartinGeorgiev\Doctrine\DBAL\Types\Jsonb - jsonb[]: MartinGeorgiev\Doctrine\DBAL\Types\JsonbArray - + 'jsonb[]': MartinGeorgiev\Doctrine\DBAL\Types\JsonbArray + + # Network types cidr: MartinGeorgiev\Doctrine\DBAL\Types\Cidr - cidr[]: MartinGeorgiev\Doctrine\DBAL\Types\CidrArray + 'cidr[]': MartinGeorgiev\Doctrine\DBAL\Types\CidrArray inet: MartinGeorgiev\Doctrine\DBAL\Types\Inet - inet[]: MartinGeorgiev\Doctrine\DBAL\Types\InetArray + 'inet[]': MartinGeorgiev\Doctrine\DBAL\Types\InetArray macaddr: MartinGeorgiev\Doctrine\DBAL\Types\Macaddr - macaddr[]: MartinGeorgiev\Doctrine\DBAL\Types\MacaddrArray + 'macaddr[]': MartinGeorgiev\Doctrine\DBAL\Types\MacaddrArray + # Spatial types point: MartinGeorgiev\Doctrine\DBAL\Types\Point - point[]: MartinGeorgiev\Doctrine\DBAL\Types\PointArray -``` + 'point[]': MartinGeorgiev\Doctrine\DBAL\Types\PointArray + geometry: MartinGeorgiev\Doctrine\DBAL\Types\Geometry + 'geometry[]': MartinGeorgiev\Doctrine\DBAL\Types\GeometryArray + geography: MartinGeorgiev\Doctrine\DBAL\Types\Geography + 'geography[]': MartinGeorgiev\Doctrine\DBAL\Types\GeographyArray + # Range types + daterange: MartinGeorgiev\Doctrine\DBAL\Types\DateRange + int4range: MartinGeorgiev\Doctrine\DBAL\Types\Int4Range + int8range: MartinGeorgiev\Doctrine\DBAL\Types\Int8Range + numrange: MartinGeorgiev\Doctrine\DBAL\Types\NumRange + tsrange: MartinGeorgiev\Doctrine\DBAL\Types\TsRange + tstzrange: MartinGeorgiev\Doctrine\DBAL\Types\TstzRange +``` -*Add mapping between DBAL and PostgreSQL data types* -PostgreSQL will normally prefix array data-types with `_`. -Beware of the specific to PostgreSQL primary way of data-type naming for integers (`int2`, `int4`, `int8`). +### Configure Type Mappings +Add mapping between DBAL and PostgreSQL data types. PostgreSQL normally prefixes array data-types with `_`. Note the PostgreSQL-specific naming for integers (`int2`, `int4`, `int8`). ```yaml -# Usually part of config.yml +# config/packages/doctrine.yaml doctrine: dbal: connections: - your_connection: + default: mapping_types: - bool[]: bool[] - _bool: bool[] - smallint[]: smallint[] - _int2: smallint[] - integer[]: integer[] - _int4: integer[] - bigint[]: bigint[] - _int8: bigint[] - - double precision[]: double precision[] - _float8: double precision[] - real[]: real[] - _float4: real[] - - text[]: text[] - _text: text[] + # Array type mappings + 'bool[]': 'bool[]' + _bool: 'bool[]' + 'smallint[]': 'smallint[]' + _int2: 'smallint[]' + 'integer[]': 'integer[]' + _int4: 'integer[]' + 'bigint[]': 'bigint[]' + _int8: 'bigint[]' + 'double precision[]': 'double precision[]' + _float8: 'double precision[]' + 'real[]': 'real[]' + _float4: 'real[]' + 'text[]': 'text[]' + _text: 'text[]' + + # JSON type mappings jsonb: jsonb - jsonb[]: jsonb[] - _jsonb: jsonb[] - + 'jsonb[]': 'jsonb[]' + _jsonb: 'jsonb[]' + + # Network type mappings cidr: cidr - cidr[]: cidr[] - _cidr: cidr[] + 'cidr[]': 'cidr[]' + _cidr: 'cidr[]' inet: inet - inet[]: inet[] - _inet: inet[] + 'inet[]': 'inet[]' + _inet: 'inet[]' macaddr: macaddr - macaddr[]: macaddr[] - _macaddr: macaddr[] + 'macaddr[]': 'macaddr[]' + _macaddr: 'macaddr[]' + # Spatial type mappings point: point - point[]: point[] - _point: point[] + 'point[]': 'point[]' + _point: 'point[]' + geometry: geometry + 'geometry[]': 'geometry[]' + _geometry: 'geometry[]' + geography: geography + 'geography[]': 'geography[]' + _geography: 'geography[]' + + # Range type mappings + daterange: daterange + int4range: int4range + int8range: int8range + numrange: numrange + tsrange: tsrange + tstzrange: tstzrange ``` -*Register the functions you'll use in your DQL queries* +### Register DQL Functions -Full set of the available functions and extra operators can be found in the [Available Functions and Operators](AVAILABLE-FUNCTIONS-AND-OPERATORS.md) documentation and its specialized sub-pages: +Register the functions you'll use in your DQL queries. The full set of available functions and operators can be found in the [Available Functions and Operators](AVAILABLE-FUNCTIONS-AND-OPERATORS.md) documentation and its specialized sub-pages: - [Array and JSON Functions](ARRAY-AND-JSON-FUNCTIONS.md) - [PostGIS Spatial Functions](SPATIAL-FUNCTIONS-AND-OPERATORS.md) - [Text and Pattern Functions](TEXT-AND-PATTERN-FUNCTIONS.md) @@ -93,7 +124,7 @@ Full set of the available functions and extra operators can be found in the [Ava - [Mathematical Functions](MATHEMATICAL-FUNCTIONS.md) ```yaml -# Usually part of config.yml +# config/packages/doctrine.yaml doctrine: orm: entity_managers: @@ -253,3 +284,101 @@ doctrine: TO_NUMBER: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToNumber TO_TIMESTAMP: MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\ToTimestamp ``` + +### Usage in Entities + +Once configured, you can use the PostgreSQL types in your Symfony entities: + +```php +executeDqlQuery($dql); @@ -26,7 +26,7 @@ public function websearch_to_tsquery_with_explicit_config(): void } #[Test] - public function websearch_to_tsquery_with_default_config(): void + public function can_use_default_config(): void { $dql = "SELECT websearch_to_tsquery('\"sad cat\" or \"fat rat\"') as result FROM Fixtures\\MartinGeorgiev\\Doctrine\\Entity\\ContainsTexts t WHERE t.id = 1"; $result = $this->executeDqlQuery($dql); @@ -34,7 +34,7 @@ public function websearch_to_tsquery_with_default_config(): void } #[Test] - public function totsquery_throws_with_invalid_input(): void + public function throws_for_invalid_config_input(): void { $this->expectException(DriverException::class); $this->expectExceptionMessageMatches('/text search configuration .*invalid_regconfig.* does not exist/i');