Doctrine – Point data type

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
Томас
Člen | 85
+
0
-

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
+
0
-

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
+
0
-

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…