Finalize first version
This commit is contained in:
parent
228d8517c7
commit
cbefb7c543
@ -13,11 +13,9 @@ class, converting the value on the database-level or a combination of both.
|
|||||||
This article describes the third way by implementing the MySQL specific column
|
This article describes the third way by implementing the MySQL specific column
|
||||||
type `Point <http://dev.mysql.com/doc/refman/5.5/en/gis-class-point.html>`_.
|
type `Point <http://dev.mysql.com/doc/refman/5.5/en/gis-class-point.html>`_.
|
||||||
|
|
||||||
The `Point` type is part of the `Spatial extension <http://dev.mysql.com/doc/refman/5.5/en/spatial-extensions.html>`_
|
The ``Point`` type is part of the `Spatial extension <http://dev.mysql.com/doc/refman/5.5/en/spatial-extensions.html>`_
|
||||||
of MySQL and enables you to store a single location in a coordinate space by
|
of MySQL and enables you to store a single location in a coordinate space by
|
||||||
using x and y coordinates.
|
using x and y coordinates. You can use the Point type to store a
|
||||||
|
|
||||||
As you might have already guessed, you can use the Point type to store a
|
|
||||||
longitude/latitude pair to represent a geographic location.
|
longitude/latitude pair to represent a geographic location.
|
||||||
|
|
||||||
The entity
|
The entity
|
||||||
@ -42,27 +40,53 @@ The entity class:
|
|||||||
/**
|
/**
|
||||||
* @Column(type="point")
|
* @Column(type="point")
|
||||||
*
|
*
|
||||||
* @var \Geo\Point
|
* @var \Geo\ValueObject\Point
|
||||||
*/
|
*/
|
||||||
private $point;
|
private $point;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \Geo\Point $point
|
* @Column(type="string")
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
*/
|
*/
|
||||||
public function setPoint(\Geo\Point $point)
|
private $address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Geo\ValueObject\Point $point
|
||||||
|
*/
|
||||||
|
public function setPoint(\Geo\ValueObject\Point $point)
|
||||||
{
|
{
|
||||||
$this->point = $point;
|
$this->point = $point;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Geo\Point
|
* @return \Geo\ValueObject\Point
|
||||||
*/
|
*/
|
||||||
public function getPoint()
|
public function getPoint()
|
||||||
{
|
{
|
||||||
return $this->point;
|
return $this->point;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $address
|
||||||
|
*/
|
||||||
|
public function setAddress($address)
|
||||||
|
{
|
||||||
|
$this->address = $address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getAddress()
|
||||||
|
{
|
||||||
|
return $this->address;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
We use the custom type ``point`` in the ``@Column`` docblock annotation of the
|
||||||
|
``$point`` field. We will create this custom mapping type in the next chapter.
|
||||||
|
|
||||||
The point class:
|
The point class:
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
@ -73,17 +97,28 @@ The point class:
|
|||||||
|
|
||||||
class Point
|
class Point
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param float $latitude
|
||||||
|
* @param float $longitude
|
||||||
|
*/
|
||||||
public function __construct($latitude, $longitude)
|
public function __construct($latitude, $longitude)
|
||||||
{
|
{
|
||||||
$this->latitude = $latitude;
|
$this->latitude = $latitude;
|
||||||
$this->longitude = $longitude;
|
$this->longitude = $longitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
public function getLatitude()
|
public function getLatitude()
|
||||||
{
|
{
|
||||||
return $this->latitude;
|
return $this->latitude;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
public function getLongitude()
|
public function getLongitude()
|
||||||
{
|
{
|
||||||
return $this->longitude;
|
return $this->longitude;
|
||||||
@ -93,10 +128,7 @@ The point class:
|
|||||||
The mapping type
|
The mapping type
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
As you may have noticed, we used the custom type ``point`` in the ``@Column``
|
Now we're going to create the ``point`` type and implement all required methods.
|
||||||
docblock annotation of the ``$point`` field.
|
|
||||||
|
|
||||||
Now we're going to create this type and implement all required methods.
|
|
||||||
|
|
||||||
.. code-block:: php
|
.. code-block:: php
|
||||||
|
|
||||||
@ -144,12 +176,76 @@ Now we're going to create this type and implement all required methods.
|
|||||||
return sprintf('AsText(%s)', $sqlExpr);
|
return sprintf('AsText(%s)', $sqlExpr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function convertToDatabaseValue($sqlExpr, AbstractPlatform $platform)
|
public function convertToDatabaseValueSQL($sqlExpr, AbstractPlatform $platform)
|
||||||
{
|
{
|
||||||
return sprintf('GeomFromText(%s)', $sqlExpr);
|
return sprintf('PointFromText(%s)', $sqlExpr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
A few notes about the implementation:
|
We do a 2-step conversion here. In the first step, we convert the ``Point``
|
||||||
|
object into a string representation before saving to the database (in the
|
||||||
|
``convertToDatabaseValue`` method) and back into an object after fetching the
|
||||||
|
value from the database (in the ``convertToPHPValue`` method).
|
||||||
|
|
||||||
*
|
The format of the string representation format is called `Well-known text (WKT)
|
||||||
|
<http://en.wikipedia.org/wiki/Well-known_text>`_. The advantage of this format
|
||||||
|
is, that it is both human readable and parsable by MySQL.
|
||||||
|
|
||||||
|
Internally, MySQL stores geometry values in a binary format that is not
|
||||||
|
identical to the WKT format. So, we need to let MySQL transform the WKT
|
||||||
|
representation into its internal format.
|
||||||
|
|
||||||
|
This is where the ``convertToPHPValueSQL`` and ``convertToDatabaseValueSQL``
|
||||||
|
methods come into play.
|
||||||
|
|
||||||
|
This methods wrap a sql expression (the WKT representation of the Point) into
|
||||||
|
MySQL functions `PointFromText <http://dev.mysql.com/doc/refman/5.5/en/creating-spatial-values.html#function_pointfromtext>`_
|
||||||
|
and `AsText <http://dev.mysql.com/doc/refman/5.5/en/functions-to-convert-geometries-between-formats.html#function_astext>`_
|
||||||
|
which convert WKT strings to and from the internal format of MySQL.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
When using DQL queries, the ``convertToPHPValueSQL`` and
|
||||||
|
``convertToDatabaseValueSQL`` methods only apply to identification variables
|
||||||
|
and path expressions in SELECT clauses. Expressions in WHERE clauses are
|
||||||
|
**not** wrapped!
|
||||||
|
|
||||||
|
If you want to use Point values in WHERE clauses, you have to implement a
|
||||||
|
:doc:`user defined function <dql-user-defined-functions>` for
|
||||||
|
``PointFromText``.
|
||||||
|
|
||||||
|
Example usage
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. code-block:: php
|
||||||
|
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// Bootstrapping stuff...
|
||||||
|
// $em = \Doctrine\ORM\EntityManager::create($connectionOptions, $config);
|
||||||
|
|
||||||
|
// Setup custom mapping type
|
||||||
|
use Doctrine\DBAL\Types\Type;
|
||||||
|
|
||||||
|
Type::addType('point', 'Geo\Types\Point');
|
||||||
|
$em->getConnection()->getDatabasePlatform()->registerDoctrineTypeMapping('point', 'point');
|
||||||
|
|
||||||
|
// Store a Location object
|
||||||
|
use Geo\Entity\Location;
|
||||||
|
use Geo\ValueObject\Point;
|
||||||
|
|
||||||
|
$location = new Location();
|
||||||
|
|
||||||
|
$location->setAddress('1600 Amphitheatre Parkway, Mountain View, CA');
|
||||||
|
$location->setPoint(new Point(37.4220761, -122.0845187));
|
||||||
|
|
||||||
|
$em->persist($location);
|
||||||
|
$em->flush();
|
||||||
|
$em->clear();
|
||||||
|
|
||||||
|
// Fetch the Location object
|
||||||
|
$query = $em->createQuery("SELECT l FROM Geo\Entity\Location WHERE l.address = '1600 Amphitheatre Parkway, Mountain View, CA'");
|
||||||
|
$location = $query->getSingleResult();
|
||||||
|
|
||||||
|
/* @var Geo\ValueObject\Point */
|
||||||
|
$point = $location->getPoint();
|
||||||
|
Loading…
Reference in New Issue
Block a user