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

Laravel Istat Geography Laravel Package

plin-code/laravel-istat-geography

Laravel package for Italian ISTAT geography data, providing regions, provinces, and municipalities (comuni) ready to use in your app. Simple Eloquent integration for addresses, filters, and location-based features.

View on GitHub
Deep Wiki
Context7

Getting Started

This package gives you Italian geographical data (regions, provinces, municipalities/CAP boundaries) as Eloquent models and migrations, so you don't hand-roll your own regions/provinces tables.

  1. Install and migrate

    composer require plin-code/laravel-istat-geography
    php artisan vendor:publish --tag="istat-geography-config"   # inspect config before migrating
    php artisan migrate
    

    Laravel 12 or 13 required.

  2. Decide your table and model names first. As of v1.5.0 the tables config genuinely renames tables: the base migration creates the configured names and the package models use them. Set them before running php artisan migrate — changing the keys later does not rename anything that already exists. Likewise, if you want your own model classes (with extra scopes, casts, or traits), configure them under models.

  3. Load the data. Use the geography:* artisan commands: geography:download-cap fetches CAP boundary data (default output storage/app/cap-boundaries.geojson — check --help), and the import command consumes it. Run php artisan geography:download-cap then the import, or wire both into a seeder/deploy script.

  4. First useful use case: an address form. A region select, a province select filtered by region via $region->provinces(), and a municipality select filtered by province — all backed by real ISTAT data instead of a hardcoded array.

If your editor/agent supports Laravel Boost, the package now ships resources/boost/guidelines/core.blade.php, which teaches the agent about the models, tables, relations, geography:* commands and config keys. That's the fastest way to stop an agent from inventing its own regions table. laravel/boost is suggested only — nothing breaks without it.

Implementation Patterns

Relations over manual queries. Use provinces(), region(), municipalities(), province(). Since v1.5.0 these resolve through the classes configured under models, with the same foreign keys as before — so swapping in your own model classes does not break the relation graph.

Custom models via config, not forks. Point models at your own classes and add scopes/casts there. Remember a $table property set on your own model still takes precedence over the config — useful for one-off tables, a footgun if you're inconsistent.

Eager-load for selects. Building a nested region → province → municipality form is the classic N+1 trap:

$regions = Region::with('provinces.municipalities')->get();

For large datasets, prefer a lazy endpoint that returns provinces for a chosen region.

Seeding and CI. Keep data loading in a dedicated seeder or deploy step, not in the base migration. The geography dataset is large; you don't want it re-imported on every migrate:fresh in tests — use a small fixture or RefreshDatabase with a subset.

Multi-tenant / multi-instance table names. The tables config makes it viable to run the package against differently named tables per connection, but only if the config is resolved before migration runs. For per-tenant setups, consider a separate connection + config set rather than renaming after the fact.

CAP boundaries. geography:download-cap writes GeoJSON to storage/app/cap-boundaries.geojson by default (the --help output and README now agree on this). Store the file outside the repo, and re-download on deploy or cache it in your artifact pipeline rather than committing large GeoJSON.

Gotchas and Tips

  • Renaming tables after the fact does nothing. v1.5.0's tables support is read at migration and model-resolution time, not a migration of existing data. Treat table names as a pre-migration decision. If you already migrated with defaults, write your own rename migration or re-run migrate:fresh before you have real data.
  • $table on your model wins over config. Great escape hatch, easy to forget during a rename — audit custom models when you change the tables keys.
  • Relations changed in 1.5.0. If you previously relied on relations returning the package's default classes (e.g. type-hinting PlinCode\...\Province in a closure or instanceof check), configure models accordingly or loosen the type hints. Foreign keys are unchanged, so queries still work.
  • Guzzle is no longer a dependency. The package uses Laravel's Http facade, so Guzzle comes from your app (7 on Laravel 12; 7 or 8 on Laravel 13). If you had a transitive reliance on the package pinning Guzzle, verify your own constraint — especially before jumping to Laravel 13.
  • Debugging relations returning the wrong class: check config('istat-geography.models') and clear config cache (php artisan config:clear) after edits. Config-cached deploys are the usual culprit.
  • Debugging empty selects: confirm the data was actually imported (row counts on the region/province tables) before suspecting relations; the download step and the import step are separate.
  • Defaults unchanged, no new migration in 1.5.0 — the upgrade is safe to drop into an existing app. Just don't expect table renaming to apply retroactively.
  • Extension points: models and tables config, your own model classes with $table and custom relations, and the Boost guidelines file as a reference for what the package expects an agent to know.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core
nodisrupt/laravel-agent
sierratecnologia/media-manager