reza-id/yii2-geopoint

支持 MySQL 空间点数据的 Yii2 ActiveRecord

安装次数: 2,047

依赖项: 0

建议者: 0

安全: 0

星标: 5

关注者: 2

分支: 3

公开问题: 1

类型:yii2-extension

v1.1.0 2017-10-30 07:33 UTC

This package is not auto-updated.

Last update: 2024-09-28 20:14:29 UTC


README

受yii2-spatial启发,但只使用特定空间数据类型:POINT,简化了ActiveRecord的使用。
在查找后,将内部MySQL格式转换为简单坐标文本,存储前反之。

Yii2-geopoint 也可用于查找与给定位置最近的模型或多个模型。

注意,此扩展程序可以与 MySQL >= 5.6.1MariaDB >= 5.3.3PostgreSQL >= 9.1 一起使用。

安装

使用 Composer 安装 Yii2-geopoint。可以在你的 composer.json 文件的 require 部分添加以下内容

"reza-id/yii2-geopoint": "*"

或者运行

$ php composer.phar require reza-id/yii2-geopoint "*"

您可以通过 下载ZIP格式的源代码 手动安装 Yii2-geopoint

用法

使用迁移创建空间索引表

$this->createTable('{{%place}}', [
	'id' => $this->primaryKey(),
	'name' => $this->string(125)->notNull(),
	'location' => 'POINT NOT NULL',
], $tableOptions);

if ($this->db->driverName === 'mysql') {
	$this->execute('CREATE SPATIAL INDEX `idx-place-location` ON '.'{{%place}}(location);');
} elseif ($this->db->driverName === 'pgsql') {
	$this->execute('CREATE INDEX "idx-place-location" ON '.'{{%place}} USING GIST(location);');
}

rezaid\geopoint\ActiveRecord 作为模型的基础类,如下所示

<?php
namespace app\models;

use rezaid\geopoint\ActiveRecord;

class MyModel extends ActiveRecord
{
    // ...
}

注意:如果您在一个派生自 rezaid\geopoint\ActiveRecord 的类中重写 find(),请确保返回一个 rezaid\geopoint\ActiveQuery 而不是一个 '普通' 的 yii\db\ActiveQuery

ActiveQuery 方法

nearest()

public function nearest($from, $attribute, $radius, $unit)

更改查询,使其找到由 $from 给定的点最近的模型。

  • $from - string:形式为 <lng>,<lat> 的位置(两个 floats)。
  • $attribute - string:模型中 Point 的属性名称。
  • $radius - number:以公里或英里为单位的搜索半径。默认 100
  • $unit - string:单位值,km 代表公里,mil 代表英里。默认 km

示例用法

$here = '4.9,52.3';     // longitude and latitude of my place
 

$nearestModel = <model>::find()->nearest($here, <attributeName>, 200, 'mil')->one();    // search radius is 200 miles

$fiveNearestModels =  <model>::find()->nearest($here, <attributeName>)->limit(5)->all();	// search radius is 100 km (default)

$dataProvider = new ActiveDataProvider([ 'query' => <model>::find()->nearest($here, <attributeName>) ]);

ActiveRecord 方法

getDistance()

获取在 ActiveQuery 方法 nearest() 中给定位置的距离,如果您想在 RESTful API 中显示距离,请将此作为新字段添加到您的模型中

<?php
namespace app\models;

use rezaid\geopoint\ActiveRecord;

class MyModel extends ActiveRecord
{
	
	// ...

	public function fields()
	{
		$fields = parent::fields();

		$fields['distance'] = function ($model) {
			return $model->getDistance();
		};

		return $fields;
	}

	// ...

}

示例 rest 控制器

<?php
namespace app\controllers;

use Yii;
use yii\rest\ActiveController;

class PlaceController extends ActiveController
{
	public $modelClass = 'app\models\MyModel';

	public function actionSearch()
	{
		$from = Yii::$app->request->get('from');
		$model = new $this->modelClass;
		$query = $model->find();

		if (!empty($from)) {
			$query->nearest($from, 'location', 200);
		}

		try {
			$provider = new \yii\data\ActiveDataProvider([
				'query' => $query,
			]);
		} catch (Exception $ex) {
			throw new \yii\web\HttpException(500, 'Internal server error');
		}

		if ($provider->getCount() <= 0) {
			throw new \yii\web\HttpException(404, 'No entries found');
		} else {
			return $provider;
		}
	}
}