topukhan/geokit

A clean and extensible geocoding toolkit for Laravel

Installs: 4

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/topukhan/geokit

v2.0.0 2025-11-07 14:04 UTC

This package is auto-updated.

Last update: 2025-12-07 14:52:15 UTC


README

A clean and extensible geocoding toolkit for Laravel that supports multiple providers with automatic fallback handling.

Features

  • 🌍 Multiple Providers: Geoapify (premium) and Nominatim (free) support
  • 🔄 Smart Fallback: Automatically falls back to next provider if one fails
  • 🛡️ Quota Protection: Detects API quota issues and handles them gracefully
  • 🎯 Consistent Results: Unified response format across all providers
  • Laravel Integration: Facade and Service injection support
  • 🔧 Configurable: Easy configuration and extensible architecture

Installation

Install the package via Composer:

composer require topukhan/geokit

Publish the configuration file:

php artisan vendor:publish --tag=geokit-config

Configuration

Environment Variables

Add these variables to your .env file:

# Optional: Your Geoapify API key (if you have one)
GEOKIT_GEOAPIFY_KEY=your_geoapify_api_key_here

# Optional: Request timeout in seconds (default: 30)
GEOKIT_TIMEOUT=30

# Optional: Maximum results per search (default: 10)
GEOKIT_MAX_RESULTS=10

# Optional: User agent for API requests
GEOKIT_USER_AGENT="Your App Name/1.0"

Config File

The config/geokit.php file allows you to customize:

  • Provider order and selection
  • API keys
  • Request timeouts
  • Result limits

Usage

Using the Facade

use Topukhan\Geokit\Facades\Geokit;

$response = Geokit::search('Tongi, Dhaka');

// Check if we got results
if ($response->hasResults()) {
    echo "Found {$response->count()} results\n";
    
    // Get the first result
    $first = $response->first();
    echo "Best match: {$first->formatted}\n";
    echo "Coordinates: {$first->lat}, {$first->lng}\n";
    echo "Provider: {$first->provider}\n";
    
    // Access address components
    if (isset($first->components['city'])) {
        echo "City: {$first->components['city']}\n";
    }
}

// Check if fallback was used
if ($response->usedFallback) {
    echo "Used fallback providers\n";
}

// See which providers failed
if (!empty($response->failedProviders)) {
    echo "Failed providers: " . implode(', ', $response->failedProviders) . "\n";
}

Using Service Injection

use Topukhan\Geokit\Services\AddressResolverService;

class LocationController extends Controller
{
    public function search(Request $request, AddressResolverService $geokit)
    {
        $response = $geokit->search($request->input('query'));
        
        return response()->json($response->toArray());
    }
}

Response Format

All searches return a GeocodeResponse object with this structure:

GeocodeResponse {
    +query: string           // Original search query
    +results: array         // Array of GeocodeResult objects
    +usedFallback: bool     // Whether fallback providers were used
    +failedProviders: array // Names of providers that failed
}

Each result in the results array is a GeocodeResult object:

GeocodeResult {
    +provider: string    // Provider name (e.g., 'geoapify', 'nominatim')
    +formatted: string   // Full formatted address
    +lat: float         // Latitude
    +lng: float         // Longitude
    +components: array  // Address components (city, state, country, etc.)
}

Example Response

{
    "query": "Tongi, Dhaka",
    "results": [
        {
            "provider": "geoapify",
            "formatted": "Tongi, Gazipur District, Dhaka Division, Bangladesh",
            "lat": 23.8896,
            "lng": 90.3961,
            "components": {
                "city": "Tongi",
                "district": "Gazipur District", 
                "state": "Dhaka Division",
                "country": "Bangladesh",
                "country_code": "BD"
            }
        }
    ],
    "usedFallback": false,
    "failedProviders": []
}

Provider Details

Geoapify

  • Type: Premium (requires API key)
  • Quota: Varies by plan
  • Accuracy: High
  • Coverage: Global

Nominatim

  • Type: Free (no API key required)
  • Quota: Rate limited
  • Accuracy: Good
  • Coverage: Global (OpenStreetMap data)

Error Handling

The package handles various error scenarios automatically:

  • Invalid API Keys: Automatically falls back to next provider
  • Quota Exceeded: Detects quota issues and skips provider
  • Network Timeouts: Respects configured timeout limits
  • Rate Limits: Handles rate limiting gracefully

Extending with New Providers

To add a new geocoding provider:

  1. Create a new class implementing GeocodingDriverInterface
  2. Add it to the service provider's provider mapping
  3. Update the configuration file

Example:

use Topukhan\Geokit\Contracts\GeocodingDriverInterface;

class GoogleGeocoder implements GeocodingDriverInterface
{
    public function getName(): string
    {
        return 'google';
    }
    
    // Implement other interface methods...
}

Requirements

  • PHP 8.2+
  • Laravel 10.0+

License

This package is open-sourced software licensed under the MIT license.