Laravel package to work with geospatial data types and functions.

Last update: Jul 17, 2022

Laravel Spatial

Latest Version on Packagist Total Downloads GitHub Actions

Laravel package to work with geospatial data types and functions.

For now it supports only MySql Spatial Data Types and Functions.

Supported data types:

  • Point

Available Scopes:

  • withinDistanceTo($column, $coordinates, $distance)
  • selectDistanceTo($column, $coordinates)
  • orderByDistanceTo($column, $coordinates, 'asc')

Installation

You can install the package via composer:

composer require tarfin-labs/laravel-spatial

Usage

Generate a new model with a migration file:

php artisan make:model Address --migration

To avoid Doctrine\DBAL\Exception : Unknown database type point requested, Doctrine\DBAL\Platforms\MySQL80Platform may not support it. exception, extend the migration file from TarfinLabs\LaravelSpatial\Migrations\SpatialMigration and add a spatial column. It just adds point type to Doctrine mapped types.

use TarfinLabs\LaravelSpatial\Migrations\SpatialMigration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends SpatialMigration {
    
    public function up(): void
    {
        Schema::create('addresses', function (Blueprint $table) {
            $table->point('location');
            
            $table->spatialIndex('location');
        })
    }

}

Fill the $fillable, $casts arrays in the model:

use Illuminate\Database\Eloquent\Model;
use TarfinLabs\LaravelSpatial\Casts\LocationCast;
use TarfinLabs\LaravelSpatial\Traits\HasSpatial;

class Address extends Model {

    use HasSpatial;

    protected $fillable = [
        'id',
        'name',
        'address',
        'location',
    ];
    
    protected array $casts = [
        'location' => LocationCast::class
    ];

}

Filter addresses within 10 km of the given coordinate:

use TarfinLabs\LaravelSpatial\Types\Point;
use App\Models\Address;

Address::query()
       ->withinDistanceTo('location', new Point(lat: 25.45634, lng: 35.54331), 10000)
       ->get();

Select distance to given coordinate as meter:

use TarfinLabs\LaravelSpatial\Types\Point;
use App\Models\Address;

Address::query()
       ->selectDistanceTo('location', new Point(lat: 25.45634, lng: 35.54331))
       ->get();

Get latitude and longitude of the location:

use App\Models\Address;

$address = Address::find(1);
$address->location; // TarfinLabs\LaravelSpatial\Types\Point

$address->location->getLat();
$address->location->getLng();

Create a new address with location:

use App\Models\Address;

Address::create([
    'name'      => 'Bag End',
    'address'   => '1 Bagshot Row, Hobbiton, Shire',
    'location'  => new Point(lat: 25.45634, lng: 35.54331),
]);

Testing

composer test

Todo

  • Proper documentation.
  • Missing tests.

Changelog

Please see CHANGELOG for more information what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you discover any security related issues, please email [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

Laravel Package Boilerplate

This package was generated using the Laravel Package Boilerplate.

GitHub

https://github.com/tarfin-labs/laravel-spatial
You might also like...

Laravel basic Functions, eloquent cruds, query filters, constants

Emmanuelpcg laravel-basics Description Package with basic starter features for Laravel. Install If Builder Constants Install composer require emmanuel

Jan 1, 2022

webtrees module: enhanced clippings cart with more functions to add records to the clippings cart and to start actions on these records

webtrees module: enhanced clippings cart with more functions to add records to the clippings cart and to start actions on these records

webtrees module hh_clippings_cart_enhanced !!! This is an alpha version! Do not use it in a productive webtrees system! !!! This webtrees custom modul

Feb 16, 2022

A collection of helper functions that I use across my projects.

A collection of helper functions that I use across my projects. This package includes some of the helper functions that I tend to use in all of my pro

Jun 30, 2022

Smeify is a Stable Automated Solution for Airtime and Data businesses in Nigeria, this package helps you integrate smeify easily into your laravel application.

Smeify is a Stable Automated Solution for Airtime and Data businesses in Nigeria, this package helps you integrate smeify easily into your laravel application.

Jul 27, 2022

Save Model is a Laravel package that allows you to save data in the database in a new way.

Save Model is a Laravel package that allows you to save data in the database in a new way. No need to worry about $guarded and $fillable properties in the model anymore. Just relax an use Save Model package.

Mar 2, 2022

A laravel package to handle sanitize process of model data to create/update model records.

Laravel Model UUID A simple package to sanitize model data to create/update table records. Installation Require the package using composer: composer r

Jul 20, 2022

Laravel Grid is a package that helps you display table data.

Laravel Grid Laravel Grid is a package that helps you display table data. I could not find package that would satisfy my needs so I decided to write o

May 31, 2021

Laravel 5.* package to easily introduce a transformation layer for your data

Laraformer Laraformer is a laravel 5.* package that lets you easily introduce a transformation layer for your data. Laraformer (originated from Larave

Jan 25, 2020

Laravel package to normalize your data before saving into the database.

This package helps you normalize your data in order to save them into the database. The Goal is to having separate classes that handle the data normalization, and thus can be tested independently.

Apr 21, 2021
Comments
  • 1. 1582 Incorrect parameter count in the call to native function 'ST_SRID'

    SQLSTATE[42000]: Syntax error or access violation: 1582 Incorrect parameter count in the call to native function 'ST_SRID' (SQL: select `id`, `user_id`, `location` from `user_profiles` where `online` = 1 and `updated_at` >= 2022-02-03 15:09:51 and `location` is not null and ST_Distance( ST_SRID(location, 0), ST_SRID(Point(93.045724, -8.834381), 0) ) <= 20000)
    
    Reviewed by Saifallak at 2022-02-03 15:20
  • 2. Latitude / Longitude shouldn't be cast to float values

    This is unlikely to affect 99% of developers, but just throwing it out there as a similar issue caught me out before 🙃

    The TarfinLabs\LaravelSpatial\Types\Point class treats latitude/longitude as a float. Most PHP installations will be able to handle up to 11 decimal places (but the precision can vary in php.ini).

    However, the POINT type in MySQL supports up to 25 bytes of resolution. So if this package is used against any existing high-precision POINT values, it would lose data when saving the model back to the database.

    I think the correct approach would be to use protected string $lat; in the Point class, and construct it with __construct(string|float $lat = 0 ...) etc... The getLat(): float method would still automatically cast as a float before returning, but the toPair() method should be changed to use the original string values of the properties. This would ensure the full precision is persisted back to the database by the LocationCast class.

    Again, unlikely to affect most people — just worth mentioning for best practice 👍

    Reviewed by JackWH at 2022-07-16 18:46
  • 3. Handling spatial indexes for NULLable POINT columns

    👋 Hi there! As I was integrating this package with my application, I found out it's not possible to add a SPATIAL index on a POINT column if it supports NULL values. More info here and here.

    Because only some rows in my table have location data associated, querying is slow without a spatial index. It seems as though the suggested way around this is to set a default POINT(0 0) value on all records without location data.

    I can do this easily enough with an Eloquent model event:

    public static function booted(): void
    {
        // When a Model is being created, set its location field to a neutral Point(0 0) if not already set.
        static::creating(static function(Model $model) {
            foreach ($model->getLocationCastedAttributes() as $column) {
                if ($model->{$column} === null) {
                    $model->{$column} = new Point();
                }
            }
        });
    }
    

    This now allows for spatial indexing to be used. However, the package's scopes become a lot harder to use practically. For example, calling Address::withinDistanceTo('location', new Point(25.45634, 35.54331), 10000000)->get() could incorrectly include records with POINT(0 0) set (or whatever default is used).

    I appreciate the HasSpatial trait can be extended, and developers can override each method with an extra $query->whereRaw("ST_ASTEXT({$column}) = 'POINT(0 0)'") clause. Developers could also add their own scope method to their models, but would have to remember to call it every single time, which isn't ideal.

    So it would be fantastic if support for this could be built-in natively somehow — especially if more scopes are likely to be added as the roadmap progresses in future.

    Thanks for a really useful package! 🚀

    Reviewed by JackWH at 2022-07-16 18:07
  • 4. if location is null, getting error

    always getting this error if location col. is null

    because of $casts in the model

    explode(): Argument #2 ($string) must be of type string, null given
    exception: "TypeError",
    "/var/www/sonbla/releases/8/vendor/tarfin-labs/laravel-spatial/src/Casts/LocationCast.php"
    line: 18,
    
    Reviewed by Saifallak at 2022-03-07 12:46
Aug 13, 2022
Localization Helper - Package for convenient work with Laravel's localization features and fast language files generation
Localization Helper - Package for convenient work with Laravel's localization features and fast language files generation

Localization Helper Package for convenient work with Laravel's localization features and fast language files generation. Installation Via Composer $ c

Jul 13, 2019
A simple to use opinionated ERP package to work with Laravel

Laravel ERP A simple to use opinionated ERP package to work with Laravel Installation You can install the package via composer: composer require justs

Aug 9, 2022
This package allows you to easily work with NanoID in your Laravel models.
This package allows you to easily work with NanoID in your Laravel models.

Laravel Model UUIDs Introduction Huge thanks to Micheal Dyrynda, whose work inspired me to create this package based on laravel-model-nanoid but uses

Jul 27, 2022
This package provides new helper functions that take care of handling all the translation hassle and do it for you.

Laravel Translate Message ?? This package provides new helper functions that take care of handling all the translation hassle and do it for you. Insta

Feb 8, 2022
Postgis extensions for laravel. Aims to make it easy to work with geometries from laravel models.

Laravel Wrapper for PostgreSQL's Geo-Extension Postgis Features Work with geometry classes instead of arrays. $model->myPoint = new Point(1,2); //lat

Aug 14, 2022
laravel-wallet - Easy work with virtual wallet.
laravel-wallet - Easy work with virtual wallet.

laravel-wallet - Easy work with virtual wallet. [Documentation] [Get Started] [Документация] [Как начать] Vendor: bavix Package: laravel-wallet Versio

Aug 5, 2022
An extended laravel eloquent WHERE method to work with sql LIKE operator.

Laravel Eloquent WhereLike An extended laravel eloquent WHERE method to work with sql LIKE operator. Inspiration The idea of this package comes from o

Aug 6, 2022
Deploy and execute non-PHP AWS Lambda functions from your Laravel application.

Sidecar for Laravel Deploy and execute non-PHP AWS Lambda functions from your Laravel application. Read the full docs at hammerstone.dev/sidecar/docs.

Aug 8, 2022
Collection of agnostic PHP Functions and helpers with zero dependencies to use as foundation in packages and other project

Collection of agnostic PHP Functions and helpers This package provides a lot of very usefull agnostic helpers to use as foundation in packages and oth

Feb 12, 2022