cakePHPでMySQLのgeometry型を使う

Twitter ツイート Hatena Bookmark ブックマーク

cakephp1.3でMySQLのgeometry型を使いたとおもったのですが、普通にModel::saveだとうまくいきません。
afterSaveとかでsaveすると2回クエリなげることになって微妙な感じだったんで、なにか方法はないかと探していました。

まる2日間ぐらい悩んだんですが、DboSource::expression()使えばいいんじゃね?ってことで、試してみました。

とりあえずスキーマはこんな感じ

1
2
3
4
5
6
7
8
CREATE TABLE  `test`.`areas` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
`name` VARCHAR( 255 ) NOT NULL ,
`latlng` GEOMETRY NOT NULL ,
`created` DATETIME NOT NULL ,
`modified` DATETIME NOT NULL ,
PRIMARY KEY (  `id` )
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;

んで、適当にbakeとかしてmodelとかcontrollerとかつくっておきます。
controllerのsave前にexpressionを使えば良いわけです。
ちなみに前提としているPOSTされるデータは
$this->data[‘Area’][’name’],
$this->data[‘Area’][’lat’],
$this->data[‘Area’][’lng’],
といった感じになります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class AreasController extends AppController {

	var $name = 'Areas';

	function add() {
		if (!empty($this->data)) {
			$this->Area->create();
			if ( !is_null($this->data['Area']['lat']) &amp;&amp;  !is_null($this->data['Area']['lng']) ) {
				$this->data['Area']['latlng'] = $db->expression(
					&quot;GeomFromText('POINT({$this->data['Area']['lat']} {$this->data['Area']['lng']})')&quot;
				);
			}

			if ($this->Area->save($this->data)) {
				$this->Session->setFlash(__('The item has been saved', true));
				$this->redirect(array('action' => 'index'));
			}
		}
	}
}

これでエラーも出ずにsaveが出来てしまいます。
次はfind周りの対策をします。
findした際に戻り値が以下のような形になってしまいます。

1
 string '����������l�xa@:@0G��A@' (length=25)

これではさすがにカオスなので、modelに以下のように「$virtualFields」を指定しておきます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?php
class Area extends AppModel {
	var $name = 'Area';
	//The Associations below have been created with all possible keys, those that are not needed can be removed

	var $virtualFields = array(
    	'lng' => 'X(latlng)',
    	'lat' => 'Y(latlng)'
	);

}

そすると、普通にlatとlngに別れて値が戻ってきます。

[参考]
CakePHPでGeometry型を使ってみたよ。
Handling spatial data in CakePHP

comments powered by Disqus
Built with Hugo
テーマ StackJimmy によって設計されています。