Skip to content

Instantly share code, notes, and snippets.

@monkeyphysics
Last active April 12, 2025 13:51
Show Gist options
  • Save monkeyphysics/8fa32b4bd79e185bc0a42b6b2ecab427 to your computer and use it in GitHub Desktop.
Save monkeyphysics/8fa32b4bd79e185bc0a42b6b2ecab427 to your computer and use it in GitHub Desktop.
Laravel MySQL Point Cast class
<?php
namespace App\Casts;
use Illuminate\Support\Facades\DB;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
// todo: make it even better by implementing a Point class and working with that
class Point implements CastsAttributes
{
public function get($model, $key, $value, $attributes)
{
// https://stackoverflow.com/questions/37467050/convert-mysqls-point-to-text-in-php
return unpack('x4/corder/Ltype/dlng/dlat', $value);
}
public function set($model, $key, $value, $attributes)
{
return DB::raw(sprintf('POINT(%f, %f)', $value['lng'], $value['lat']));
}
}
@martio
Copy link

martio commented May 6, 2024

My example for PHP 8 and MySQL 8 with SRID 4326:

$table->geography(column: 'coordinates', subtype: 'point', srid: 4326);
<?php

declare(strict_types=1);

namespace App\Casts;

use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Contracts\Database\Query\Expression;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;

class PointCast implements CastsAttributes
{
    /**
     * Cast the given value.
     *
     * @param array<string, mixed> $attributes
     */
    public function get(Model $model, string $key, mixed $value, array $attributes): array
    {
        if ( ! is_string(value: $value)) {
            return [
                'latitude' => 0.0,
                'longitude' => 0.0,
            ];
        }

        $coordinates = unpack(format: 'x4/corder/Ltype/dlng/dlat', string: $value);

        if ($coordinates === false) {
            return [
                'latitude' => 0.0,
                'longitude' => 0.0,
            ];
        }

        return [
            'latitude' => $coordinates['lat'],
            'longitude' => $coordinates['lng'],
        ];
    }

    /**
     * Prepare the given value for storage.
     *
     * @param array<string, mixed> $attributes
     */
    public function set(Model $model, string $key, mixed $value, array $attributes): Expression
    {
        if ( ! is_array(value: $value)) {
            $value = [
                'latitude' => 0.0,
                'longitude' => 0.0,
            ];
        }

        $lat = $value['latitude'] ?? 0.0;
        $lng = $value['longitude'] ?? 0.0;

        return DB::raw(value: "ST_GeomFromText('POINT({$lat} {$lng})', 4326)");
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment