You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've been studying it under a lot of angles and I either have a problem at insertion time OR at query time. Here is what I have and what is going on. Following is a PR.
Models
I have 3 models, each properly setup using the spatial trait and declaring the spatial fields
class Region extends Model {
// that one has a required zone attribute which is a Polygon
}
class Forecast extends Model {
// that one has a required zone attribute which is a Polygon
}
class Boat extends Model {
// that one has a required location attribute which is a Point
}
Creating a Forecast for a Region
From Laravel Nova, one can create a Forecast easily by specifying a region instead of directly specifying the zone. Filling the Forecast zone from the Region zone is done using an Eloquent observer with the creating method getting called before the model is saved.
class WeatherForecastCreationObserver
{
private NovaRequest $request;
public function __construct(NovaRequest $request)
{
$this->request = $request;
}
public function creating(WeatherForecast $forecast)
{
$coast = Coast::find($this->request->input('coast_id'));
if ($coast !== null)
{
unset($forecast->coast_id);
// This is throwing an SQLException, see below
// $forecast->zone = $coast->zone;
// I can however make it happy by wrapping it inside a SpatialExpression
// Remember this tweak #1 as I will refer to it in next observer
$forecast->zone = new SpatialExpression($coast->zone);
}
}
}
Here is the exception
Numeric value out of range: 1416
Cannot get geometry object from data you send to the GEOMETRY field
(SQL: insert into `weather_forecasts` (`timestamp`, `zone`) values
(2020-02-18 00:00:00, (-16.3 16.28,-23 16.28,-23 14.45,-16.3 14.45,-16.3 16.28)))
at /home/vagrant/code/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669)
I believe that inside the observer it is too late to convert fields and they get thrown at MySQL the way they are stored.
Alerting boats from a forecast alert
I have another observer which gets called to notify boats when an alarming forecast is saved in database. Its job is to query all boats inside forecast zone and send them a message.
class BroadcastWeatherAlertObserver
{
public function saved(WeatherForecast $forecast)
{
$boatsAtRisk = Boat::within('location', $forecast->zone)->get();
}
}
That method gets called after the Forecast is saved. Because of my tweak above, $forecast->zone passed to the within method is not a GeometryInterface. Hence the scopeWithin method fails:
Call to undefined method Grimzy\LaravelMysqlSpatial\Eloquent\SpatialExpression::toWkt()
at /home/vagrant/code/vendor/grimzy/laravel-mysql-spatial/src/Eloquent/SpatialTrait.php:219)
However, we cannot assume it always will be a SpatialExpression, as we may have set the zone directly using a Polygon (first observer exiting early).
Any idea how to fix it all?
Proposed fix
My current solution and proposed PR is to add the method toWkt() to the SpatialExpression class:
public function toWkt()
{
return $this->value->toWkt();
}
The text was updated successfully, but these errors were encountered:
I've been studying it under a lot of angles and I either have a problem at insertion time OR at query time. Here is what I have and what is going on. Following is a PR.
Models
I have 3 models, each properly setup using the spatial trait and declaring the spatial fields
Creating a Forecast for a Region
From Laravel Nova, one can create a Forecast easily by specifying a region instead of directly specifying the zone. Filling the Forecast zone from the Region zone is done using an Eloquent observer with the
creating
method getting called before the model is saved.Here is the exception
I believe that inside the observer it is too late to convert fields and they get thrown at MySQL the way they are stored.
Alerting boats from a forecast alert
I have another observer which gets called to notify boats when an alarming forecast is saved in database. Its job is to query all boats inside forecast zone and send them a message.
That method gets called after the Forecast is saved. Because of my tweak above,
$forecast->zone
passed to thewithin
method is not aGeometryInterface
. Hence the scopeWithin method fails:However, we cannot assume it always will be a SpatialExpression, as we may have set the zone directly using a Polygon (first observer exiting early).
Any idea how to fix it all?
Proposed fix
My current solution and proposed PR is to add the method
toWkt()
to theSpatialExpression
class:The text was updated successfully, but these errors were encountered: