ijeffro/laravel-cities
Laravel package that provides IATA codes, ISO 3166-3 and country codes for cities worldwide, with a migration generator and seeder to populate a searchable cities table in your Laravel app.
Architecture fit: This package is best leveraged as a Laravel-native reference dataset and validation layer for IATA city codes, country codes, and city lookup—not as a geospatial engine or a replacement for an airport-code authority. The v1.0.0 release is aligned with modern Laravel 12/13 and PHP 8.2+, offering in-memory lookup (find, findOrFail, exists, inCountry, search, options), readonly City objects, a CityCode validation rule, optional Eloquent model/migration/seeder, and Artisan install/seed commands. That is a good fit for travel, logistics, onboarding, address forms, and API validation where a static, local dataset beats an external geocoding API on latency and cost. It is not suitable for real-time geospatial queries, dynamic city administration, or use cases that require airport-level IATA codes rather than city codes.
Integration feasibility: Feasible for a Laravel 12/13 application via Composer and package auto-discovery. The optional database path means teams can start with in-memory lookups and only publish the migration/Eloquent model when joins or admin reporting are needed. The main integration friction is documentation drift: the visible README describes an older Laravel 5 workflow and namespace (ijeffro\Cities), while v1.0.0 release notes specify FLAIRUK\Cities, auto-discovery, renamed code field, and Laravel 12/13 only. Any integration plan must be based on the release notes and actual package source, not the README alone.
Technical risk: The largest risk is low adoption and maintenance confidence: 11 stars, 0 dependents, and a recent major rewrite create uncertainty around long-term support and real-world hardening. The package claims tests and CI, but external validation is minimal. Data freshness is also a risk: IATA/ISO reference data changes periodically, and the package is updated through Composer rather than a live feed. Additional risks include namespace/version migration from older examples, stale documentation causing misconfiguration, ambiguous city/airport expectations, and lack of built-in fallback if a city is missing. MIT licensing is favorable, and the code can be forked or vendored if needed.
Key questions: What is the dataset source, coverage, and update cadence? Are IATA city codes clearly distinguished from airport codes in our product requirements? Does the package include localized/non-Latin city names, aliases, and search normalization? What happens on ambiguous or missing city names—does findOrFail fail hard, and do we need a fallback? Are the published tests sufficient for our critical paths? Which exact release/version will we pin, and what is our fork/upgrade strategy? Do we need the optional database table for joins, reporting, or admin tooling, or is the in-memory API sufficient? How will we validate data quality against official IATA/ISO sources before launch?
Stack fit: Use this package where the stack is Laravel 12/13 on PHP 8.2+ and the need is standardized city-code lookup, validation, and lightweight search. Keep it behind an internal adapter or service interface so product code depends on our own CityLookup contract rather than the vendor facade. Use the in-memory API for request-time validation and autocomplete; use the optional Eloquent model/migration only when we need SQL joins, reporting, or operational tooling. Do not position it as a geocoding, distance, or airport-operations system.
Migration path: Start with a short technical spike in a non-critical branch. Pin the exact Composer version, verify auto-discovery, and confirm the v1.0.0 namespace and API against the release notes. If migrating from older examples, replace ijeffro\Cities references with FLAIRUK\Cities, remove manual provider/alias registration where auto-discovery applies, and account for iso_3166_3 becoming code. Publish config/migration only if the database path is required; otherwise avoid schema changes. Replace hardcoded city lists incrementally with adapter methods, and add tests for valid codes, invalid codes, missing cities, country filtering, and search behavior.
Compatibility: Treat Laravel 12/13 and PHP 8.2+ as the supported baseline for v1.0.0. Older README instructions for Laravel 5 are not a reliable compatibility guide. Validate Composer constraints against the application’s framework and PHP versions, and check transitive dependency risk. If the app is on Laravel 10/11, plan a fork or defer adoption until compatibility is proven. Database compatibility should be tested if using the optional migration, but the in-memory path reduces database-specific risk.
Sequencing: First, define the business need: city-code validation, autocomplete, or reference data. Second, run a spike to verify dataset coverage, API behavior, and test coverage. Third, wrap the package behind an internal adapter and add contract tests. Fourth, integrate into one low-risk workflow—e.g., address validation or internal search—before expanding to booking or customer-facing flows. Fifth, document data provenance, update process, and fallback behavior. Sixth, decide whether to consume, fork, or replace based on the spike and operational review.
Maintenance: Maintenance effort is low if we pin the version and avoid relying on live updates. However, low stars and zero dependents mean we should assume self-service maintenance. Assign an owner, track the upstream repo, monitor releases, and keep a fork/vendor option ready. Since data updates arrive via Composer, schedule periodic review of IATA/ISO changes and re-run validation tests after upgrades. Avoid automatic minor upgrades in production until the adapter contract tests pass.
Support: Community support is likely limited. Troubleshooting will depend on package source, release notes, and our own tests. Common issues will be outdated README instructions, namespace/version confusion, missing cities, ambiguous names, and unexpected validation failures. Provide internal documentation and a runbook: how to verify a code, how to add a fallback, how to inspect the dataset, and how to escalate to a fork if upstream is inactive.
Scaling: The in-memory lookup model is attractive for read-heavy validation and autocomplete because it avoids external API latency and cost. The optional database path supports SQL joins and reporting but adds migration and indexing concerns. Scaling risk is modest for typical city lookup volumes, but benchmark memory and search performance if loading the full dataset per request or in high-concurrency workers. Avoid using this package for geospatial radius queries or real-time location services.
Failure modes: Expect stale data, missing or renamed city codes, ambiguous city-to-airport mappings, validation false negatives, documentation-driven misconfiguration, and upstream abandonment. Hard failures from findOrFail should be wrapped with graceful fallback or user-facing validation. Build a fallback path—manual override, admin correction, or external provider—for critical travel flows. Monitor validation failure rates and missing-city reports after launch.
Ramp-up: Ramp-up is low for Laravel developers familiar with Composer, facades, validation rules, and Eloquent. The main ramp-up cost is product and data literacy: stakeholders must understand that these are IATA city codes, not necessarily airport codes, and that the dataset is static. Provide a short internal guide covering the adapter API, supported Laravel versions, data provenance, update cadence, and fallback procedure. A one-day spike plus contract tests is usually enough to decide whether to leverage, fork, or replace.
How can I help you explore Laravel packages today?