当前位置: 首页 > 软件库 > 开发工具 > PHP开发工具 >

laravel-mysql-spatial

授权协议 View license
开发语言 PHP
所属分类 开发工具、 PHP开发工具
软件类型 开源软件
地区 不详
投 递 者 胡景澄
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

Laravel MySQL Spatial extension

Build StatusCode ClimateCode Climate PackagistPackagist StyleCIlicense

Laravel package to easily work with MySQL Spatial Data Types and MySQL Spatial Functions.

Please check the documentation for your MySQL version. MySQL's Extension for Spatial Data was added in MySQL 5.5 but many Spatial Functions were changed in 5.6 and 5.7.

Versions

  • 1.x.x: MySQL 5.6 (also supports MySQL 5.5 but not all spatial analysis functions)
  • 2.x.x: MySQL 5.7 and 8.0 (Laravel version < 8.0)
  • 3.x.x: MySQL 8.0 with SRID support (Laravel version < 8.0)
  • 4.x.x: MySQL 8.0 with SRID support (Laravel 8+) [Current branch]
  • 5.x.x: MySQL 5.7 and 8.0 (Laravel 8+)

This package also works with MariaDB. Please refer to the MySQL/MariaDB Spatial Support Matrix for compatibility.

Installation

Add the package using composer:

$ composer require grimzy/laravel-mysql-spatial:^4.0

# or for Laravel version < 8.0
$ composer require grimzy/laravel-mysql-spatial:^3.0

For MySQL 5.7:

$ composer require grimzy/laravel-mysql-spatial:^2.0

For MySQL 5.6 and 5.5:

$ composer require grimzy/laravel-mysql-spatial:^1.0

For Laravel versions before 5.5 or if not using auto-discovery, register the service provider in config/app.php:

'providers' => [
  /*
   * Package Service Providers...
   */
  Grimzy\LaravelMysqlSpatial\SpatialServiceProvider::class,
],

Quickstart

Create a migration

From the command line:

php artisan make:migration create_places_table

Then edit the migration you just created by adding at least one spatial data field. For Laravel versions prior to 5.5, you can use the Blueprint provided by this package (Grimzy\LaravelMysqlSpatial\Schema\Blueprint):

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;

// For Laravel < 5.5
// use Grimzy\LaravelMysqlSpatial\Schema\Blueprint;

class CreatePlacesTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('places', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('name')->unique();
            // Add a Point spatial data field named location
            $table->point('location')->nullable();
            // Add a Polygon spatial data field named area
            $table->polygon('area')->nullable();
            $table->timestamps();
        });
  
        // Or create the spatial fields with an SRID (e.g. 4326 WGS84 spheroid)
  
        // Schema::create('places', function(Blueprint $table)
        // {
        //     $table->increments('id');
        //     $table->string('name')->unique();
        //     // Add a Point spatial data field named location with SRID 4326
        //     $table->point('location', 4326)->nullable();
        //     // Add a Polygon spatial data field named area with SRID 4326
        //     $table->polygon('area', 4326)->nullable();
        //     $table->timestamps();
        // });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('places');
    }
}

Run the migration:

php artisan migrate

Create a model

From the command line:

php artisan make:model Place

Then edit the model you just created. It must use the SpatialTrait and define an array called $spatialFields with the name of the MySQL Spatial Data field(s) created in the migration:

namespace App;

use Illuminate\Database\Eloquent\Model;
use Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait;

/**
 * @property \Grimzy\LaravelMysqlSpatial\Types\Point   $location
 * @property \Grimzy\LaravelMysqlSpatial\Types\Polygon $area
 */
class Place extends Model
{
    use SpatialTrait;

    protected $fillable = [
        'name'
    ];

    protected $spatialFields = [
        'location',
        'area'
    ];
}

Saving a model

use Grimzy\LaravelMysqlSpatial\Types\Point;
use Grimzy\LaravelMysqlSpatial\Types\Polygon;
use Grimzy\LaravelMysqlSpatial\Types\LineString;

$place1 = new Place();
$place1->name = 'Empire State Building';

// saving a point
$place1->location = new Point(40.7484404, -73.9878441);	// (lat, lng)
$place1->save();

// saving a polygon
$place1->area = new Polygon([new LineString([
    new Point(40.74894149554006, -73.98615270853043),
    new Point(40.74848633046773, -73.98648262023926),
    new Point(40.747925497790725, -73.9851602911949),
    new Point(40.74837050671544, -73.98482501506805),
    new Point(40.74894149554006, -73.98615270853043)
])]);
$place1->save();

Or if your database fields were created with a specific SRID:

use Grimzy\LaravelMysqlSpatial\Types\Point;
use Grimzy\LaravelMysqlSpatial\Types\Polygon;
use Grimzy\LaravelMysqlSpatial\Types\LineString;

$place1 = new Place();
$place1->name = 'Empire State Building';

// saving a point with SRID 4326 (WGS84 spheroid)
$place1->location = new Point(40.7484404, -73.9878441, 4326);	// (lat, lng, srid)
$place1->save();

// saving a polygon with SRID 4326 (WGS84 spheroid)
$place1->area = new Polygon([new LineString([
    new Point(40.74894149554006, -73.98615270853043),
    new Point(40.74848633046773, -73.98648262023926),
    new Point(40.747925497790725, -73.9851602911949),
    new Point(40.74837050671544, -73.98482501506805),
    new Point(40.74894149554006, -73.98615270853043)
])], 4326);
$place1->save();

Note: When saving collection Geometries (LineString, Polygon, MultiPoint, MultiLineString, and GeometryCollection), only the top-most geometry should have an SRID set in the constructor.

In the example above, when creating a new Polygon(), we only set the SRID on the Polygon and use the default for the LineString and the Point objects.

Retrieving a model

$place2 = Place::first();
$lat = $place2->location->getLat();	// 40.7484404
$lng = $place2->location->getLng();	// -73.9878441

Geometry classes

Available Geometry classes

Grimzy\LaravelMysqlSpatial\Types OpenGIS Class
Point($lat, $lng, $srid = 0) Point
MultiPoint(Point[], $srid = 0) MultiPoint
LineString(Point[], $srid = 0) LineString
MultiLineString(LineString[], $srid = 0) MultiLineString
Polygon(LineString[], $srid = 0) (exterior and interior boundaries) Polygon
MultiPolygon(Polygon[], $srid = 0) MultiPolygon
GeometryCollection(Geometry[], $srid = 0) GeometryCollection

Check out the Class diagram.

Using Geometry classes

In order for your Eloquent Model to handle the Geometry classes, it must use the Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait trait and define a protected property $spatialFields as an array of MySQL Spatial Data Type column names (example in Quickstart).

IteratorAggregate and ArrayAccess

The collection Geometries (LineString, Polygon, MultiPoint, MultiLineString, and GeometryCollection) implement IteratorAggregate and ArrayAccess; making it easy to perform Iterator and Array operations. For example:

$polygon = $multipolygon[10];	// ArrayAccess

// IteratorAggregate
for($polygon as $i => $linestring) {
  echo (string) $linestring;
}

Helpers

From/To Well Known Text (WKT)
// fromWKT($wkt, $srid = 0)
$point = Point::fromWKT('POINT(2 1)');
$point->toWKT();	// POINT(2 1)

$polygon = Polygon::fromWKT('POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))');
$polygon->toWKT();	// POLYGON((0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1))
From/To String
// fromString($wkt, $srid = 0)
$point = new Point(1, 2);	// lat, lng
(string)$point			// lng, lat: 2 1

$polygon = Polygon::fromString('(0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)');
(string)$polygon;	// (0 0,4 0,4 4,0 4,0 0),(1 1, 2 1, 2 2, 1 2,1 1)
From/To JSON (GeoJSON)

The Geometry classes implement JsonSerializable and Illuminate\Contracts\Support\Jsonable to help serialize into GeoJSON:

$point = new Point(40.7484404, -73.9878441);

json_encode($point); // or $point->toJson();

// {
//   "type": "Feature",
//   "properties": {},
//   "geometry": {
//     "type": "Point",
//     "coordinates": [
//       -73.9878441,
//       40.7484404
//     ]
//   }
// }

To deserialize a GeoJSON string into a Geometry class, you can use Geometry::fromJson($json_string) :

$location = Geometry::fromJson('{"type":"Point","coordinates":[3.4,1.2]}');
$location instanceof Point::class;  // true
$location->getLat();  // 1.2
$location->getLng()); // 3.4

Scopes: Spatial analysis functions

Spatial analysis functions are implemented using Eloquent Local Scopes.

Available scopes:

  • distance($geometryColumn, $geometry, $distance)
  • distanceExcludingSelf($geometryColumn, $geometry, $distance)
  • distanceSphere($geometryColumn, $geometry, $distance)
  • distanceSphereExcludingSelf($geometryColumn, $geometry, $distance)
  • comparison($geometryColumn, $geometry, $relationship)
  • within($geometryColumn, $polygon)
  • crosses($geometryColumn, $geometry)
  • contains($geometryColumn, $geometry)
  • disjoint($geometryColumn, $geometry)
  • equals($geometryColumn, $geometry)
  • intersects($geometryColumn, $geometry)
  • overlaps($geometryColumn, $geometry)
  • doesTouch($geometryColumn, $geometry)
  • orderBySpatial($geometryColumn, $geometry, $orderFunction, $direction = 'asc')
  • orderByDistance($geometryColumn, $geometry, $direction = 'asc')
  • orderByDistanceSphere($geometryColumn, $geometry, $direction = 'asc')

Note that behavior and availability of MySQL spatial analysis functions differs in each MySQL version (cf. documentation).

Migrations

For Laravel versions prior to 5.5, you can use the Blueprint provided with this package: Grimzy\LaravelMysqlSpatial\Schema\Blueprint.

use Illuminate\Database\Migrations\Migration;
use Grimzy\LaravelMysqlSpatial\Schema\Blueprint;

class CreatePlacesTable extends Migration {
    // ...
}

Columns

Available MySQL Spatial Types migration blueprints:

  • $table->geometry(string $column_name, int $srid = 0)
  • $table->point(string $column_name, int $srid = 0)
  • $table->lineString(string $column_name, int $srid = 0)
  • $table->polygon(string $column_name, int $srid = 0)
  • $table->multiPoint(string $column_name, int $srid = 0)
  • $table->multiLineString(string $column_name, int $srid = 0)
  • $table->multiPolygon(string $column_name, int $srid = 0)
  • $table->geometryCollection(string $column_name, int $srid = 0)

Spatial indexes

You can add or drop spatial indexes in your migrations with the spatialIndex and dropSpatialIndex blueprints.

  • $table->spatialIndex('column_name')
  • $table->dropSpatialIndex(['column_name']) or $table->dropSpatialIndex('index_name')

Note about spatial indexes from the MySQL documentation:

For MyISAM and (as of MySQL 5.7.5) InnoDB tables, MySQL can create spatial indexes using syntax similar to that for creating regular indexes, but using the SPATIAL keyword. Columns in spatial indexes must be declared NOT NULL.

Also please read this important note regarding Index Lengths in the Laravel 5.6 documentation.

For example, as a follow up to the Quickstart; from the command line, generate a new migration:

php artisan make:migration update_places_table

Then edit the migration file that you just created:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class UpdatePlacesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        // MySQL < 5.7.5: table has to be MyISAM
        // \DB::statement('ALTER TABLE places ENGINE = MyISAM');

        Schema::table('places', function (Blueprint $table) {
            // Make sure point is not nullable
            $table->point('location')->change();
          
            // Add a spatial index on the location field
            $table->spatialIndex('location');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('places', function (Blueprint $table) {
            $table->dropSpatialIndex(['location']); // either an array of column names or the index name
        });

        // \DB::statement('ALTER TABLE places ENGINE = InnoDB');

        Schema::table('places', function (Blueprint $table) {
            $table->point('location')->nullable()->change();
        });
    }
}

Tests

$ composer test
# or 
$ composer test:unit
$ composer test:integration

Integration tests require a running MySQL database. If you have Docker installed, you can start easily start one:

$ make start_db		# starts MySQL 8.0
# or
$ make start_db V=5.7	# starts MySQL 5.7

Contributing

Recommendations and pull request are most welcome! Pull requests with tests are the best! There are still a lot of MySQL spatial functions to implement or creative ways to use spatial functions.

Credits

Originally inspired from njbarrett's Laravel postgis package.

  • 在操作数据库中,实现一个功能时有时候会多次操作数据库,在多次操作数据库时,就会有可能出现其中一条sql语句执行成功,而另一条sql语句执行失败。这样的话就会出现很严重的问题,所以可以用MySQL的实物处理来解决这个问题。 laravel中的事物: 假如说:有一个用户表(user) 里面有两个字段,username,password password字段设置为char(32),固定长度。 现在想要一

  • 项目中主要2个时区设置: app  time_zone 处理app内时间相关函数处理 db time_zone 处理写入数据库的时间字符串的时区处理(带时区功能的字段类型如timestamp) laravel中,使用含时间字段的model,写入的sql填充时间字段的值为'2021-06-28 21:40:19' ,跟app time_zone; 写入数据库的时候根据session的timezone

  • laravel-Schema-2020-2-14 门面: use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; 1、数据库 连接和存储引擎 连接不是默认数据库连接,使用connection 连接 S

  • 直接上代码,有需要可以做参考 public function getOldUserQipuYearPage($map,$field,$map1,$field1,$year,$perpage=7) { if(!$year){ $year = date('Y'); } $sql1 = DB::connection('mysqlutf8') ->t

  • 一:作用与目的 1:消除读写的冲突,提高性能 2:提升数据库的并发负载能力 官方说明: 有时候你可能会希望使用一个数据库连接来执行 SELECT 语句, 而 INSERT、UPDATE 和 DELETE 语句则由另一个数据库连接来执行。 在 Laravel 中,无论你是使用原生 SQL 查询、查询构造器 或是 Eloquent ORM,都能轻松实现读写分离。 配置: 一:单 读库 配置(一

  • 关于主从数据库,有两种方式。 1、自己搭建主从数据库,然后在代码层面上将请求定向到主或从。 2、使用类似阿里云的服务,一种是把主从连接都配置上,这就和普通的主从一样了。另一种就是你可以在代码里只配置一个数据库(主库)的连接,然后阿里云根据你的SQL判断将请求定向到主或从,在代码层面你看不出是主从配置,这种操作使你可以很灵活的上下从库,而代码不需要做任何改动,但是弊端就是不能从代码层面决定去主或从(

  • laravel框架,对于mysql的版本是有要求的,要求5.7及以上版本,除了修改已安装mysql的版本之外,还有另外两种方式可以实现低版本的数据库: |---> 找到对应的数据库配置文件config/database.php->mysql | 修改为: 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', | |---> 找到app目录下P

  • 数据库某个字段没有默认值 mysql error. SQLSTATE[HY000]: General error: 1364 Field 'uuid' doesn't have a default value (SQL: insert into `comments` (`markdown`, `updated_at`, `created_at`) values (Hello, 2016-11-24

  • 基于swoole的mysql连接池 基于swoole协程的mysql连接池 前言 ​ 传统的nginx+FPM模式的PHP程序而言,每次请求FPM的worker都会连接一次mysql,然后请求结束便会断开连接。对于并发小的应用来说这不会有什么问题,但是对于高并发的应用来说,频繁建立连接Connect和销毁连接Close,数据库便会成为瓶颈,相信不少人也遇到过to many connection的m

  • 标签: 增删改查 配置完数据库连接,就可以使用DB类进行查询了。 查询 $results = DB::select(‘select * from users where id = ?‘, array(1)); select方法会以数组形式返回查询结果。 插入 DB::insert(‘insert into users (id, name) values (?, ?)‘, array(1, ‘Day

  • 找到 config/database.php 'mysql' => [ 'driver' => 'mysql', //数据库的类型 'host' => env('DB_HOST', '127.0.0.1'), //数据库的位置 'port' => env('DB_PORT', '3306'), //端口号 'database' => env('DB_DATABASE', 'forge'), //数

  • 可用的字段类型 数据库结构生成器包含构建表时可以指定的各种字段类型: 命令    描述 $table->bigIncrements('id');    递增 ID(主键),相当于「UNSIGNED BIG INTEGER」 $table->bigInteger('votes');    相当于 BIGINT $table->binary('data');    相当于 BLOB $table->b

  • laravel分库说明: 1、修改配置文件.env 加上:     DB_CONNECTION=mysql     DB_HOST=127.0.0.1     DB_PORT=3306     DB_DATABASE=hoteldb     DB_DATABASE_CENTER=hotel_data_db  // 多加的一条     DB_USERNAME=root     DB_PASSWORD

  • 新建mysql视图 命名为:c_good_advantage_views select `g`.`id` AS `id`,`g`.`cas` AS `cas`,`g`.`company_id` AS `company_id`,`a`.`is_advantage` AS `is_advantage` from (`c_goods` `g` join `c_advantage_goods` `a`) 

  • 最近在浏览社区话题的时候,看到了一位同仁发表的一篇教程:Laravel 5.3 下通过 migrate 添加 “全文索引” 的方法,突然想到自己之前也研究过这一话题,所以今天就和大家分享一下我的实现思路:如何更优雅地创建fulltext索引。 我非常喜欢Laravel框架的原因之一就是它的拓展性简直太赞了,所有框架本身未实现的功能你都可以自定义实现,而且可以实现得非常优雅。 其实,要想让添加全文索

  • laravel打印sql语句 DB::connection()->enableQueryLog();#开启执行日志 $a = self::where(['investorid'=>$id])->whereBetween('inserttime',[$start,$end])->where('deposit','>',0)->orderBy('id','asc')->Paginate(20); va

  • 1.应用场景 用于与数据库的交互. 2.学习/操作 环境: Windows10 64位 专业版 laravel 5.8+   2.1 数据迁移 migrate  --- 可测试数据库是否连接正常 https://blog.csdn.net/william_n/article/details/103612764   2.2 数据填充 factory seed  https://blog.csdn.n

  • 一、使用DB门面操作 需要引入 DB类 Illuminate\Support\Facades\DB 查询数据库记录 DB::select(SQL语句); DB::select('select * from `stu` from ') //以数组形式返回结果 增加数据库记录 DB::insert(SQL语句); DB::insert("insert into `stu` (`name`,`sex`

  • 场景:数据库是阿里云数据库,只允许指定的服务器访问,但是想在本地连接数据库做调试。 1. 启动 SSH 隧道 ssh -i ./path/to/id_rsa -o ServerAliveInterval=60 -N -L 13306:阿里云数据库地址:3306 服务器账号名@服务器地址 2. 修改laravel的mysql连接 'mysql' => [ 'driver' =

  • 1.运行命令 php artisan make:model XXX -fs -mfs :其他创建文件;目录:database/ m 代表在 database/migrations 目录里面创建 表文件 f 代表在 database/factories 目录里面创建 Factory.php 文件 s 代表在 database/seeders 目录里面创建 Seeder.php 文件 2. 修改Fac

 相关资料
  • 本文向大家介绍Laravel 使用MySQL Dump播种,包括了Laravel 使用MySQL Dump播种的使用技巧和注意事项,需要的朋友参考一下 示例 遵循前面创建种子的示例。本示例使用MySQL Dump在项目数据库中播种表。必须在播种之前创建表。 $sql将成为users.sql转储的内容。转储应具有INSERT INTO语句。存储转储的位置将取决于您。在上面的示例中,它存储在项目目录中

  • 问题内容: 我已经能够使用以下原始sql获取查询结果: 但是我还不能使它雄辩地工作。 根据一些类似的答案,我曾尝试在或中执行功能,但尚未过滤每个人的操作。就目前而言: 我至少在标题 大致 正确的方向,正确的…? 如果相关,则该模型具有两个关系: 问题答案: 因此,作为参考,我像这样解决了它: 奇怪的是,其中的子句需要语音标记才能使变量正确通过sql查询(同样,“ 2”似乎不起作用,而“ 2”却可以

  • 我需要在集合中返回以分页,但我只能在数组中返回,因为查询使用自然联接。如何使用Laravel集合执行此查询: 选择男性。*从mensagens自然加入(选择id_emissor,最大(created_at)created_at从mensagensid_receptor="。$user_id"集团id_emissor)t 我用过这个代码:

  • 问题:将L4代码转换为L5。2和am接收到以下错误:SQLSTATE[42000]:语法错误或访问冲突:1305 FUNCTION cr_debug。输入模块2不存在(SQL:调用填充天数表(20,“01/29/2016”)) 更新:我不知道功能功能cr_debug。ENTER_MODULE2。我不知道那是从哪里来的。这似乎是导致这个问题的原因,因为这个函数在MySQL中不存在,我也不知道它是从哪

  • 问题内容: 有没有办法在Laravel 4迁移中生成存储的MYSQL过程? 例如,这是一个简单的过程生成查询,以字符串形式存储(通过Heredoc) 在迁移函数中运行此命令时,出现以下错误: 问题答案: 您的代码有两个主要问题 不是有效的sql语句。这只是一个MySql客户端命令。因此,请不要使用它。 顺便说一句 ,您得到的错误恰恰告诉您。 您无法使用来执行代码,因为它使用的预准备语句源代码。您可

  • 我有一个由3列组成的用户设置表(或见下图):,,。 然后我有两个函数,一个保存时区,一个保存时间格式。 当我第一次运行函数时(每个函数都是通过ajax调用独立运行的),我得到了正确的结果: 然后,当我尝试更新