useMartinGeorgiev\Doctrine\DBAL\Types\ValueObject\WktSpatialData;useMartinGeorgiev\Doctrine\DBAL\Types\ValueObject\GeometryType;useMartinGeorgiev\Doctrine\DBAL\Types\ValueObject\DimensionalModifier;// Build from individual components$point=WktSpatialData::fromComponents(GeometryType::POINT,'1 2');// With SRID$pointWithSrid=WktSpatialData::fromComponents(GeometryType::POINT,'-122.4194 37.7749',4326);// With dimensional modifier$line3d=WktSpatialData::fromComponents(GeometryType::LINESTRING,'0 0 1, 1 1 2, 2 2 3',null,DimensionalModifier::Z);// With all parameters$polygon4d=WktSpatialData::fromComponents(GeometryType::POLYGON,'0 0 0 1, 0 1 0 1, 1 1 0 1, 1 0 0 1, 0 0 0 1',4326,DimensionalModifier::ZM);
Convenience Methods for Points
useMartinGeorgiev\Doctrine\DBAL\Types\ValueObject\WktSpatialData;// Simple 2D point$point=WktSpatialData::point(1,2);// Result: POINT(1 2)// Point with SRID (common for geographic coordinates)$location=WktSpatialData::point(-122.4194,37.7749,4326);// Result: SRID=4326;POINT(-122.4194 37.7749)// 3D point with elevation$point3d=WktSpatialData::point3d(-122.4194,37.7749,100);// Result: POINT Z(-122.4194 37.7749 100)// 3D point with SRID$location3d=WktSpatialData::point3d(-122.4194,37.7749,100,4326);// Result: SRID=4326;POINT Z(-122.4194 37.7749 100)
Supported Geometry Types
The library supports all PostGIS geometry types through the GeometryType enum:
By default geometry and geography columns are declared as bare GEOMETRY / GEOGRAPHY. A bare GEOMETRY column accepts any subtype and any SRID. A bare GEOGRAPHY column is narrower: it accepts only geography-compatible subtypes (PostGIS rejects e.g. TIN) and geodetic lon/lat SRIDs, and stores SRID-less input as SRID 4326. Two column options add a PostGIS type modifier so the constraint is enforced by PostgreSQL itself:
Option
Type
Meaning
geometry_type
string
The geometry subtype, e.g. Point, LineString, MultiPolygon. Case-insensitive. May carry a dimensional modifier suffix: PointZ, PointM, PointZM. Use Geometry for “any subtype”.
srid
int
The spatial reference system identifier, e.g. 4326. Must be a non-negative integer.
useDoctrine\ORM\MappingasORM;useMartinGeorgiev\Doctrine\DBAL\Types\ValueObject\WktSpatialData;#[ORM\Entity]classPlace{// GEOGRAPHY(POINT,4326)#[ORM\Column(type: 'geography', options: ['geometry_type' => 'Point', 'srid' => 4326])]privateWktSpatialData$location;// GEOMETRY(POLYGONZ) — 3D polygons, SRID unconstrained#[ORM\Column(type: 'geometry', options: ['geometry_type' => 'PolygonZ'])]privateWktSpatialData$volume;// GEOMETRY(GEOMETRY,3857) — any subtype, but SRID pinned to Web Mercator#[ORM\Column(type: 'geometry', options: ['srid' => 3857])]privateWktSpatialData$tileShape;// GEOMETRY — unconstrained#[ORM\Column(type: 'geometry')]privateWktSpatialData$shape;}
Both options are optional and independent:
Neither option → bare GEOMETRY / GEOGRAPHY.
geometry_type only → GEOMETRY(POINT).
srid only → GEOMETRY(GEOMETRY,4326), since PostGIS requires a subtype whenever an SRID is given.
Caveats
The options only shape the DDL that Doctrine generates. They do not alter value conversion — a WktSpatialData carrying a different subtype is still handed to PostgreSQL, which rejects it at insert time.
geography only supports lon/lat reference systems; PostgreSQL rejects e.g. GEOGRAPHY(POINT,3857) at CREATE TABLE time.
A constrained column coerces values that carry no SRID: inserting POINT(1 2) into GEOMETRY(POINT,4326) stores SRID=4326;POINT(1 2).
Doctrine’s schema comparator does not understand PostGIS type modifiers, so doctrine:schema:update and diff-based migration generation may report spurious changes for these columns. Manage them with explicit migrations.
Spatial (GiST) indexes are not covered by these options. Declare them in a migration with raw SQL: CREATE INDEX idx_place_location ON place USING GIST (location);
Geography vs Geometry specifics
Geometry accepts WKT and EWKT (SRID=...;...).
Geography commonly uses SRID 4326; EWKT is supported (e.g., SRID=4326;POINT(...)).
Dimensional modifiers (Z, M, ZM) are normalized consistently for both types.
Arrays
GEOMETRY[] and GEOGRAPHY[] bind through DBAL parameter binding, with any number of elements.
A null element is written as a SQL NULL element and read back as null.
The spatial types provide error handling for invalid spatial data:
Common Validation Errors
useMartinGeorgiev\Doctrine\DBAL\Types\ValueObject\Exceptions\InvalidWktSpatialDataException;try{// Invalid WKT format$invalid=WktSpatialData::fromString('INVALID(1 2)');}catch(InvalidWktSpatialDataException$e){// Throws: "Unsupported geometry type: 'INVALID'. Supported types: POINT, LINESTRING, POLYGON, …"}try{// Empty coordinate section$empty=WktSpatialData::fromString('POINT()');}catch(InvalidWktSpatialDataException$e){// Throws: "Invalid Wkt: empty coordinate/body section"}try{// Invalid SRID format$invalidSrid=WktSpatialData::fromString('SRID=abc;POINT(1 2)');}catch(InvalidWktSpatialDataException$e){// Throws: "Invalid Srid value in Ewkt: 'abc'"}try{// Missing semicolon in EWKT$missingSemicolon=WktSpatialData::fromString('SRID=4326POINT(1 2)');}catch(InvalidWktSpatialDataException$e){// Throws: "Invalid Ewkt: missing semicolon after Srid prefix"}
Database Conversion Errors
useMartinGeorgiev\Doctrine\DBAL\Types\Exceptions\InvalidGeometryForDatabaseException;useMartinGeorgiev\Doctrine\DBAL\Types\Exceptions\InvalidGeometryForPHPException;// Invalid type passed to a geometry columntry{$geometryType->convertToDatabaseValue('not a geometry',$platform);}catch(InvalidGeometryForDatabaseException$e){// Throws: "Value must be a Geometry value object, 'not a geometry' given"}// Invalid format from the databasetry{$geometryType->convertToPHPValue('invalid wkt from db',$platform);}catch(InvalidGeometryForPHPException$e){// Throws: "Invalid Geometry value object format: 'invalid wkt from db'"}
Validation Best Practices
// Validate WKT before database operationsfunctionvalidateSpatialData(string$wkt):bool{try{WktSpatialData::fromString($wkt);returntrue;}catch(InvalidWktSpatialDataException){returnfalse;}}// Check geometry type before processing$spatialData=WktSpatialData::fromString('POINT(1 2)');if($spatialData->getGeometryType()===GeometryType::POINT){// Process point-specific logic}// Validate SRID for geography operations$geographyData=WktSpatialData::fromString('SRID=4326;POINT(-122 37)');if($geographyData->getSrid()===4326){// Valid for geography operations}