GithubHelp home page GithubHelp logo

laravel-eloquent-spatial's People

Contributors

d0m4te avatar devinfd avatar dzhwar-k avatar eschricker avatar gdebrauwer avatar jobverplanke avatar ju-gow avatar lukevi avatar matanyadaev avatar riley19280 avatar synchro avatar trin4ik avatar yinx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

laravel-eloquent-spatial's Issues

Package no longer provides a service provider

The composer.json of this package still tries to auto-discover a service provider, but there isn't one.

Proposed solution: remove the auto-discovery line from the composer.json:

"providers": [
"MatanYadaev\\LaravelEloquentSpatial\\LaravelEloquentSpatialServiceProvider"
],
"aliases": {
"LaravelEloquentSpatial": "MatanYadaev\\LaravelEloquentSpatial\\LaravelEloquentSpatialFacade"
}

New version current master

It would be great if you could create a new release (v1.0.4) from the current master that includes the changes related to phpstan

Updating location data using update/updateOrCreate doesnt work

Hey there,

so i am currently working on a Project that needs Points for a Location and we are sending over the Data as an array.
Right now i am trying to get a helper function to work, but it seems it only works with create() and everything else like update(), updateOrCreate(), doesnt seem to work at all.

    /**
     * Create or update event location
     * Converts latitude/longitude to SpatialPoint.
     */
    public function setLocation(array $data): void
    {
        $location = Arr::map($data, function ($value, $key) {
            if (str_contains($key, 'coordinates')) {
                $value = new Point($value['latitude'], $value['longitude']);
            }

            return $value;
        });

        $this->location()->updateOrCreate($location);
    }

Error that i am getting back is (note this is from postman):
"Object of class MatanYadaev\\EloquentSpatial\\Objects\\Point could not be converted to string"

For the setup
location is just casting two attributes (exact_coordinates and fuzzy_coordinates, which are always given from the post request) into a Point::class.

Edit: Using laravel-eloquent-spatial 2.0

Support strings for spatial types creation

Hi, I just started using your package yesterday, so i may not understand something (do not blame me to hard =D).

I found that creating a new instance of MatanYadaev\EloquentSpatial\Objects\Point (or other spatial abstractions as well) is a bit of a mess (if your project big enough and you have a ton of spatial data manipulations).

Wouldn't it be nice to have string values support for creating models with spatial data types?

For example this code from your readme:

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

Could be rewritten as such:

$vaticanCity = Place::create([
    'name' => 'Vatican City',
    'area' => new Polygon([
        new LineString([
              '12.455363273620605,41.90746728266806',
              '12.450309991836548,41.906636872349075',
              '12.445632219314575,41.90197359839437',
              '12.447413206100464,41.90027269624499',
              '12.457906007766724,41.90000118654431',
              '12.458517551422117,41.90281205461268',
              '12.457584142684937,41.903107507989986',
              '12.457734346389769,41.905918239316286',
              '12.45572805404663,41.90637337450963',
              '12.455363273620605,41.90746728266806',
        ]),
    ]),
])

Is it possible and what do you think about that?

Support Laravel 9

Currently the library just supports Laravel 8. Will it be updated to support Laravel 9?

Numeric value out of range: 1416 Cannot get geometry object from data you send to the GEOMETRY field

I'm getting a casting problem when running this update:

I have a Point value set from request properties like this:

$return_location = new Point((float)$request->latitude, (float)$request->longitude);

This is then used to update DB records:

            $count = Checkout::query()
                ->where('user_id', $user->id)
                ->limit(1)
                ->update(
                    [
                        'return_location'   => $return_location,
                    ]
                );

but even though the Point object is valid, and has a cast set correctly in its model, it fails like this:

SQLSTATE[22003]: Numeric value out of range: 1416 Cannot get geometry object from data you send to the GEOMETRY
field (SQL: update `checkouts` set `return_location` = POINT(-0.118092 51.509865), `checkouts`.`updated_at` = 
2022-12-06 11:03:38 where `user_id` = 4 limit 1)

In other contexts this field works fine.

Is there some limitation I'm running into here, or a bug?

Query methods don't accept fully-qualified column names

I have a table called locations containing a Point column called location, and if I query it like this:

$point = new Point($lat, $long);
$within = 500;

$locations
    ->whereDistance('locations.location', $point, '<=', $within)
    ->orderByDistance('locations.location', $point);

It fails with this error:

Column not found: 1054 Unknown column 'locations.location' in 'where clause' (SQL: select `locations`.* from `locations` where ST_DISTANCE(`locations.location`...

If I change it to ->whereDistance('location', $point, '<=', $within) (and similarly for the same parameter in the orderByDistance call), dropping the table name, the query works. If I dump it, I can see that it renders to this SQL:

...where ST_DISTANCE(`location`, ST_GeomFromText(...

However, this would cause ambiguity problems if I had a column with the same name in a different table in the same query.

Is this a bug/limitation in MySQL or in this package?

Polygon To WKT Not Returning Valid WKT

So we seem to have suddenly developed a problem where converting a polygon to WKT gives not valid WKT and it's only recently started happening.

$polygon = 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),
                ])
            ]
        );
    dd($polygon->toWkt());

This returns:

POLYGON(LINESTRING(POINT(41.907467282668, 12.455363273621),POINT(41.906636872349, 12.450309991837),POINT(41.901973598394, 12.445632219315),POINT(41.900272696245, 12.4474132061),POINT(41.900001186544, 12.457906007767),POINT(41.902812054613, 12.458517551422),POINT(41.90310750799, 12.457584142685),POINT(41.905918239316, 12.45773434639),POINT(41.90637337
451, 12.455728054047),POINT(41.907467282668, 12.455363273621)))

Which is not valid, it should return POLYGON() which this package has been doing previously.

Any ideas on how to resolve would be great!

Moving from grimzy / laravel-mysql-spatial on laravel 8

Hi,

Apologies if this doesn't belong in issues. I am trying to move to this library with this composer command:

composer require matanyadaev/laravel-eloquent-spatial "^2.0"

But I get the following error:


composer/package-versions-deprecated: Generating version class...
composer/package-versions-deprecated: ...done generating version class
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
PHP Fatal error:  Declaration of MatanYadaev\EloquentSpatial\EloquentSpatialServiceProvider::registerDoctrineTypes(Illuminate\Database\Connection $connection): void must be compatible with Illuminate\Database\DatabaseServiceProvider::registerDoctrineTypes() in /Users/kunal/code/opensports/vendor/matanyadaev/laravel-eloquent-spatial/src/EloquentSpatialServiceProvider.php on line 30

In EloquentSpatialServiceProvider.php line 30:
                                                                                                                                                                         
  Declaration of MatanYadaev\EloquentSpatial\EloquentSpatialServiceProvider::registerDoctrineTypes(Illuminate\Database\Connection $connection): void must be compatible  
   with Illuminate\Database\DatabaseServiceProvider::registerDoctrineTypes()                                                                                             
                                                                                                                                                                         

Script @php artisan package:discover --ansi handling the post-autoload-dump event returned with error code 255

Installation failed, reverting ./composer.json and ./composer.lock to their original content.

Any ideas on how to resolve this? Do I need to remove the grimzy / laravel-mysql-spatial library first and what is the best way to do this in composer?

Thanks heaps.

ST_GeomFromText failure on MySQL 5.7

According to the mysql reference, ST_GeomFromText does not accept a 3rd parameter on v5.7. On version 2.2 of the laravel-eloquent-spatial library, the axis-order parameter was introduced as a 3rd parameter, breaking code that runs on installations of MySQL 5.7.

Illuminate\Database\QueryException: SQLSTATE[42000]: Syntax error or access violation: 1582 Incorrect parameter count in the call to native function 'ST_GeomFromText' (SQL: insert into tablename (geometry) values ( ST_GeomFromText('POLYGON((-122.48961925507 37.768781090011, -122.48773097992 37.768781090011, -122.48773097992 37.769764882401, -122.48961925507 37.769764882401, -122.48961925507 37.768781090011))', 0, 'axis-order=long-lat'))) in file /vendor/laravel/framework/src/Illuminate/Database/Connection.php on line 759

Geometry classes are not extensible

I want to change display results of coordinates, but for me returned by Geometry class array is completely useless.
I want to return:

[
"latitude": 18.612053,
"longitude": 53.010963
]

How to do that?
I've try to extend Geometry class and add to casts, but i doesn't work.

Nullable geospatial fields, default values

In your code example you use this in the migration:

$table->point('location')->nullable();

However, if you try to do that and want to search on this field (i.e. it has a spatial index), this will cause an error:

All parts of a SPATIAL index must be NOT NULL

So spatial fields cannot be null at all, which means they must also be initialised to non-null values in a constructor, as that can't be done in the attributes array, and can't handled by a cast.

But then I run into another issue. If my Location model has:

public function newEloquentBuilder($query): SpatialBuilder
{
    return new SpatialBuilder($query);
}

protected $casts = [
    'location' => \MatanYadaev\EloquentSpatial\Objects\Point::class,
];

public function __construct()
{
    $this->location = new \MatanYadaev\EloquentSpatial\Objects\Point(51.5032973, -0.1195537);
}

and I do this:

    $location = new Location();
    $location->save();

it fails with:

TypeError: MatanYadaev\EloquentSpatial\Objects\Geometry::fromWkb(): Argument #1 ($wkb) must be of type string, Illuminate\Database\Query\Expression given, called in vendor/matanyadaev/laravel-eloquent-spatial/src/GeometryCast.php on line 39

How should this be done?

Compatibility Issue with SQLiteConnection when using PHPUnit

Issue Description

When using with PHPUnit and the SQLiteConnection driver, I encountered a compatibility issue with the AxisOrder class. The issue arises due to the differences in SQL syntax between SQLite and other database systems.

Steps to Reproduce

  • Set up a Laravel project with the MatanYadaev/laravel-eloquent-spatial library.
  • Configure the database connection to use the SQLiteConnection driver.
  • Write test cases using PHPUnit that involve spatial data and the AxisOrder class.

Expected Behavior

I expected the test cases to run successfully and pass, regardless of the database driver used.

Actual Behavior

When running the test cases with the SQLiteConnection driver, I encountered errors related to the AxisOrder class. It seems that the SQL syntax used by the library is not compatible with SQLite, resulting in failed queries and test failures.

Reproducible Example

Here is a simplified example of a failing test case:

use PHPUnit\Framework\TestCase;
use MatanYadaev\EloquentSpatial\Types\Point;
use App\Models\Location;

class SpatialTest extends TestCase
{
    public function testSpatialQuery()
    {
        $location = new Location();
        $location->point = new Point(1, 2);
        $location->save();

        // Perform some spatial queries or assertions
        // ...

        $this->assertTrue(true);
    }
}

Environment

Laravel version: ^10
Laravel Eloquent Spatial version:^2.10
PHPUnit version: ^10.0
Database driver: SQLite

Possible Solution

Possible fix in Axis class:

To address the compatibility issue between MatanYadaev/laravel-eloquent-spatial and SQLiteConnection, you can modify the Axis class as follows:

public static function fromWKT($wkt)
{
    // ...

    // Add conditional check for SQLiteConnection
    if (app('db')->connection() instanceof \Illuminate\Database\SQLiteConnection) {
        // Handle SQLite-specific behavior here
        // For example, convert the WKT to a different format or implement a workaround
        // based on the limitations of SQLite's spatial support.
        // ...
    }
    
    // ...

    return $axis;
}
  • Inside the conditional block, you can implement specific logic or workarounds to handle the limitations of spatial support in SQLite. This could involve converting the WKT format or utilizing SQLite-specific functions.

  • Save the changes to the Axis.php file.

  • Test your application to verify that the compatibility issue has been resolved .

Additional Information

I have tested the same code with other database drivers (e.g., MySQL) and did not encounter any issues.
I have checked the documentation and GitHub repository of the MatanYadaev/laravel-eloquent-spatial library but did not find any specific information regarding SQLite compatibility.

Make third wkt-parametr (axis-order=long-lat) optional for MariaDB compatibility

Unlike MySQL, the WKT-input spatial analysis functions in MariaDB (like ST_GeomFromText and ST_DISTANCE) do not take an options parameter: https://mariadb.com/kb/en/st_geomfromtext/

For this reason, we should get an SQL error, while saving the model with spatial fields:
SQLSTATE[42000]: Syntax error or access violation: 1582 Incorrect parameter count in the call to native function 'ST_GeomFromText'

A similar issue was in grimzy/laravel-mysql-spatial and it was fixed by pull request grimzy/laravel-mysql-spatial#152

Add Arrange-Act-Assert comments inside tests

The AAA (Arrange, Act Assert) pattern's purpose is to organize your test in a way that is easier to read and understand. You can read about it here: https://github.com/goldbergyoni/javascript-testing-best-practices#-%EF%B8%8F-12-structure-tests-by-the-aaa-pattern

In this repo, all of the tests are following this pattern. But it's not perfect, because no comments are separating the test into these 3 sections.

This task is about adding these comments.

Example:

// โŒ Before
it('calculates sum', function (): void {
  $firstNumber = 1;
  $secondNumber = 2;

  $result = sum($firstNumber, $secondNumber);

  expect($result)->toBe(3);
});

// โœ… After
it('calculates sum', function (): void {
  // Arrange
  $firstNumber = 1;
  $secondNumber = 2;

  // Act
  $result = sum($firstNumber, $secondNumber);

  // Assert
  expect($result)->toBe(3);
});

Real example:

it('calculates geometry centroid', function (): void {
// Arrange
$polygon = Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[1,-1],[1,1],[-1,1],[-1,-1]]]}');
TestPlace::factory()->create(['polygon' => $polygon]);
// Act
/** @var TestPlace $testPlace */
$testPlace = TestPlace::query()
->withCentroid('polygon')
->withCasts(['centroid' => Point::class])
->firstOrFail();
// Assert
$expectedCentroid = new Point(0, 0);
expect($testPlace->centroid)->toEqual($expectedCentroid);
});

Improve pipeline

  1. Test MySQL 8 & 5.7 & MariaDB
  2. php-cs-fixer should lint - not fix
  3. Consider using PHPStan instead of PSalm.

Support for MySQL 8 SRID?

I have been using https://github.com/grimzy/laravel-mysql-spatial/ which has support for SRIDs. I am planning to migrate to this package as it has greater potential with Laravel's current ecosystem.

But looking at the source code, I don't see any support for SRID which will conflict with my current database schema. Is there any plan or are you interested in a PR?

Unable to JSON encode payload. Error code: 5

Thank you for your work on this package! I've been fighting an issue for the past week that I can't find a resolution to. I don't know if this is an issue with this package or Laravel but I thought that I would start here.

I have a queued job that has an object (not a model) as constructor argument. The object has property that is a model with a coordinates (Point) attribute.

something like:

class Report
{
  $account = null;
  public function __construct(Model $account) {
    $this->account = $account
  }
}

$account = Account::first();
MakeReport::dispatch(new Report($account));

The coordinates attribute is properly casted on the Account model

protected $casts = [
    'coordinates' => Point::class
];

The problem is that the coordinates are not being serialized by laravel and I get the error:
Illuminate\โ€‰Queue\โ€‰InvalidPayloadException Unable to JSON encode payload. Error code: 5

Any ideas? I'm starting to lose my mind on this.

PHP 8.1.10
Laravel 9.28.0

Laravel 10 support

Laravel 10 was just released. The package apparently supports it without major issues, but the composer.json needs to be updated.

new Point(lat,lng) always gets reversed ; ๐Ÿฅฒ

Hi , while inserting data to point i noticed my polygons gets rendered in wrong part of map ,
then i found this
' new LineString([
new Point(23.455363273620605, 45.82746723286806),
new Point(23.450309991836548, 45.826636872349075),
new Point(23.445632219314575, 45.82197359839437),
new Point(23.455363273620605, 45.82746723286806),
]); '
the above code is actually returning the next
{"type":"LineString",
"coordinates":[
[45.82746723286806,23.455363273620605],[45.82663687234908,23.450309991836548],[45.82197359839437,23.445632219314575],[45.82746723286806,23.455363273620605]]}

which is totally wrong,
i temporally fixed it by swapping lats and lngs locations , but it needs to be fixed ,

thank you for your work;;; ๐Ÿฅณ

why "geometry" type is not in `/src/Doctrine/` ?

I want to use "geometry" type like $table->geometry('location'), but this is not supported because Geometry type declaration for doctrine/dbal is not in /src/Doctrine. How can I use "geometry" type?

Point column is always "dirty" after creating a record

Hi, thank you for your work on this package.

I've tested it with Laravel 10.39.0 and 10.46.0 with your package version 3.2.2 and 4.1.0.

If you are creating a new record or a factory record the column, which includes the point, is always dirty.

Here is an example:

<?php

// Model

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use MatanYadaev\EloquentSpatial\Objects\Point;
use MatanYadaev\EloquentSpatial\Traits\HasSpatial;

class Estate extends Model
{
    use HasFactory;
    use HasSpatial;

    protected $fillable = [
        'name',
        'coordinates',
    ];

    protected $casts = [
        'coordinates' => Point::class,
    ];
}
<?php

// Factory

namespace Database\Factories;

use Illuminate\Database\Eloquent\Factories\Factory;
use MatanYadaev\EloquentSpatial\Objects\Point;

/**
 * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Estate>
 */
class EstateFactory extends Factory
{
    /**
     * Define the model's default state.
     *
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        return [
            'name' => fake()->word(),
            'coordinates' => new Point(51.5032973, -0.1217424),
        ];
    }
}
<?php

// Test

use App\Models\Estate;
use MatanYadaev\EloquentSpatial\Objects\Point;

test('coordinates have to be not dirty on factory create', function () {
    $estate = Estate::factory()
        ->create();

    expect($estate->isDirty('name'))->toBeFalse();

    expect($estate->isDirty('coordinates'))->toBeFalse(); // Failed
});


test('coordinates have to be not dirty on create', function () {
    $estate = Estate::create([
        'name' => 'Foo',
        'coordinates' => new Point(51.5032973, -0.1217424),
    ]);

    expect($estate->isDirty('name'))->toBeFalse();

    expect($estate->isDirty('coordinates'))->toBeFalse(); // Failed
});

I've created a demo repository: https://github.com/poldixd/laravel-eloquent-spatial-issue

You can run the test with ./vendor/bin/pest tests/Feature/LaravelEloquentSpatialTest.php

Update Readme

Hello,

At first I would like to thank you for this package. โค๏ธโค๏ธ You are a life saver.

My first impression about this package is awesome, and it satisfies all conditions (at least for me) ๐Ÿ˜‚

But I would like to know how to use Spatial functions ST_Distance_Sphere
By chance, I found the API.md file and it has a pretty well description however it does not contain more examples.

What I want to do is, instead of creating Database procedures, I want to use ST_Distance_Sphere

Here is a code sample of my project:

        // ! show providers listed with in particular distance
        $subqueryDistanceFrom = "ST_Distance_Sphere(Point(trips.longitude_from,"
            . " trips.latitude_from),"
            . " Point($request->long_from, $request->lat_from ))"
            . " as distance_from";
        $subqueryDistanceTo = "ST_Distance_Sphere(Point(trips.longitude_to,"
            . " trips.latitude_to),"
            . " Point($request->long_to, $request->lat_to))"
            . " as distance_to";

        $subqueryDistanceReturnFrom = "ST_Distance_Sphere(Point(trips.longitude_to,"
            . " trips.latitude_to),"
            . " Point($request->long_from, $request->lat_from ))"
            . " as distance_return_from";
        $subqueryDistanceReturnTo = "ST_Distance_Sphere(Point(trips.longitude_from,"
            . " trips.latitude_from),"
            . " Point($request->long_to, $request->lat_to))"
            . " as distance_return_to";


        $subqueryDistanceWhereFrom = "ST_Distance_Sphere(Point(trips.longitude_from,"
            . " trips.latitude_from),"
            . " Point($request->long_from, $request->lat_from ))"
            . " < " . $distanceDelta;

        $subqueryDistanceWhereTo = "ST_Distance_Sphere(Point(trips.longitude_to,"
            . " trips.latitude_to),"
            . " Point($request->long_to, $request->lat_to ))"
            . " < " . $distanceDelta;

        $subqueryDistanceWhereReturnFrom = "ST_Distance_Sphere(Point(trips.longitude_to,"
            . " trips.latitude_to),"
            . " Point($request->long_from, $request->lat_from ))"
            . " < " . $distanceDelta;

        $subqueryDistanceWhereReturnTo = "ST_Distance_Sphere(Point(trips.longitude_from," . " trips.latitude_from),"
            . " Point($request->long_to, $request->lat_to ))" . " < " . $distanceDelta;

I appreciate your help ๐Ÿ˜Š

Polygon SRID

Hi everyone!

We're facing some problems when storing a polygon with a srid. The problem is that is saving without the srid, so is failing when comparing with other models with srid working.

Example:

$data = "POLYGON((17.03558877746583 -22.543548588275577,17.046918428344735 -22.5888848509733,17.08279565612794 -22.577235171974756,17.122792756958017 -22.572559173452948,17.09824518005372 -22.5226191338314,17.06502870361329 -22.528803166402827,17.03558877746583 -22.543548588275577))";

$polygon = Polygon::fromWkt($data, 4326);

When polygon is stored on DB, srid is not saving.

Can you check it please?

Numeric value out of range: 1416 Cannot get geometry object from data you send to the GEOMETRY field

 public function setLocationAttribute($value) {
        $this->attributes['location'] = new Point($value['lng'], $value['lat']);
    }

When I try to update my location column trough setAttribute method I get the following error:
Numeric value out of range: 1416 Cannot get geometry object from data you send to the GEOMETRY field

If I update the column with raw sql query everything works fine.

Using Laravel 10.10 & mysql 8.0

Doctrine types are not defined

Getting the below error, when querying the table details from the Doctrine Schema Manager, can you assist?

    public static function getTable($tableName)
    {
        $sm = Schema::getConnection()->getDoctrineSchemaManager();
        $doctrineTable = $sm->listTableDetails($tableName);
        return $doctrineTable;
    }

for the following table:

    CREATE TABLE 'geo_areas' (
      'id' int unsigned NOT NULL AUTO_INCREMENT,
      'account_id' int unsigned NOT NULL,
      'geo_area_name' varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
      'geo_area_region' varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
      'geo_area_location' point DEFAULT NULL,
      'geo_area_area' polygon DEFAULT NULL,
      'created_at' timestamp NULL DEFAULT NULL,
      'updated_at' timestamp NULL DEFAULT NULL,
      PRIMARY KEY ('id'),
      UNIQUE KEY 'geo_areas_geo_area_name_unique' ('geo_area_name'),
      KEY 'geo_areas_account_id_foreign' ('account_id'),
      CONSTRAINT 'geo_areas_account_id_foreign' FOREIGN KEY ('account_id') REFERENCES 'accounts' ('id') ON DELETE CASCADE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

Error below:

    {
        "message": "Unknown database type point requested, Doctrine\\DBAL\\Platforms\\MySQL80Platform may not support it.",
        "exception": "Doctrine\\DBAL\\Exception",
        "file": "/MySite/vendor/doctrine/dbal/src/Platforms/AbstractPlatform.php",
        "line": 418,
        "trace": [
            {
                "file": "/MySite/vendor/doctrine/dbal/src/Schema/MySQLSchemaManager.php",
                "line": 176,
                "function": "getDoctrineTypeMapping",
                "class": "Doctrine\\DBAL\\Platforms\\AbstractPlatform",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/doctrine/dbal/src/Schema/AbstractSchemaManager.php",
                "line": 1347,
                "function": "_getPortableTableColumnDefinition",
                "class": "Doctrine\\DBAL\\Schema\\MySQLSchemaManager",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/doctrine/dbal/src/Schema/AbstractSchemaManager.php",
                "line": 256,
                "function": "_getPortableTableColumnList",
                "class": "Doctrine\\DBAL\\Schema\\AbstractSchemaManager",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/doctrine/dbal/src/Schema/MySQLSchemaManager.php",
                "line": 81,
                "function": "doListTableColumns",
                "class": "Doctrine\\DBAL\\Schema\\AbstractSchemaManager",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/doctrine/dbal/src/Schema/AbstractSchemaManager.php",
                "line": 476,
                "function": "listTableColumns",
                "class": "Doctrine\\DBAL\\Schema\\MySQLSchemaManager",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/doctrine/dbal/src/Schema/MySQLSchemaManager.php",
                "line": 73,
                "function": "doListTableDetails",
                "class": "Doctrine\\DBAL\\Schema\\AbstractSchemaManager",
                "type": "->"
            },
            {
                "file": "/MySite/app/Common/Helpers.php",
                "line": 74,
                "function": "listTableDetails",
                "class": "Doctrine\\DBAL\\Schema\\MySQLSchemaManager",
                "type": "->"
            },
            {
                "file": "/MySite/app/Http/Controllers/Controller.php",
                "line": 82,
                "function": "createIndex",
                "class": "App\\Common\\Helpers",
                "type": "::"
            },
            {
                "file": "/MySite/app/Http/Controllers/Admin/JobController.php",
                "line": 1023,
                "function": "MakePaginatedResult",
                "class": "App\\Http\\Controllers\\Controller",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Routing/Controller.php",
                "line": 54,
                "function": "showAllJobsBetweenDatesForAccount",
                "class": "App\\Http\\Controllers\\Admin\\JobController",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php",
                "line": 43,
                "function": "callAction",
                "class": "Illuminate\\Routing\\Controller",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Routing/Route.php",
                "line": 259,
                "function": "dispatch",
                "class": "Illuminate\\Routing\\ControllerDispatcher",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Routing/Route.php",
                "line": 204,
                "function": "runController",
                "class": "Illuminate\\Routing\\Route",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
                "line": 725,
                "function": "run",
                "class": "Illuminate\\Routing\\Route",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 141,
                "function": "Illuminate\\Routing\\{closure}",
                "class": "Illuminate\\Routing\\Router",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/passport/src/Http/Middleware/CheckForAnyScope.php",
                "line": 28,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "Laravel\\Passport\\Http\\Middleware\\CheckForAnyScope",
                "type": "->"
            },
            {
                "file": "/MySite/app/Http/Middleware/IsClientCredential.php",
                "line": 40,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "App\\Http\\Middleware\\IsClientCredential",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php",
                "line": 50,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "Illuminate\\Routing\\Middleware\\SubstituteBindings",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php",
                "line": 126,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php",
                "line": 62,
                "function": "handleRequest",
                "class": "Illuminate\\Routing\\Middleware\\ThrottleRequests",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "Illuminate\\Routing\\Middleware\\ThrottleRequests",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php",
                "line": 44,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "Illuminate\\Auth\\Middleware\\Authenticate",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 116,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
                "line": 726,
                "function": "then",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
                "line": 703,
                "function": "runRouteWithinStack",
                "class": "Illuminate\\Routing\\Router",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
                "line": 667,
                "function": "runRoute",
                "class": "Illuminate\\Routing\\Router",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
                "line": 656,
                "function": "dispatchToRoute",
                "class": "Illuminate\\Routing\\Router",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
                "line": 190,
                "function": "dispatch",
                "class": "Illuminate\\Routing\\Router",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 141,
                "function": "Illuminate\\Foundation\\Http\\{closure}",
                "class": "Illuminate\\Foundation\\Http\\Kernel",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/sentry/sentry-laravel/src/Sentry/Laravel/Http/SetRequestIpMiddleware.php",
                "line": 45,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "Sentry\\Laravel\\Http\\SetRequestIpMiddleware",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/sentry/sentry-laravel/src/Sentry/Laravel/Http/SetRequestMiddleware.php",
                "line": 31,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "Sentry\\Laravel\\Http\\SetRequestMiddleware",
                "type": "->"
            },
            {
                "file": "/MySite/app/Http/Middleware/DbSelector.php",
                "line": 37,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "App\\Http\\Middleware\\DbSelector",
                "type": "->"
            },
            {
                "file": "/MySite/app/Http/Middleware/Cors.php",
                "line": 32,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "App\\Http\\Middleware\\Cors",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
                "line": 21,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ConvertEmptyStringsToNull.php",
                "line": 31,
                "function": "handle",
                "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "Illuminate\\Foundation\\Http\\Middleware\\ConvertEmptyStringsToNull",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php",
                "line": 21,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TrimStrings.php",
                "line": 40,
                "function": "handle",
                "class": "Illuminate\\Foundation\\Http\\Middleware\\TransformsRequest",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "Illuminate\\Foundation\\Http\\Middleware\\TrimStrings",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php",
                "line": 27,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "Illuminate\\Foundation\\Http\\Middleware\\ValidatePostSize",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/PreventRequestsDuringMaintenance.php",
                "line": 86,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "Illuminate\\Foundation\\Http\\Middleware\\PreventRequestsDuringMaintenance",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Http/Middleware/TrustProxies.php",
                "line": 39,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "Illuminate\\Http\\Middleware\\TrustProxies",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/sentry/sentry-laravel/src/Sentry/Laravel/Tracing/Middleware.php",
                "line": 53,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 180,
                "function": "handle",
                "class": "Sentry\\Laravel\\Tracing\\Middleware",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php",
                "line": 116,
                "function": "Illuminate\\Pipeline\\{closure}",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
                "line": 165,
                "function": "then",
                "class": "Illuminate\\Pipeline\\Pipeline",
                "type": "->"
            },
            {
                "file": "/MySite/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php",
                "line": 134,
                "function": "sendRequestThroughRouter",
                "class": "Illuminate\\Foundation\\Http\\Kernel",
                "type": "->"
            },
            {
                "file": "/MySite/public/index.php",
                "line": 53,
                "function": "handle",
                "class": "Illuminate\\Foundation\\Http\\Kernel",
                "type": "->"
            },
            {
                "file": "/Users/ricardonolan/.composer/vendor/laravel/valet/server.php",
                "line": 234,
                "function": "require"
            }
        ]
    }

Fetching Points within coordinates received from Google Maps

Hi, this is not an issue, I just need help with something, if that's alright.

I pull google map bounds, and the result I get is this:

{ south: 44.85856815478515, west: 12.956013352988899, north: 46.61810356385327, east: 18.40797868502015 }

or this:

North-east:

{ lat: 46.61810356385327, lng: 18.40797868502015}

South-west:

{ lat: 44.85856815478515, lng: 12.956013352988899 }

What I'm trying to do is fetch Locations form my MySQL database within those bounds. I've figured I probably need to use whereWithin() method, which accepts Geometry as the second argument. How do I make an instance of Geometry with the data that I have?

Is it as simple as just translating those point to south-east and north-west, and then creating a Polygon using fromJson, or is there more to it?

Thanks!

response()->json() fails as it incorrectly interprets spatial fields

When returning a collection with some spatial fields in it (in our case, all Point's) like this:

return response()->json($res);

We get a 500 error on the server with "Malformed UTF-8 characters, possibly incorrectly encoded".
As soon as I null the spatial field in the DB, the error dissolves. It seemingly is unable to correctly create a json out of the field.
Using latest Laravel 9 and current master.

Connection Exception if run in Octane mode

The bug appears after approximately 40 - 60 secs of instance lifetime, probably due connection outdating.... In regular FPM mode it is working as expected.

{
"class": "Error",
"message": "Call to a member function getAttribute() on null",
"code": 0,
"file": "/var/task/vendor/laravel/framework/src/Illuminate/Database/MySqlConnection.php:23",
"trace": [
"/var/task/vendor/matanyadaev/laravel-eloquent-spatial/src/AxisOrder.php:34",
"/var/task/vendor/matanyadaev/laravel-eloquent-spatial/src/AxisOrder.php:18",
"/var/task/vendor/matanyadaev/laravel-eloquent-spatial/src/Objects/Geometry.php:219",
"/var/task/vendor/matanyadaev/laravel-eloquent-spatial/src/SpatialBuilder.php:326",
"/var/task/vendor/matanyadaev/laravel-eloquent-spatial/src/SpatialBuilder.php:95",
"/var/task/app/Domain/Car/Actions/GetChargingStations.php:111",
"/var/task/vendor/laravel/framework/src/Illuminate/Conditionable/Traits/Conditionable.php:34",
"/var/task/app/Domain/Car/Actions/GetChargingStations.php:114",
"/var/task/app/Domain/Car/Actions/GetChargingStations.php:29",
"/var/task/app/Domain/Car/Http/Controllers/Api/ChargingStationController.php:469",

"Expected MatanYadaev\EloquentSpatial\GeometryCast, string given" while swapping two records

Hi!,
i am trying to implement draft functionality on model. in that while trying to swap two records. i am facing Expected MatanYadaev\EloquentSpatial\GeometryCast, string given this type of error.
Updating location data doesn't work.
Below is the snapshot of swapping code.

$oldAttributes = $published?->getAttributes() ?? [];
        $newAttributes = $this->getAttributes();
        Arr::forget($oldAttributes, $this->getKeyName());
        Arr::forget($newAttributes, $this->getKeyName());

        $published->forceFill($newAttributes);
        $this->forceFill($oldAttributes);

The field is casted in model as
location' => Point::class,

in the migration the field is created as
$table->point('location')->nullable();

Using Laravel-Drafts package for implementing draft functionality.

Generic geometry object

I have a column that can be either a Point or a Polygon, so this column has the generic geometry type. But I'm getting an error when I cast it.

Illuminate\Database\QueryException: SQLSTATE[HY093]: Invalid parameter number (SQL: insert into `areas` (`name`, `type`, `city_id`, `region_id`, `description`, `ai_description`, `country_id`, `geometry`, `centroid`, `updated_at`, `created_at`) values (Priceport, NH, sublocality_level_2, 1697, 3286, Tempore sint molestiae distinctio porro ab vel. Exercitationem quam illum rerum enim nam quidem. Ut soluta dicta quos iste., Et totam velit corrupti voluptatum nobis perferendis magnam. Quia non asperiores quas nihil. Qui sit at voluptate quam dolorem consequatur., 914, ST_GeomFromText('POINT(113.417617 -24.459282)', 4326, 'axis-order=long-lat'), ST_GeomFromText(2024-01-29 06:07:51, 2024-01-29 06:07:51, 'axis-order=long-lat'), ?, ?))

/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Connection.php:760
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Connection.php:720
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Connection.php:546
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Connection.php:498
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Query/Processors/Processor.php:32
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:3322
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:1869
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1330
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1295
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1138
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:330
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php:235
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:339
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:283
/var/www/datacontent/tests/Feature/Controllers/Api/LocationControllerTest.php:54

Caused by
PDOException: SQLSTATE[HY093]: Invalid parameter number

/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Connection.php:545
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Connection.php:753
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Connection.php:720
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Connection.php:546
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Connection.php:498
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Query/Processors/Processor.php:32
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:3322
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php:1869
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1330
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1295
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php:1138
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:330
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Collections/Traits/EnumeratesValues.php:235
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:339
/var/www/datacontent/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Factories/Factory.php:283
/var/www/datacontent/tests/Feature/Controllers/Api/LocationControllerTest.php:54

Illuminate\Database\SQLiteConnection error

  • Laravel: 10.5.0
  • matanyadaev/laravel-eloquent-spatial: 3.1.2
  • PHPUnit: 10.0.19
  • Pest: 2

phpunit.xml

<server name="DB_CONNECTION" value="sqlite"/>
<server name="DB_DATABASE" value=":memory:"/>

I write a FeatureTest which creates a model through a factory, and the factory looks like this:

public function definition(): array
  {
      return [
          ...
          'address' => $this->faker->address(),
          'point' => new Point($this->faker->latitude, $this->faker->longitude),
          ...
      ];
  }

Inside my test, I execute the following code: MyModel::factory()->create() and I get the following error

Error:
MatanYadaev\EloquentSpatial\AxisOrder::isMariaDb(): Argument #1 ($connection) must be of type Illuminate\Database\MySqlConnection, Illuminate\Database\SQLiteConnection given, called in /app/vendor/matanyadaev/laravel-eloquent-spatial/src/AxisOrder.php on line 18

I can somehow make it work with sql-lite?

Help using Spatial with Spatie QueryBuilder

After the recent change that removes SpatialBuilder (#102), I am trying to use Spatie QueryBuilder to sort by distance.

$businesses = QueryBuilder::for(Business::class)
  ->allowedSorts([
      AllowedSort::custom('distance', new AddressDistanceSort()),
  ])
  ->paginate()
  ->withQueryString();
class AddressDistanceSort implements Sort
{
  public function __invoke(Builder $query, bool $descending, string $property)
  {
    $point = new Point(request()->latitude, request()->longitude, Srid::WGS84->value);

    $query->with(['address' => function ($query) use ($point, $descending) {
      $query->withDistance('location', $point);
    }]);
    
    // How to apply orderByDistance here???
  }
}

Obviously I'm not saying it's a bug in the Spatial package, but I think a lot of Laravel developers use Spatie QueryBuilder and I was wondering if anyone has managed to get this to work.

Could this package work together with Spatie QueryBuilder?

Thank you very much for your help and for this great package.

Unknown column 'distance_sphere'

Laravel: 10.1.5
matanyadaev/laravel-eloquent-spatial: 3.1.2

Query example:
Users::whereDistanceSphere('location', $user->location, '<', 20)->get()

Error:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'distance_sphere' in 'where clause' (Connection: mysql, SQL: select * from `users` where `distance_sphere` = location)

What do I do wrong?

Feature request: ST_Buffer support

It would be brilliant if the API spatial scopes could be expanded to support ST_Buffer, e.g.


whereBuffer

Filters records within a buffer. Uses ST_Buffer.

parameter name type
$column Geometry \ string
$geometryOrColumn Geometry \ string
$value int \ float
Example
Place::create(['location' => new Point(1, 1.5)]);

$placesCountWithinBuffer = Place::query()
    ->whereBuffer('location', Polygon::fromJson('{"type":"Polygon","coordinates":[[[-1,-1],[1,-1],[1,1],[-1,1],[-1,-1]]]}'), 3)
    ->count();

echo $placesCountWithinBuffer; // 1

I will see if I can submit a PR, but with Christmas coming up it won't be for a little while!

Support `ST_CENTROID` spatial function

I'm using Laravel Eloquent Spatial in my project.
Despite I've could used it pretty well when selecting Point objects within a Polygon geometry, I had to create a raw SQL request to use those MySQL Spatial methods.

Here's my code of a method in my app, used to return a Point geometry with the centroid of a polygon:

public function centroide(array $featurePoligono){

  error_log(json_encode($featurePoligono)); //{"type":"Feature" ...}
  error_log(json_encode($featurePoligono['geometry'])); //{"type":"Polygon" ...}
  
  $dbQuery=DB::select('SELECT ST_AsGeoJSON(ST_Centroid(ST_GeomFromGeoJSON(\''. json_encode($featurePoligono) .'\')))');
  
  $centroide=array_values((array)$dbQuery[0])[0];
  
  error_log($centroide); //{"type": "Point", "coordinates": [-58.424712150445174, -34.605689506111084]}
  error_log(gettype($centroide)); //string
  error_log(get_class(json_decode($centroide))); //stdClass
  
  return (array)json_decode($centroide);
}

Is there any way to achieve this using Laravel Eloquent Spatial?

Have latitude and longitude swapped places?

Hi,

The factory class seems to be swapping the values of latitude and longitude. See the code below. Why is that? I'm using MariaDB v. 10.5. with Laravel 9.

protected static function createFromGeometry(geoPHPGeometry $geometry): Geometry
{
   if ($geometry instanceof geoPHPPoint) {
      return new Point($geometry->coords[1], $geometry->coords[0]);
   }
}

Support Laravel Nova

error:
Unable to encode attribute [original] for model [Laravel\Nova\Actions\ActionEvent] to JSON: Malformed UTF-8 characters, possibly incorrectly encoded.

Reverse point order

Hello,

image

The constructor accepts LAT as the first parameter and LNG as the second but the toArray() order and saving in the database are reversed. Is there any plans to change this or at least have a "reverse" functionality since in google maps for example the order is "LAT LNG".

Feature request: validation rules

It would be quite nice to include validation rules that could be used in form validations to validate appropriate JSON representations of each class.

For example, we could then validate requests using:

use MatanYadaev\EloquentSpatial\Rules\Point;
 
$request->validate([
    'location' => ['required', new Point],
]);

rather than having to do it manually, such as:

$request->validate([
    'location' => ['required', 'array:type,coordinates'],
    'location.type' => ['required', 'in:Point'],
    'location.coordinates' => ['required', 'array:0,1'],
    'location.coordinates.0' => ['required', 'numeric', 'min:-90', 'max:90'],
    'location.coordinates.1' => ['required', 'numeric', 'min:-180', 'max:180'],
]);

Unless I'm being a bit thick and can do it more easily than this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.