Installation
composer require baks-dev/users-geocode
php artisan vendor:publish --provider="BaksDev\UsersGeocode\UsersGeocodeServiceProvider" --tag="migrations"
php artisan migrate
Run Asset Installation
php artisan baks:assets:install
(Ensures config, migrations, and views are published to your project.)
First Use Case: Geocoding a User
Attach the HasGeocode trait to your User model:
use BaksDev\UsersGeocode\Traits\HasGeocode;
class User extends Authenticatable
{
use HasGeocode;
// ...
}
Then geocode an address:
$user = User::find(1);
$user->geocode('1600 Amphitheatre Parkway, Mountain View, CA');
$user->save(); // Triggers geocoding via model observer
config/users-geocode.php (API keys, default settings).app/Models/User.php for trait integration.database/migrations/*_create_users_geocode_table.php (if customizing).vendor/baks-dev/users-geocode/src/Geocoder/ (for service details).Geocoding Addresses
// Manual geocoding (bypasses observer)
$user->geocode('Address string', ['provider' => 'google']); // Uses config default if omitted
// Batch geocode existing users
User::whereNull('latitude')->chunk(50, function ($users) {
foreach ($users as $user) {
$user->geocode($user->address);
}
});
Reverse Geocoding
$user = User::find(1);
$user->reverseGeocode(); // Returns formatted address from lat/lng
Querying by Location
// Nearby users (radius in km)
$nearby = User::near(37.422, -122.084, 10)->get();
// Bounding box
$inArea = User::withinBounds(37.422, -122.084, 37.774, -121.880)->get();
$this->app->bind(\BaksDev\UsersGeocode\Contracts\Geocoder::class, function ($app) {
return new CustomGeocoder($app['config']['services.custom_geocoder']);
});
event(new GeocodingStarted($user, '123 Main St'));
'cache' => [
'enabled' => true,
'ttl' => 86400, // 24h in seconds
],
config/users-geocode.php:
'providers' => [
'primary' => 'google',
'fallback' => ['openstreetmap', 'mapbox'],
],
API Key Management
config/users-geocode.php is not secure. Use Laravel’s .env:
GEOCODER_GOOGLE_API_KEY=your_key_here
\BaksDev\UsersGeocode\Facades\Geocoder::stats();
Observer Conflicts
HasGeocode. If you have custom observers:
observables() in your AppServiceProvider to merge observers:
protected $observables = [
User::class => [
\BaksDev\UsersGeocode\Observers\UserGeocodeObserver::class,
\App\Observers\CustomUserObserver::class,
],
];
Database Schema Assumptions
latitude, longitude, and address columns. Customize migrations if your schema differs:
Schema::table('users', function (Blueprint $table) {
$table->decimal('lat', 10, 8)->nullable()->after('address');
$table->decimal('lng', 11, 8)->nullable()->after('lat');
});
Rate Limiting
$users->each(function ($user) {
sleep(1); // 1-second delay between requests
$user->geocode($user->address);
});
Enable Logging: Add to config/users-geocode.php:
'debug' => env('APP_DEBUG', false),
Logs API responses to storage/logs/geocode.log.
Test Locally: Use the mock provider for testing:
config(['users-geocode.providers.primary' => 'mock']);
Mock responses are in config/users-geocode/mock_responses.php.
Custom Geocoder
Implement \BaksDev\UsersGeocode\Contracts\Geocoder:
class CustomGeocoder implements Geocoder
{
public function geocode(string $address): array
{
// Your logic here
return ['lat' => 1.0, 'lng' => 2.0];
}
}
Override Default Address Field Publish the config and modify:
'address_field' => 'custom_address_column', // Default: 'address'
Add Custom Metadata
Extend the geocode method to store additional data:
$user->geocode('Address', ['place_id' => 'ChIJD7fiBh9u5kcRYJSMaMO5KF8']);
Then add a column to your users table (e.g., place_id) and update the migration.
Webhook Integration Trigger actions post-geocode via events:
\BaksDev\UsersGeocode\Events\GeocodingCompleted::class => [
\App\Listeners\UpdateUserLocation::class,
],
How can I help you explore Laravel packages today?