reza-id / yii2-geopoint
支持 MySQL 空间点数据的 Yii2 ActiveRecord
Requires
- yiisoft/yii2: *
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.1、MariaDB >= 5.3.3 和 PostgreSQL >= 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;
}
}
}