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

Kml Parser Laravel Package

plin-code/kml-parser

Parse KML and KMZ files in Laravel to extract placemarks, styles, style maps, and document metadata. Simple installation, configurable namespace and temp directory, with a clean API for reading geographic data.

View on GitHub
Deep Wiki
Context7
v3.1.0

Folder hierarchy, and three bugs that turned up while raising static analysis to its strictest level.

Added

<Folder> is no longer flattened away. Placemarks are collected with a flat //kml:Placemark query, which is what lets the parser find them at any depth, and also what made the folders invisible. A document organised into folders came back as one undifferentiated list, and the grouping the author put there, usually the layer names in a Google My Maps export, was gone.

Every placemark now carries the path of the folders containing it:

[
    'name' => 'Lago Blu',
    'description' => 'A lake',
    'folder' => ['Piemonte', 'Laghi'],
    'type' => 'Point',
    'coordinates' => [...],
]

Outermost first, and an empty array for a placemark sitting directly under the Document. The list itself stays flat, so nothing is duplicated and grouping stays a one-liner:

collect($parser->getPlacemarks())
    ->groupBy(fn (array $placemark) => implode('/', $placemark['folder']));

A Folder with no <name> contributes an empty string rather than being skipped, so the length of the path always matches the real nesting depth. Otherwise ['Piemonte'] would mean both "one level deep" and "two levels deep inside an unnamed folder".

toGeoJson() carries the path into properties, but only for a placemark that actually is in a folder. A flat document produces byte-identical GeoJSON to 3.0.

Fixed

An unreadable file reported the wrong problem. file_get_contents() returns false when a file exists but cannot be opened: a permissions problem, a file mid-write, a broken symlink. That false was passed straight into loadFromString(), became the empty string, and surfaced as XML parsing error: String could not be parsed as XML. That points at the content. The content was fine, the file could not be read. Now Unable to read KML file: <path>, distinct from the existing not-found error.

xpath() and preg_split() failures were iterated. Both return false on failure and both were fed straight to foreach, at five call sites across the parser, the validator and the coordinate trait. All now fall back to an empty array.

A non-numeric archive limit silently turned the limit off. The KMZ ceilings added in 3.0 were read with a blind (int) cast, and (int) 'plenty' is 0, which is the documented way to disable a limit. So a typo in the config removed the protection instead of being rejected, which is the worst possible failure direction for that particular setting. A value that is not a number now falls back to the documented default.

Internal

PHPStan raised from level 5 to level 9. Level 5 let the whole public surface through as bare array, which told an IDE nothing and let no analysis catch a caller reading a key that is never set, such as coordinates on a MultiGeometry.

Every getter is now typed as precisely as it honestly can be, with the coordinate shapes declared once and imported where they are used. A placemark genuinely is a heterogeneous map, and claiming otherwise would be a fiction the analyser then enforces on everyone; typed objects remain separate, breaking work.

Reached with the baseline still empty, no [@phpstan-ignore](https://github.com/phpstan-ignore) comments, no inline [@var](https://github.com/var) overrides, and no casts or widened signatures added to quiet the analyser. The GeoJSON conversion is narrowed with real runtime checks instead, so a hand-built or partly malformed geometry array now returns null or 0.0 for the bad part rather than raising a TypeError.

The test suite went from 79 tests to 91.

Upgrading from 3.0

composer update. Nothing was removed and no message changed.

One thing to check: getPlacemarks() entries gained the folder key. Additive, but a test comparing a whole placemark array with === or Pest's toBe() will notice the extra key. Reading individual keys is unaffected.

v1.0.2

This release introduces key foundational features for the KML parser:

  • GeometryType and RequiredElement enums to represent geometry types and required XML elements.
  • KmlException, KmlParserException, and KmzExtractorException for more expressive and structured error handling.
  • KmlValidator class to perform pre-validation of KML content before XML parsing.
  • Integration of the validator into KmlParser::loadFromString().

These changes improve robustness and prepare the parser for more advanced validation and error reporting.

v1.0.0

⚠️ First Release Disclaimer

This package is in its early stages. Support for the KML format is still evolving as I continue to explore its structure and variations. Feedback and contributions are welcome!

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.
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc