Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Geo Parser Laravel Package

creof/geo-parser

Creof GeoParser is a PHP library that parses geographic coordinate strings and formats like WKT, GeoJSON, KML, and GPX into geometry objects via geoPHP, making it easy to import, convert, and work with spatial data in Laravel and PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

creof/geo-parser is a small, standalone PHP library that turns free-form coordinate strings (40.7128, -74.0060, 40°42'46"N 74°0'22"W) and WKT literals (POINT(-74.0060 40.7128)) into value objects from creof/geo. It is not Laravel-aware — there is no service provider, facade, config file, or validation rule shipped with it. Plan to wire it up yourself.

composer require creof/geo-parser

Look at these first:

  1. Creof\GeoParser\GeoParser — the single entry point. parse($string) auto-detects the format and returns the parsed value object(s).
  2. Creof\GeoParser\Parse\ParseCoord and Parse\ParseWKT — the concrete strategies that do the work; look here when a string fails to parse and you need to know the accepted grammar.
  3. Creof\Geo\Value\Coordinate — the lat/lon value object you will almost always end up holding.

First use case — parse a user-supplied "lat, lng" input in a controller:

use Creof\GeoParser\GeoParser;

$parser = new GeoParser();
$coordinate = $parser->parse($request->input('location')); // e.g. "40.7128, -74.0060"

$coordinate->getLatitude();  // 40.7128
$coordinate->getLongitude(); // -74.0060

Bind it as a singleton in AppServiceProvider so you are not instantiating it per call:

$this->app->singleton(\Creof\GeoParser\GeoParser::class, fn () => new \Creof\GeoParser\GeoParser());

Then app(GeoParser::class) or constructor injection works everywhere.

Implementation Patterns

Validation rule for form input. The parser throws on garbage, which makes it a natural validation rule:

use Creof\GeoParser\GeoParser;
use Illuminate\Contracts\Validation\Rule;

class CoordinateString implements Rule
{
    public function passes($attribute, $value): bool
    {
        try {
            app(GeoParser::class)->parse((string) $value);
            return true;
        } catch (\Throwable $e) {
            return false;
        }
    }

    public function message(): string
    {
        return 'The :attribute must be a valid coordinate pair or WKT literal.';
    }
}

Normalize on the way in via a form request. Parse once in prepareForValidation()/passedValidation() and store canonical numeric columns rather than the raw string, so downstream queries are simple:

protected function passedValidation(): void
{
    $coord = app(GeoParser::class)->parse($this->input('location'));
    $this->merge([
        'latitude'  => $coord->getLatitude(),
        'longitude' => $coord->getLongitude(),
    ]);
}

Bulk imports (CSV/seeders). Reuse one GeoParser instance across the loop — the object is stateless and cheap to call. Collect failures instead of aborting the whole import:

$parser = app(GeoParser::class);
$errors = [];

foreach ($rows as $i => $row) {
    try {
        $coord = $parser->parse($row['coords']);
    } catch (\Throwable $e) {
        $errors[$i] = $e->getMessage();
        continue;
    }
    // persist...
}

WKT for spatial columns. MySQL POINT/GEOMETRY columns and PostGIS accept WKT. Since the parser reads WKT but does not write it, treat it as input-side only: parse user WKT, pull the coordinate out, and let your own ST_GeomFromText/ST_MakePoint or creof/geo geometry objects do the output. Keep coordinate ordering explicit at the boundary (see Gotchas).

API resources. Serialize to a stable shape rather than exposing creof/geo objects directly — they are not JsonSerializable in a way tailored to your clients:

return [
    'latitude'  => (float) $coordinate->getLatitude(),
    'longitude' => (float) $coordinate->getLongitude(),
];

Multi-format endpoint. Because parse() auto-detects, you can accept decimals, DMS, and WKT through one field and branch only when you need to know which format arrived — parse the WKT path separately if you need the geometry type (point vs. linestring).

Gotchas and Tips

  • Coordinate order is the #1 bug source. Human strings are almost always lat, lng; WKT POINT(x y) is lng lat. Parse WKT into a Coordinate and always read via getLatitude()/getLongitude() rather than positional access, or you will silently swap axes on one code path.
  • The package is old. Last release was 2019 and it predates PHP 8 typed properties and many deprecations. Test on your actual PHP version; if Composer blocks installation, verify the real constraint before reaching for --ignore-platform-reqs, which hides genuine incompatibilities.
  • Exceptions are generic in practice. Catch \Throwable at the boundaries rather than memorizing specific exception classes — input that is almost a coordinate (extra text, a trailing comma, a range unit suffix) fails in slightly different ways depending on which parser strategy is tried first.
  • It parses, it does not validate geography. parse("91, 0") may succeed syntactically. Add your own range check (-90..90, -180..180) if lat/lon correctness matters; the parser is not a geographic validator and definitely not a geocoder.
  • No writer. There is no toWKT() serializer here. For output, either build WKT yourself or use creof/geo geometry objects — check what the installed version exposes before assuming symmetry with the parser.
  • No Laravel integration means no config. Format switching, strictness, and defaults are yours to own. If you need "reject DMS, accept decimals only," implement it by calling the specific parse strategy or by pre-checking with a regex rather than by configuration.
  • Precision and casting. Coordinates are returned as floats; casting to strings on the way to the DB can reorder/round things. Store numeric columns and format only at the response layer.
  • Extension point. ParseInterface/the Parse\* classes are the seam to watch: if you need a custom grammar (e.g. "lat/lng" with a slash separator or a plus-code prefix), implement the parse interface and compose it rather than regex-splitting in your controller.
  • Test the edges. Poles, the antimeridian, leading +/-, and DMS with seconds all behave subtly differently. Put a handful of these strings in a Pest/PHPUnit data provider early — it doubles as documentation for your team about what the field accepts.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons