A modern, feature-rich Laravel package for managing addresses with geocoding, validation, caching, and spatial operations. Perfect for e-commerce, CRM systems, and any application requiring robust address management.
- 🔗 Polymorphic Relationships - Attach addresses to any model
- 🌍 Geocoding Support - Google Maps, OpenStreetMap, HERE APIs
- ✅ Address Validation - Postal codes, phone numbers, email validation
- 🗺️ Spatial Operations - Distance calculations, geofencing, bounding boxes
- ⚡ Smart Caching - Multi-level caching for performance
- 🔒 Security Features - Data masking, GDPR compliance, encryption
- 📊 Bulk Operations - Efficient mass address management
- 🎯 Multiple Address Types - Home, work, billing, shipping addresses
- 📱 Mobile Optimized - Responsive design considerations
- 🧪 Comprehensive Testing - 100% test coverage with Pest
- PHP: 7.4, 8.0, 8.1, 8.2, 8.3, 8.4+
- Laravel: 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0+
- Database: MySQL 5.7+, PostgreSQL 10+, SQLite 3.8+
composer require awalhadi/addressablephp artisan vendor:publish --provider="Awalhadi\Addressable\Providers\AddressableServiceProvider"php artisan migrate<?php
namespace App\Models;
use Awalhadi\Addressable\Traits\Addressable;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
use Addressable;
// Your existing model code...
}$user = User::find(1);
$address = $user->addresses()->create([
'type' => 'home',
'label' => 'My Home',
'given_name' => 'John',
'family_name' => 'Doe',
'organization' => 'Acme Corp',
'phone' => '+1-555-123-4567',
'email' => 'john@example.com',
'street' => '123 Main Street',
'street_2' => 'Apt 4B',
'city' => 'New York',
'state' => 'NY',
'postal_code' => '10001',
'country_code' => 'US',
'latitude' => 40.7128,
'longitude' => -74.0060,
'is_primary' => true,
'is_billing' => false,
'is_shipping' => true,
]);// Get all addresses
$addresses = $user->addresses;
// Get primary address
$primaryAddress = $user->primaryAddress();
// Get addresses by type
$homeAddresses = $user->addresses()->ofType('home')->get();
$billingAddresses = $user->addresses()->isBilling()->get();
// Get addresses within radius
$nearbyAddresses = $user->addresses()
->withCoordinates()
->get()
->filter(fn($address) => $address->isWithinRadius(40.7128, -74.0060, 10));| Property | Type | Description |
|---|---|---|
id |
UUID | Primary key |
addressable_type |
string | Polymorphic model class |
addressable_id |
UUID | Polymorphic model ID |
type |
string | Address type (home, work, billing, shipping) |
label |
string | Custom label |
given_name |
string | First name |
family_name |
string | Last name |
organization |
string | Company name |
phone |
string | Phone number |
email |
string | Email address |
street |
string | Street address |
street_2 |
string | Secondary address line |
city |
string | City |
state |
string | State/province |
postal_code |
string | Postal/ZIP code |
country_code |
string | ISO country code |
neighborhood |
string | Neighborhood |
district |
string | District |
latitude |
decimal | Latitude coordinate |
longitude |
decimal | Longitude coordinate |
is_primary |
boolean | Primary address flag |
is_billing |
boolean | Billing address flag |
is_shipping |
boolean | Shipping address flag |
is_verified |
boolean | Verification status |
metadata |
json | Additional data |
verified_at |
timestamp | Verification timestamp |
// Get full name
$address->full_name; // "John Doe"
// Get formatted address
$address->full_address; // "123 Main Street, Apt 4B, New York, NY 10001, US"
// Get country name
$address->country_name; // "United States"
// Get formatted phone
$address->formatted_phone; // "(555) 123-4567"
// Get masked phone (for privacy)
$address->masked_phone; // "(555) ***-4567"
// Get masked email (for privacy)
$address->masked_email; // "j***@example.com"// Filter by type
Address::ofType('home')->get();
// Filter by country
Address::inCountry('US')->get();
// Filter by city
Address::inCity('New York')->get();
// Filter by state
Address::inState('NY')->get();
// Filter by postal code
Address::inPostalCode('10001')->get();
// Only verified addresses
Address::isVerified()->get();
// Only addresses with coordinates
Address::withCoordinates()->get();
// Recent addresses (last 30 days)
Address::recent()->get();// Get all addresses
$user->addresses;
// Get primary address
$user->primaryAddress();
// Get billing address
$user->billingAddress();
// Get shipping address
$user->shippingAddress();
// Check if has addresses
$user->hasAddresses();
// Check if has primary address
$user->hasPrimaryAddress();
// Get addresses by type
$user->getAddressesByType('home');
// Get addresses in country
$user->getAddressesInCountry('US');
// Get addresses within radius
$user->getAddressesWithinRadius($lat, $lng, $radius);
// Create multiple addresses
$user->createManyAddresses([
['type' => 'home', 'street' => '123 Home St'],
['type' => 'work', 'street' => '456 Work Ave'],
]);
// Update multiple addresses
$user->updateManyAddresses([
'home' => ['street' => '789 New Home St'],
'work' => ['street' => '012 New Work Ave'],
]);// Calculate distance between two addresses
$distance = $address1->distanceTo($address2);
// Check if address is within radius
$isNearby = $address->isWithinRadius($lat, $lng, 10);
// Calculate distance using Haversine formula
$distance = $address->calculateDistance($lat, $lng);
// Calculate distance using Vincenty formula (more accurate)
$distance = $address->calculateDistanceVincenty($lat, $lng);
// Check if point is in polygon (geofencing)
$isInside = $address->isPointInPolygon($polygon);
// Create bounding box
$bbox = $address->createBoundingBox($radius);
// Convert decimal to DMS format
$dms = $address->decimalToDMS($latitude);
// Convert DMS to decimal
$decimal = $address->dmsToDecimal($dms);
// Calculate midpoint between two coordinates
$midpoint = $address->calculateMidpoint($lat1, $lng1, $lat2, $lng2);// Validate entire address
$isValid = $address->isValid();
// Get validation errors
$errors = $address->getValidationErrors();
// Validate postal code
$isValid = $address->validatePostalCode();
// Validate phone number
$isValid = $address->validatePhoneNumber();
// Validate email
$isValid = $address->validateEmail();
// Validate country code
$isValid = $address->validateCountryCode();
// Format postal code
$formatted = $address->formatPostalCode();
// Format phone number
$formatted = $address->formatPhoneNumber();// Geocode address (get coordinates)
$address->geocode();
// Reverse geocode (get address from coordinates)
$address->reverseGeocode();
// Check if address has coordinates
$hasCoords = $address->hasCoordinates();
// Check if address is complete
$isComplete = $address->isComplete();// Cache address data
$address->cacheAddressData();
// Get cached address data
$cached = $address->getCachedAddressData();
// Clear address cache
$address->clearAddressCache();
// Cache geocoding results
$address->cacheGeocodingResult($result);
// Get cached geocoding result
$cached = $address->getCachedGeocodingResult();
// Clear all related caches
$address->clearAllRelatedCaches();
// Warm cache for addressable
$user->warmAddressCache();The package configuration file (config/addressable.php) provides extensive customization options:
'database' => [
'table' => 'addresses',
'primary_key' => 'id', // 'id' or 'uuid'
'uuid_version' => 4,
'soft_deletes' => true,
'timestamps' => true,
],'types' => [
'default' => 'general',
'available' => [
'home' => 'Home Address',
'work' => 'Work Address',
'billing' => 'Billing Address',
'shipping' => 'Shipping Address',
'general' => 'General Address',
],
],'geocoding' => [
'enabled' => env('ADDRESSABLE_GEOCODING_ENABLED', true),
'provider' => env('ADDRESSABLE_GEOCODING_PROVIDER', 'google'),
'providers' => [
'google' => [
'api_key' => env('GOOGLE_MAPS_API_KEY'),
'enabled' => true,
],
'nominatim' => [
'base_url' => 'https://nominatim.openstreetmap.org',
'enabled' => true,
],
'here' => [
'app_id' => env('HERE_APP_ID'),
'app_code' => env('HERE_APP_CODE'),
'enabled' => false,
],
],
'cache_duration' => 86400, // 24 hours
],'validation' => [
'enabled' => env('ADDRESSABLE_VALIDATION_ENABLED', true),
'strict_mode' => false,
'auto_verify' => false,
'postal_code_validation' => true,
'phone_validation' => true,
'email_validation' => true,
'country_code_validation' => true,
],'caching' => [
'enabled' => env('ADDRESSABLE_CACHING_ENABLED', true),
'store' => env('ADDRESSABLE_CACHE_STORE', 'default'),
'prefix' => 'addressable',
'ttl' => [
'address' => 3600, // 1 hour
'geocoding' => 86400, // 24 hours
'validation' => 7200, // 2 hours
'distance' => 1800, // 30 minutes
],
],- PHP 8.1+
- Composer
- Git
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This package is open-sourced software licensed under the MIT license.
- Documentation: GitHub Wiki
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Laravel team for the amazing framework
- Pest team for the testing framework
- All contributors who helped improve this package
Made with ❤️ by the Laravel community