Doctrine – Point data type
- Томас
- Člen | 85
Dobrý den,
začínám s kdyby/doctrine a v mé aplikaci používám datový typ POINT pro uchování souřadnic.
mám:
// entita
/**
* @Column (type="point", nullable=false)
*/
protected $coords;
// v db je column
coords POINT not null;
// a používám pro uložení souřadnic
$a = new \Kdyby\Doctrine\Geo\Element();
$a->addCoordinate($latitude, $longitude);
$this->coords = $a;
přičemž mi doctrine po persist a flush vygeneruje sql :
insert into ... (id, coords) values(null, 'POINT(40.123456 14.123456)')
což mi vrací následující chybu:
SQLSTATE[22003]: Numeric value out of range: 1416 Cannot get geometry object from data you send to the GEOMETRY field
Já bych to „point(40…)“ potřeboval totiž obalit ještě, tzn. aby to bylo správně, tak potřebuju dostat:
insert into ... (id, coords) values(null, GeomFromText('POINT( 40.123456 14.123456)'));
Jak se dostanu k tomu, abych získal GeomFromText? Koukal jsem, že abstraktní třída GeometryType má funkci convertToDatabaseValueSQL, která přesně tenhle typ vrací, ale nemůžu se k ní dostat, protože „private“. Podle mě jen musím někde něco nastavit ještě u toho vytvoření objektu Geo\Element… pomohl by mi někdo?
Dík
- Томас
- Člen | 85
Upravil jsem si kdyby\doctrine\geo\element
a dostal jsem se k tomuhle výsledku:
INSERT INTO rh_alarms_1 (id, coords)
VALUES (NULL, 'GeomFromText('POINT(40.1234560000000 14.1234560000000)')')
To už vypadá dobře, akorát tam mám o 2 uvozovky navíc – první a poslední, správný výsledek by měl být
INSERT INTO rh_alarms_1 (id, coords)
VALUES (NULL, GeomFromText('POINT(40.1234560000000 14.1234560000000)'))
aby mi to vzala databáze a nebralo se to jako string… typuju, že budu muset třídu Element přetypovat jako číslo, ale netuším jak.. aspoň nějakej postup :-D
Ve třídě element už to upravit asi nemůžu, nevím.. když jsem si dumpnul string tak je bez těch uvozovek, takže se doplńují někde jinde…
upravil jsem funkci __toString následovně:
/**
* @return string
*/
public function __toString() {
if ($this->stringValue) {
$this->init();
}
$coordinates = implode($this->separator, $this->coordinates);
if (in_array($this->name, [self::POINT, self::LINE_STRING]))
{
// tady :-)
return ($this->name == self::POINT) ?
'GeomFromText(\'' . strtoupper($this->name) . '(' . $coordinates.')\')' :
strtoupper($this->name) . '(' . $coordinates . ')';
}
else
{
return strtoupper($this->name) . '((' . $coordinates . '))';
}
}
- Томас
- Člen | 85
Oukej, takže musel jsem přepsat:
2 metody v GeometryType.php
/**
* @param mixed|Kdyby\Doctrine\Geo\Element $value
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
* @return string|NULL
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if ($value instanceof Kdyby\Doctrine\Geo\Point) {
$value = sprintf('POINT(%F %F)', $value->getLongitude(), $value->getLatitude());
}
return $value;
}
/**
* @param string $value
* @param \Doctrine\DBAL\Platforms\AbstractPlatform $platform
* @return mixed|Kdyby\Doctrine\Geo\Element
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
if ($value === NULL || empty($value)) {
return NULL;
}
list($longitude, $latitude) = sscanf($value, 'POINT(%f %f)');
return new \Kdyby\Doctrine\Geo\Point($latitude, $longitude);
}
Vytvořit si novou třídu pro souřadnice:
<?php
namespace
Kdyby\Doctrine\Geo;
class Point
{
/**
* @param double|float $latitude
* @param double|float $longitude
*/
public function __construct($latitude, $longitude)
{
$this->latitude = ($latitude);
$this->longitude = ($longitude);
}
/**
* @return double|float
*/
public function getLatitude()
{
return ($this->latitude);
}
/**
* @return double|float
*/
public function getLongitude()
{
return ($this->longitude);
}
/**
* @param double|float $latitude
* @return Point
*/
public function setLatitude($latitude)
{
$this->latitude = ($latitude);
return ($this);
}
/**
* @param double|float $longitude
* @return Point
*/
public function setLongitude($longitude)
{
$this->longitude = ($longitude);
return ($this);
}
/**
* @param double|float $latitude
* @param double|float $longitude
* @return Point
*/
public function setCoords($latitude, $longitude)
{
$this->latitude = ($latitude);
$this->longitude = ($longitude);
return ($this);
}
}
a pak už stačí jen entitě předat
$entity->setCoords(new Point(lat,lng));
result pak je taky Point, masakr :-D, nechápu, proč to nefunguje už v základu (ale asi nějak funguje ten GeomFromText(point) jsem tam viděl, ale nevedla k němu cesta, tak nevím…