php 使用DB::raw表达式的POINT/POLYGON等Laravel模型

ht4b089n  于 2023-04-10  发布在  PHP
关注(0)|答案(4)|浏览(133)

我有一些模型使用了像POINTPOLYGONMULTIPOLYGON这样的地理空间字段。我想告诉我的模型以一种特殊的方式处理这些属性,以便我获得所需的模型属性集。
示例:每个常规的Model::find()或其他Eloquent方法都应该在存储或检索数据库值之前应用一些自定义代码。
$area->surface在MySQL中是一个POLYGON字段,但在我的模型类中,我希望将$area->surfare处理为一个点数组。
因此,在SELECT上,我想1)使用原始表达式获取值以获得值的文本表示,2)通过一些自定义PHP代码将WKT字符串转换为数组。
INSERT/UPDATE上,我想获取属性值(一个数组),并1)将其转换为WKT字符串,然后2)使用存储该值的DB原始语句将其写入数据库。
我想在一个字段的基础上设置它,而不是为每个字段设置特殊的get/set函数,也不是在控制器中-因为我有很多geospatial字段。

在Laravel中有没有实现这个的方法?

  • (同一问题的一个更抽象的版本是,我如何创建代码来操作实际SQL查询的属性值,而不仅仅是通过mutator和accessors进行一些基于值的操作)*
    **更新:**深入查看Laravel Doc和API,发现可能需要操作的是Eloquent::newQuery()方法?无论SELECTINSERT还是UPDATE,都可以使用它进行查询吗?
vfh0ocws

vfh0ocws1#

我们现在已经通过使用以下函数扩展我们的基础模型来解决所有模型的一般性问题:

  • 我们定义一个属性数组来保存几何数据。
  • 我们根据每个模型来决定是否要将其作为文本自动加载。
  • 我们更改默认的查询构建器,以从数据库中选择作为文本的几何属性。

下面是我们现在使用的基本模型的摘录:

/**
 * 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);
}
kpbwa7wx

kpbwa7wx2#

如果mutator和accessor不符合您的需要,您可以使用ModelEvents操作这些属性。
然后,您可以在触发某些Eloquent事件时执行代码:创建、已创建、更新、已更新、保存、已保存、删除、已删除、恢复、已恢复。

vfh0ocws

vfh0ocws3#

您可以使用非常酷的包为点git package
安装

composer require matanyadaev/laravel-eloquent-spatial

示例:

创建迁移

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 trait:

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),
        ]),
    ]),
])

此外,软件包具有不同的有用methods with examples

whereDistance
orderByDistance
whereDistanceSphere
orderByDistanceSphere
whereWithin
whereNotWithin
whereContains
whereNotContains
whereEquals
yyhrrdl8

yyhrrdl84#

对于所有使用postgres数据库的人,laravel-postgis可以用于几何数据

相关问题