Technical Evaluation
What the package actually is: phayes/geophp is a pure-PHP geometry library — a parser/serializer and lightweight geometry engine for WKT, WKB, GeoJSON, KML, GPX, GeoRSS, with optional adapters for the GEOS PHP extension and PostGIS. It is not a spatial database, not a projection engine, and not a substitute for PostGIS.
Architecture fit
- Fits as an anti-corruption layer between external geo payloads (uploads, partner APIs, KML/GPX feeds) and our canonical storage format. This is the highest-value, lowest-risk use: normalize whatever comes in to GeoJSON/WKT before it touches the database.
- Poor fit as the system's geometry compute engine. Without GEOS loaded, topological operations (intersect, union, buffer, convex hull on complex shapes) are either unavailable or numerically fragile. If the product needs real spatial predicates or overlays, the correct architecture is PostGIS/GEOS doing the work, with geoPHP relegated to parsing.
- No SRID/projection capability worth relying on. Anything requiring reprojection needs proj4 bindings or PostGIS
ST_Transform; geoPHP cannot own that responsibility.
- No Laravel integration surface: no service provider, no config, no facade, no published contracts. It is a plain library we must wrap ourselves.
Integration feasibility
- Trivially installable via Composer (
phayes/geophp), zero runtime services, no PHP extensions required for the core path. Time-to-first-parse is measured in hours, not sprints.
- The API is small and readable (
geoPHP::load($data, 'wkt'), ->out('geojson'), ->getComponents()), so a thin wrapper class plus a Laravel singleton binding is a one-day task.
- Optional GEOS adapter is a genuine capability cliff: with GEOS the library becomes useful for topology; without it, it silently isn't. Deployment environments must be pinned deliberately, not left to chance.
- Wrapping is mandatory anyway: we need our own exception handling, input size guards, and logging, because several internal failure paths return
null/false rather than throwing.
Technical risk (ranked)
- License ambiguity — highest risk. GitHub reports
NOASSERTION; geoPHP has historically carried a GPL-2.0/BSD dual notice. A GPL read on a distributed or SaaS-adjacent product is a legal blocker, not an engineering preference. Resolve with counsel before any code is written.
- Maintenance velocity. ~875 stars but a low opportunity score (27.5) signals a library in maintenance/dormancy, not growth. Upstream activity is sporadic and the 2.x line has been "in progress" for years. Assume we will own patches.
- PHP/Laravel version drift. Legacy codebases of this vintage routinely surface PHP 8.x deprecations (dynamic properties, implicit nullable params, string/array coercion). A compatibility spike against our actual PHP 8.2/8.3 target is a hard gate, not a nice-to-have.
- Numerical robustness. Pure-PHP floating-point geometry yields invalid polygons, self-intersections, and precision drift on real-world data. Any workflow where a wrong answer is worse than no answer (billing by region, eligibility by boundary) needs a validity gate and a GEOS/PostGIS cross-check.
- Resource behavior. Geometry is loaded fully in memory as PHP objects; a large KML or a dense parcel polygon can blow
memory_limit with no streaming path.
Key questions to answer before commitment
- Do we need topological operations at all, or only format conversion? (Conversion-only ⇒ low risk. Topology ⇒ requires GEOS in prod and a fallback story.)
- Can we run the GEOS PHP extension in every target environment (containers, shared hosting, CI)? Who owns that packaging?
- What is our canonical geometry store — PostGIS geography/geometry columns, or JSON blobs with GeoJSON? If PostGIS exists, why is geoPHP doing anything but parsing?
- What is the license position from legal, in writing?
- What are realistic payload sizes and concurrency? What is our per-request geometry time budget?
- Is there an exit? If we wrap it behind a
GeometryService interface, can we swap to brick/geo, geotools, or pure PostGIS in a sprint?
Integration Approach
Stack fit
- Laravel 9–11, PHP 8.1–8.3: treat as unverified until spiked. Composer install works; runtime cleanliness on 8.2+ is the unknown.
- Bind behind our own interface:
App\Contracts\GeometryCodec with a GeoPhpCodec implementation, resolved as a singleton. No controller, job, or model should import geoPHP directly. This is the single most important design decision, because it converts a dependency risk into a one-file swap.
- Pair it with a real spatial store. Recommended: PostGIS on PostgreSQL, with geoPHP handling ingest normalization only and
ST_* functions handling predicates. On MySQL, POINT/POLYGON with SRID 4326 is usable but weaker; on SQLite, spatialite is the only credible option. If we have no spatial store, geoPHP is a stopgap, not a foundation.
Migration path
- Phase 0 — spike (2–3 days). Install against our exact PHP/Laravel matrix; run a fixture corpus (valid, invalid, self-intersecting, huge, mixed SRID, malformed KML/GPX). Measure memory, latency, and failure modes. Get license sign-off in parallel.
- Phase 1 — read path only. Add
GeometryCodec and use geoPHP solely to parse inbound formats into canonical GeoJSON/WKT before persistence. No geometry math in the product.
- Phase 2 — storage decision. If volume or query needs justify it, migrate the canonical store to PostGIS and move predicates server-side. geoPHP's role shrinks; that is success, not failure.
- Phase 3 — topology, only if demanded. Enable GEOS in a single, pinned container image; gate all GEOS-dependent calls behind a feature flag with a defined degradation behavior.
Compatibility and sequencing notes
- Pin the exact Composer version and commit the lockfile; use
replace/fork strategy if upstream is unpatchable.
- Add a CI matrix job specifically for the geoPHP fixtures so a PHP upgrade that breaks parsing fails loudly, not in production.
- Do the license review and the PHP 8 spike concurrently — both are cheap and both can kill the initiative.
- Sequence the storage decision before the topology decision. Teams routinely adopt a PHP geometry library because they lack a spatial database, then discover the library can't do what the database would have done for free.
Operational Impact
Maintenance
- Expect to own this code. Budget a named owner and a small maintenance retainer: dependency bumps, PHP-version fixes, and security triage for a package with dormant upstream activity.
- Prefer vendoring or an internal fork with a documented patch set over depending on an unresponsive upstream. Record every local patch so a future upstream release can be reconciled.
- Add contract tests around the
GeometryCodec interface — these are the artifact that makes the eventual migration to brick/geo or PostGIS cheap.
Support
- Internal support burden is low for format conversion (deterministic, easy to debug) and high for geometry math (subtle, hard to reproduce, hard to explain to a customer). Route topology bugs to platform, not to product support.
- Publish an internal "supported formats and known limitations" note so downstream teams stop assuming full OGC compliance.
Scaling
- Geometry parsing is CPU-bound PHP with no parallelism and no spatial indexing. It scales by adding workers, not by adding cores to one request.
- Move all non-trivial parsing to queued jobs with explicit
memory_limit and timeout overrides; never parse untrusted large geometry in an HTTP request.
- Impose hard ingest caps (byte size and vertex count) at the edge. An uncapped KML upload is a trivial denial-of-service against a PHP-FPM pool.
- If throughput matters, the scaling answer is PostGIS, not more PHP workers. State this in the design doc up front.
Failure modes to instrument
- Silent
null/false returns on malformed input — wrap every call and convert to a typed exception; log the raw payload hash.
- Out-of-memory on large geometries — catch, cap, and reject with a clear client error rather than a 500.
- Invalid/self-intersecting polygons passing through unchecked — run an explicit validity check at ingest and quarantine failures.
- SRID mismatch and silent coordinate misinterpretation (lat/lng swapped) — assert SRID and axis order at the boundary; this is the most common way geo bugs reach customers.
- GEOS-present vs GEOS-absent divergence between dev and prod — assert GEOS availability at boot and fail fast if a required capability is missing.
- Precision drift after round-tripping WKT→object→WKT — snapshot-test round-trips on a fixture corpus.
Ramp-up
- Low. A mid-level PHP engineer is productive in a day; the API is small and the failure modes are learnable.
- The real ramp-up cost is domain literacy — SRIDs, axis order, projection vs. datum, validity vs. correctness. Fund a half-day of geo fundamentals for the team; it prevents more incidents than any code review.
- Because the wrapper isolates the library, onboarding new engineers does not require them to learn geoPHP's internals at all — only our interface and our data contracts.
TPM verdict
Treat phayes/geophp as a tactical ingest adapter behind a stable interface, contingent on written license clearance and a clean PHP 8.x spike. Do not adopt it as the platform's geometry engine. The 875 stars reflect historical relevance, not current momentum; the low opportunity score and NOASSERTION license make this a borrow-and-wrap decision, not a build-on decision.