我有一些使用地理空间字段的模型,如POINT
, POLYGON
或MULTIPOLYGON
。我想告诉我的模型以一种特殊的方式处理这些属性,以便我获得所需的模型属性集。
的例子:每个常规的Model::find()
或其他Eloquent方法都应该在存储或检索数据库值之前或之后应用一些自定义代码。
$area->surface
是MySQL中的POLYGON
字段,但在我的模型类中,我想将$area->surfare
作为点数组处理。
因此,在SELECT
上,我想1)使用原始表达式获取值以获得值的文本表示形式,以及2)通过一些自定义PHP代码将WKT字符串转换为数组。
在INSERT/UPDATE
上,我想取属性值(一个数组),1)将其转换为WKT字符串,然后2)使用存储该值的DB原始语句将其写入数据库。
我想在字段基础上设置它,而不是作为每个字段的特殊get/set函数,也不是在控制器中-因为我有许多地理字段。
是否有一种方法来实现这在Laravel?
(同样问题的一个更抽象的版本,是我如何创建代码来操作实际的SQL查询的属性值,而不仅仅是一些基于值的操作通过mutator &;访问器)
更新:深入研究Laravel文档和API,我发现也许Eloquent::newQuery()
方法是我需要操纵的?无论SELECT
, INSERT
还是UPDATE
,都将用于任何查询吗?
我们现在通过以下功能扩展我们的基本模型,解决了所有模型的一般问题:
- 我们定义了一个保存几何数据的属性数组。
- 我们决定每个模型的基础上,如果我们想要自动加载的文本。
- 我们改变默认的查询生成器,从数据库中选择几何属性作为文本。
这是我们现在使用的基本模型的摘录:
/**
* The attributes that hold geometrical data.
*
* @var array
*/
protected $geometry = array();
/**
* Select geometrical attributes as text from database.
*
* @var bool
*/
protected $geometryAsText = false;
/**
* Get a new query builder for the model's table.
* Manipulate in case we need to convert geometrical fields to text.
*
* @param bool $excludeDeleted
* @return 'Illuminate'Database'Eloquent'Builder
*/
public function newQuery($excludeDeleted = true)
{
if (!empty($this->geometry) && $this->geometryAsText === true)
{
$raw = '';
foreach ($this->geometry as $column)
{
$raw .= 'AsText(`' . $this->table . '`.`' . $column . '`) as `' . $column . '`, ';
}
$raw = substr($raw, 0, -2);
return parent::newQuery($excludeDeleted)->addSelect('*', DB::raw($raw));
}
return parent::newQuery($excludeDeleted);
}
您可以使用非常酷的包为点git包
Instalation
composer require matanyadaev/laravel-eloquent-spatial
例子:
<创建迁移/strong>
use Illuminate'Database'Migrations'Migration;
use Illuminate'Database'Schema'Blueprint;
use Illuminate'Support'Facades'Schema;
class CreatePlacesTable extends Migration
{
public function up(): void
{
Schema::create('places', static function (Blueprint $table) {
$table->id();
$table->string('name')->unique();
$table->point('location')->nullable();
$table->polygon('area')->nullable();
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('places');
}
}
运行迁移
php artisan migrate
创建位置模型
填充$fillable
和$casts
数组,并在新模型中使用HasSpatial特征:
namespace App'Models;
use Illuminate'Database'Eloquent'Model;
use MatanYadaev'EloquentSpatial'SpatialBuilder;
use MatanYadaev'EloquentSpatial'Objects'Point;
use MatanYadaev'EloquentSpatial'Objects'Polygon;
use MatanYadaev'EloquentSpatial'Traits'HasSpatial;
/**
* @property Point $location
* @property Polygon $area
* @method static SpatialBuilder query()
*/
class Place extends Model
{
use HasSpatial;
protected $fillable = [
'name',
'location',
'area',
];
protected $casts = [
'location' => Point::class,
'area' => Polygon::class,
];
}
创建对象
use App'Models'Place;
use MatanYadaev'EloquentSpatial'Objects'Polygon;
use MatanYadaev'EloquentSpatial'Objects'LineString;
use MatanYadaev'EloquentSpatial'Objects'Point;
use MatanYadaev'EloquentSpatial'Enums'Srid;
$londonEye = Place::create([
'name' => 'London Eye',
'location' => new Point(51.5032973, -0.1217424),
]);
$whiteHouse = Place::create([
'name' => 'White House',
'location' => new Point(38.8976763, -77.0365298, Srid::WGS84->value), // with SRID
]);
$vaticanCity = Place::create([
'name' => 'Vatican City',
'area' => new Polygon([
new LineString([
new Point(12.455363273620605, 41.90746728266806),
new Point(12.450309991836548, 41.906636872349075),
new Point(12.445632219314575, 41.90197359839437),
new Point(12.447413206100464, 41.90027269624499),
new Point(12.457906007766724, 41.90000118654431),
new Point(12.458517551422117, 41.90281205461268),
new Point(12.457584142684937, 41.903107507989986),
new Point(12.457734346389769, 41.905918239316286),
new Point(12.45572805404663, 41.90637337450963),
new Point(12.455363273620605, 41.90746728266806),
]),
]),
])
也有不同的有用的方法与示例
whereDistance
orderByDistance
whereDistanceSphere
orderByDistanceSphere
whereWithin
whereNotWithin
whereContains
whereNotContains
whereEquals
如果mutator和accessor不能满足您的需要,您可以使用Model Events操作这些属性。
然后,您可以在触发一些Eloquent事件时执行代码:创建、创建、更新、更新、保存、保存、删除、删除、恢复、恢复。
对于所有使用postgres数据库的人来说,laravel-postgis可以用于几何数据