LoginSignup
5
4

More than 5 years have passed since last update.

fuelphpでgeometry型を扱う

Posted at

MySQLのviewを使うことで実現してみた。

ここではSpotという、名前と説明と位置情報を持つデータを考えてみる。

scaffoldでは、geometryを指定

php oil g scaffold -f spots title:string description:string location:geometry

できあがったmigrationファイルのup()関数内で

\DBUtil::create_index('spots', 'location', 'sp_index', 'spatial');
\DB::query("create view spots_all_view as select id, title, description, ASTEXT(location) as location, created_at, updated_at from spots")->execute();

自動生成されたSpotの定義内の$_observersに、

'Model_Spot_Observer' => array(
                                 'events' => array('before_save', 'after_load'),
                              );

を追加。

で、Model_Spot_Observerの実態は

class Model_Spot_Observer extends Orm\Observer
{
    public function before_save(Model_Spot $obj)
    {
        $location = $obj->location;
        $obj->set('location', \DB::expr('GeomFromText("POINT('.$location[0].' '.$location[1].')")'));
    }


    public function after_load(Model_Spot $obj)
    {
        $location = $obj->location;
        preg_match('/POINT\((.+)\s(.+)\)/', $location, $matches);
        $obj->location = array($matches[1], $matches[2]);

    }
}

before_saveは、値がDBに保存される前処理。ここで、controllerから配列形式で渡した緯度経度情報を基にGeomFromText関数の呼び出し形式の文字列を生成し、locationに設定する。

after_loadはDBから値を読み込んだ時の後処理。MySQLのviewの定義を見るとわかるように、ASTEXT(location) as locationとしているので、DBから読み込んだ値は"POINT(経度 緯度)"という文字列になる。ここままでは非常に扱いにくいのafter_load関数でその値を配列にしてあげる。

これによって、controller、viewから見れば、緯度経度情報が配列で扱えるようになる。

もっとうまいやり方があるのかもしれないが、とりあえずはこれで動くといえば動く。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4