Comments (10)
Hi guys, just experienced the same issue and after a long day of googling, I found that I forgot to use the use Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait;
in my model.
i.e.
use Illuminate\Database\Eloquent\Model;
use Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait;
class MyModel extends Model
{
use SpatialTrait;
protected $spatialFields = [ 'field', ];
// ...
}
That should solve it.
from laravel-mysql-spatial.
I tried using the output format on input, but that didn't work either.
from laravel-mysql-spatial.
Can you show your Location
model and how you're saving Coffee Shop 1?
Please note that we have Point::__construct($lat, $lng)
while when inserting into MySQL using this package, the latitude and longitude should be inverted and the final query should look like:
insert into `locations` (`name`, `location`) values ('Coffee Shop 1', ST_GeomFromText('POINT(-0.118092 51.509865)'))
Also, note that the JSON output is formatted into GeoJSON and I unfortunately haven't had enough time to work on #23.
from laravel-mysql-spatial.
It's all very minimal. My model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Grimzy\LaravelMysqlSpatial\Eloquent\SpatialTrait;
class Location extends Model
{
use SpatialTrait;
protected $fillable = [
'name',
'location',
];
protected $spatialFields = [
'location',
];
}
My controller's creation method is simply:
public function create(Request $request)
{
$location = Location::create($request->all());
return response()->json($location);
}
What's apparent from what you say is that there is no preset format for the point field type, so I'm assuming I need to expand the point value into lat long for delivery to the client, and map it back from lat & long on input. I was hoping there would be some standardised way to handle that, as there is for strings, numbers and arrays, for example to automatically map fieldname.long
and fieldname.lat
into the point type on the request, and vice versa on responses. The idea there is that a simple $location = Location::create($request->all());
would "just work" with no additional processing.
I assume pretty much everyone needs to do this kind of processing, so I was a bit surprised that there was no info on how to do it.
from laravel-mysql-spatial.
You're absolutely right, there's currently no standardized way to handle input and it's a much needed feature.
The current implementation of the package only integrates with Eloquent/MySQL and allows to serialize spatial fields to GeoJSON. Regrettably, until #23 is completed there isn't a straightforward way to deserialize from GeoJSON.
In fact, one of the dependencies of this package is a GeoJSON parser (jmikola/geojson) and can help in mapping GeoJson to spatial fields.
I assume pretty much everyone needs to do this kind of processing, so I was a bit surprised that there was no info on how to do it.
Feel free to submit a PR ;)
from laravel-mysql-spatial.
Hi, any update on this?
I am trying to do a bulk insert in MySQL using MyModel::insert($myModelInstances[]), where myModelInstances[] is an array of serialized instances new MyModel()->toArray(). The MyModel class in question contains a Point field.
As a workaround, I have tried, after converting the instances of MyModel to array, to manually set the field point with $serializedInstance['point'] = "ST_GeomFromText('{$point->toWkt()}')";. But I am getting the same error.
If I grab the SQL that outputs the error and run it in MySQL, it inserts without any problems:
SQL: insert into my_model
(point
, order
, fw_id
) values (ST_GeomFromText('POINT(-43.92693 -19.88423)'), 0, 1067))
Any ideias on how to adress it? Thanks.
from laravel-mysql-spatial.
I have found a workaround using:
$serializedInstance['point'] = DB::raw("ST_GeomFromText('{$point->toWkt()}')");
from laravel-mysql-spatial.
I have the same issue. Here is what I'm planning on doing. Curious to hear if there is an easier or better way to do it. I have:
$model->center_point = preparePoint($attributes['center_point']);
which calls
/**
* Makes sure input is a Point
*
* @param $string POINT
* @return \Grimzy\LaravelMysqlSpatial\Types\Point
*/
function preparePoint($point)
{
if (empty($point)) return NULL;
if ($point instanceof \Grimzy\LaravelMysqlSpatial\Types\Point) return $point;
if (gettype($point) == "string")
{
if (strpos($point, 'POINT') === false) // Needs to be wrapped with POINT()
{
$point = "POINT(".$point.")";
}
return \Grimzy\LaravelMysqlSpatial\Types\Point::fromWKT($point);
}
else return NULL;
}
from laravel-mysql-spatial.
I have found a way to make the input work, but it doesn't make much sense. I would have written this as a wiki article, but it seems that the wiki is disabled in this repo. Here goes...
In a Laravel app, I have a Location
model which has a location
field in the DB that is of the point
geospatial type, defined like this:
$table->point('location')->spatialIndex();
The problem is that there is no defined input format for such fields - every single example of using point types I've found always defines the point value within the script; it's never a user-submitted value! In the absence of such a format, the most straightforward thing to do is implement longitude
and latitude
attributes as virtual attributes; Virtual because they are never stored in the database. The idea here is that when I retrieve the location
property from the DB, I split it into lat & long numeric fields, and when storing, I combine them back into a value that's acceptable to the point
type. So I have mutators & accessors:
public function getLongitudeAttribute(): float
{
return $this->location->getLng();
}
public function getLatitudeAttribute(): float
{
return $this->location->getLat();
}
public function setLongitudeAttribute(float $longitude): void
{
$this->location->setLng($longitude);
}
public function setLatitudeAttribute(float $latitude): void
{
$this->location->setLat($latitude);
}
To tick a bunch of other boxes for this, lat & long appear in $fillable
, but location
does not:
protected $fillable = [
...
'longitude',
'latitude',
...
];
For the geospatial stuff, it needs to be told which are spatial fields, and we never want the location
property to be included directly in any input or output, so I hide it:
protected $spatialFields = [
'location',
];
protected $hidden = [
'location',
];
Lat & long are added dynamically to the model using $appends
, and because Laravel can't tell what type they should be (as they don't exist in the DB), I fill in $cast
entries:
protected $appends = [
'longitude',
'latitude',
];
protected $casts = [
'longitude' => 'float',
'latitude' => 'float',
];
That all looks about right, but when I try to create a new record, it fails because the location
field has no default value. This is kind-of correct, because point values can't have default values in MySQL, however, it should be setting it to a proper value via the mutators when the long & lat attributes are set. But I found a workaround.
Add the location
attribute back into the $fillable
property (why???!), then in the controller, manually patch in the conversion to a point value:
$request->request->add(['location' => new Point($request->input('latitude'), $request->input('longitude'))]);
and then I pass in the location
attribute and not the longitude
& latitude
attributes to the creation call:
$location = Location::create(
$request->only(
[
...
'location',
]
)
);
While this works, it's really not the "right" way to achieve it; I should not need to inject this conversion manually; it should be implicit when setting latitude & longitude attributes. It also means that I need to do the same thing any time the location needs to be updated, and that's a recipe for bugs.
Anyway, so while this works, it seems incredibly convoluted and inelegant - I'd love to see a better way!
from laravel-mysql-spatial.
I use a mutator like this:
public function setLocationAttribute($value)
{
$locationArray = explode(',', $value);
$this->attributes['location'] = new Point(
$locationArray[0],
$locationArray[1]
);
}
of course the json is like this:
{
"location": "1.2,2.3"
}
from laravel-mysql-spatial.
Related Issues (20)
- This makes funny things to the DB, and then break stuff…
- Syntax error with Laravel 8, MariaDB 10.6 and SRID HOT 2
- Migration from 4.X to 5.0.0 breaks SRID HOT 2
- Error in save or retrieve HOT 1
- Not able to update geometry field with MultiPoint HOT 1
- Does it work with PHP8.1 ? HOT 4
- Laravel 9 Support HOT 19
- MariaDB doesnt support creating a geometrycolumn with an SRID
- Polygon GeoJson String Validation
- laravel 9 HOT 2
- Invalid parameter value: 3037 Invalid GIS data provided to function st_geometryfromtext
- Cast request spatial data to Eloquent model via fill method is not possible
- Cast request spatial data to Eloquent model via fill method is not possible HOT 1
- Should support sqlite / spatiallite
- {"message":"Call to a member function getLat() on string"}
- Slow Cache retrieval
- Laravel 10 HOT 3
- Laravel 9 Issue HOT 3
- Any Update for Laravel 10 HOT 2
- Type error HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from laravel-mysql-spatial.