barryvdh/laravel-ide-helper

mysql point columns casted as MatanYadaev\EloquentSpatial\Objects\Point are type hinted as Geometry

vazaha-nl opened this issue · 1 comments

Versions:

  • ide-helper Version: v2.13.0
  • Laravel Version: v10.25.2
  • PHP Version: 8.2.11

Question:

I have a mysql table containing a point (for coordinates) column. In the corresponding model I cast this column to the Matan\Yadaev\EloquentSpatial\Objects\Point class from https://github.com/MatanYadaev/laravel-eloquent-spatial.

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

When I generate the docblocks using ide-helper, the property gets type hinted as follows:

 * @property \MatanYadaev\EloquentSpatial\Objects\Geometry|null $location

I would expect:

 * @property \MatanYadaev\EloquentSpatial\Objects\Point|null $location

The Point class is a subclass of Geometry. But only the Point class has public latitude and longitude properties, which my IDE now doesn't know about.

Is it possible in some way to enforce that the $location property is type hinted as Point i/o Geometry? I tried editing the ide_helper config file, adding:

    'interfaces' => [
        MatanYadaev\EloquentSpatial\Objects\Geometry::class => MatanYadaev\EloquentSpatial\Objects\Point::class,
    ],

but that doesn't seem to work. Also tried the other way around.

So I did some further research myself and I found the cause, and also a workaround. The cause is not a bug in my opinion but just a result of how things work in ide-worker and how things are implemented in the EloquentSpatial lib.

The cause is that the Point::class cast is resolved to Geometry::class because all share the same Cast class, \MatanYadaev\EloquentSpatial\GeometryCast. The get() method has Geometry|null as return value, see https://github.com/MatanYadaev/laravel-eloquent-spatial/blob/master/src/GeometryCast.php#L34. And that return type is used to get the correct type. See https://github.com/barryvdh/laravel-ide-helper/blob/master/src/Console/ModelsCommand.php#L1379

The workaround is to add the following to the type_overrides array in config/ide-helper.php:

    'type_overrides' => [
        // ...
        '\MatanYadaev\EloquentSpatial\Objects\Geometry|null' => '\MatanYadaev\EloquentSpatial\Objects\Point|null',
    ],

and now it works, for my limited case. This is a hack because it only works as long as I don't use any of the other Geometry subclasses (like fe Polygon) as eloquent cast, because all other subclasses will be resolved to Point which would be even more wrong.

I wouldn't know a better solution and I even doubt whether this is solvable at all for all cases.