multek/laravel-geoaddress
Composer 安装命令:
composer require multek/laravel-geoaddress
包简介
Production-ready polymorphic address system with automatic geocoding for Laravel
README 文档
README
Production-ready polymorphic address system with automatic geocoding, PostGIS geographic queries, and multi-provider support.
Features
- Polymorphic Relationships - Any model can have multiple addresses
- Automatic Geocoding - Background job processing with Google Maps API (or other providers)
- PostGIS Integration - Geographic queries and spatial indexing
- Brazilian Address Format - Street, number, complement, neighbourhood, city, state, postal code
- Smart Geocoding Control -
geocoding_enabledflag for address types that don't need coordinates - Trust-Based Coordinate Input - Pass lat/lng to skip geocoding API calls
- Multiple Address Types - Home, work, billing, shipping, delivery with custom nicknames
- Customer Contact Information - Store recipient/contact details with each address
- Flexible Metadata - JSON storage for edge cases and custom data
- Multi-Provider Geocoding - Support for Google Maps, Nominatim (free), Mapbox
- Smart Re-geocoding - Automatically re-geocodes when address fields change (unless coordinates provided)
Requirements
- PHP 8.2+
- Laravel 11.0+
- PostgreSQL with PostGIS extension (required)
Note: This package is designed exclusively for PostgreSQL with PostGIS. It uses PostGIS geography types for storing coordinates and spatial indexing, enabling powerful geographic queries like radius searches. MySQL and SQLite are not supported.
Installation
composer require multek/laravel-geoaddress
Quick Install
The easiest way to install is using the install command:
php artisan geoaddress:install
This will:
- Check and enable PostGIS extension if needed
- Publish the configuration file
- Publish and run migrations
Manual Installation
If you prefer to install manually:
# Enable PostGIS (if not already enabled) psql -d your_database -c "CREATE EXTENSION IF NOT EXISTS postgis;" # Publish config and migrations php artisan vendor:publish --tag=geoaddress-config php artisan vendor:publish --tag=geoaddress-migrations php artisan migrate
Environment Variables
# Geocoding Provider: google, nominatim, mapbox GEOADDRESS_PROVIDER=google # Fallback Provider (optional) - used if primary fails GEOADDRESS_FALLBACK_PROVIDER=nominatim # Google Maps (if using google provider) GOOGLE_MAPS_API_KEY=your-api-key-here # Nominatim (if using nominatim provider - optional custom URL) NOMINATIM_URL=https://nominatim.openstreetmap.org NOMINATIM_USER_AGENT=YourAppName # Mapbox (if using mapbox provider) MAPBOX_ACCESS_TOKEN=your-access-token # Queue settings (optional) GEOADDRESS_QUEUE_CONNECTION=redis GEOADDRESS_QUEUE_NAME=geocoding
Tip: For production, we recommend using Google Maps as primary provider and Nominatim as fallback. Google is more accurate, especially for Brazilian addresses, while Nominatim provides free fallback if Google is unavailable.
Usage
Make a Model Addressable
use Multek\LaravelGeoaddress\Traits\Addressable; class Customer extends Model { use Addressable; }
Creating Addresses
// Delivery address - Will be geocoded automatically $customer->addAddress([ 'type' => 'delivery', 'is_primary' => true, 'street' => 'Avenida Paulista', 'number' => '1578', 'neighbourhood' => 'Bela Vista', 'city' => 'Sao Paulo', 'state' => 'SP', 'postal_code' => '01310-200', 'country_code' => 'BR', ]); // Billing address - No geocoding $customer->addAddress([ 'type' => 'billing', 'geocoding_enabled' => false, 'street' => 'Rua Fiscal', 'number' => '100', 'city' => 'Sao Paulo', 'state' => 'SP', 'country_code' => 'BR', ]); // Delivery from map picker - Skip geocoding API ("trust me") $customer->addAddress([ 'type' => 'delivery', 'street' => 'Avenida Paulista', 'number' => '1578', 'city' => 'Sao Paulo', 'state' => 'SP', 'country_code' => 'BR', 'latitude' => -23.561414, 'longitude' => -46.656689, ]);
Working with Addresses
// Get all addresses $addresses = $customer->addresses; // Get primary address $primary = $customer->primaryAddress(); // Get formatted address string $formatted = $customer->full_address; // Set primary address $customer->setPrimaryAddress($addressId); // Get only geocoding-enabled addresses $physical = $customer->geocodableAddresses;
Query Scopes
use Multek\LaravelGeoaddress\Models\Address; $geocoded = Address::geocoded()->get(); $failed = Address::failed()->get(); $primary = Address::primary()->get(); $needsGeocoding = Address::needsGeocoding()->get(); $geocodingEnabled = Address::geocodingEnabled()->get();
Geographic Queries (PostGIS)
use MatanYadaev\EloquentSpatial\Objects\Point; // Find addresses within 5km radius $nearby = Address::geocodingEnabled() ->whereRaw( 'ST_DWithin(coordinates::geography, ST_MakePoint(?, ?)::geography, ?)', [$longitude, $latitude, 5000] ) ->get();
Listening to Events
use Multek\LaravelGeoaddress\Events\AddressGeocoded; // In a listener or EventServiceProvider Event::listen(AddressGeocoded::class, function ($event) { // $event->address contains the geocoded address });
Geocoding Design Philosophy
The geocoding system uses a two-layer approach to decide when and how coordinates are set.
Layer 1: geocoding_enabled (Persistent — stored in DB)
Controls whether an address should ever have coordinates.
| Value | Meaning | Example |
|---|---|---|
true (default) |
Physical address — should have coordinates | delivery, home, work |
false |
Non-physical address — coordinates are always null | billing, PO Box, virtual |
When geocoding_enabled is false, the system actively clears coordinates, geocoded_at, and any geocoding error data on every save. This is enforced both in the model's saving callback and in the observer's updating event.
Layer 2: trustProvidedCoordinates (Transient — per request only)
Controls whether the system should call a geocoding API or trust what was provided. This flag is set automatically when you pass latitude and longitude in the address data — you never set it manually.
| Scenario | Flag | What happens |
|---|---|---|
addAddress() without lat/lng |
false |
Geocoding job is dispatched |
addAddress() with lat/lng |
true |
Coordinates are used directly, no API call |
update() changes address fields, no lat/lng |
false |
Old coordinates are cleared, new geocoding job dispatched |
update() changes address fields, with lat/lng |
true |
New coordinates are used directly, no API call |
update() changes non-address fields (notes, metadata) |
false |
Nothing happens — existing coordinates are preserved |
Lifecycle: Converting Address Types
When you change geocoding_enabled on an existing address:
Billing to Delivery (false → true):
$address->update(['geocoding_enabled' => true, 'type' => 'delivery']); // → Geocoding job is dispatched (address now needs coordinates) // Or, if you already have coordinates: $address->update([ 'geocoding_enabled' => true, 'type' => 'delivery', 'latitude' => -23.561414, 'longitude' => -46.656689, ]); // → Coordinates are stored directly, no API call
Delivery to Billing (true → false):
$address->update(['geocoding_enabled' => false, 'type' => 'billing']); // → Coordinates, geocoded_at, and geocoding errors are all cleared
Internal Flow Summary
User calls addAddress() or update()
│
├─ geocoding_enabled = false?
│ └─ Clear all coordinate data → DONE
│
├─ latitude + longitude provided?
│ ├─ Set trustProvidedCoordinates = true
│ ├─ Store Point coordinates (PostgreSQL)
│ ├─ Set geocoded_at timestamp
│ └─ Fire AddressGeocoded event → DONE (no API call)
│
└─ No coordinates provided?
├─ Address fields changed? → Clear old coords, dispatch GeocodeAddress job
├─ geocoding_enabled just turned on? → Dispatch GeocodeAddress job
└─ Nothing relevant changed? → DONE (keep existing coords)
Geocoding Providers
Available Providers
| Provider | Pros | Cons |
|---|---|---|
| Google Maps | Most accurate, great for Brazil | Requires API key, costs money |
| Nominatim | Free, no API key needed | Less accurate, rate limited (1 req/sec) |
| Mapbox | Good accuracy, generous free tier | Requires access token |
Fallback Provider
If the primary provider fails (API down, rate limited, etc.), the system can automatically try a fallback provider:
GEOADDRESS_PROVIDER=google GEOADDRESS_FALLBACK_PROVIDER=nominatim
Custom Providers
use Multek\LaravelGeoaddress\Services\GeocoderFactory; $factory = app(GeocoderFactory::class); // Use a specific provider $nominatim = $factory->make('nominatim'); $google = $factory->make('google'); $mapbox = $factory->make('mapbox'); // Extend with custom provider $factory->extend('custom', CustomGeocoder::class);
Testing
composer test
License
MIT License
multek/laravel-geoaddress 适用场景与选型建议
multek/laravel-geoaddress 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 202 次下载、GitHub Stars 达 1, 最近一次更新时间为 2025 年 12 月 05 日, 在 PHP 生态内属于活跃度较高的组件。
它主要适用于以下技术方向: 「geocoding」 「address」 「laravel」 「postgis」 「polymorphic」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。
我们在过去多个企业项目中使用过 multek/laravel-geoaddress 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 multek/laravel-geoaddress 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
与 multek/laravel-geoaddress 相关的其它包
同方向 / 同关键字的高下载量 PHP Composer 包推荐,方便对比选型:
Maps in minutes. Powered by the Google Maps API.
Redirects TYPO3 visitors automatic or with a suggestlink to another language and/or root page.
Yii2 map input widget. Allows you to select geographcal coordinates via a human-friendly inteface.
GISCO Geocoding Provider for Geocoder PHP.
Module adding custom shipping attribute for what3words address
Laravel integration for Nominatim Geocoding API Client
统计信息
- 总下载量: 202
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 9
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2025-12-05