Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Geodistance Laravel Package

jackpopp/geodistance

Laravel/PHP package to calculate geographic distances between coordinates. Supports common formulas and helpers to get miles/kilometers between points, useful for proximity search, radius filtering, and location-based features in apps.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require jackpopp/geodistance
    

    Publish the config file (if needed):

    php artisan vendor:publish --provider="Jackpopp\GeoDistance\GeoDistanceServiceProvider"
    
  2. Model Integration Add HasGeoDistance trait to your Eloquent model:

    use Jackpopp\GeoDistance\HasGeoDistance;
    
    class Restaurant extends Model
    {
        use HasGeoDistance;
    
        protected $coordinates = 'latitude,longitude'; // Define your coordinate columns
    }
    
  3. First Query Find locations within 10km of a point (e.g., 40.7128° N, -74.0060° W):

    $nearby = Restaurant::near(40.7128, -74.0060, 10)->get();
    

Key Files to Review

  • config/geodistance.php (for distance unit defaults, precision, etc.)
  • src/HasGeoDistance.php (trait methods and query builder extensions)
  • src/GeoDistanceServiceProvider.php (service registration)

Implementation Patterns

Common Workflows

1. Radius Queries

// Basic radius search (default: kilometers)
$results = Model::near($lat, $lng, $radius)->get();

// With unit specification
$results = Model::near($lat, $lng, $radius, 'miles')->get();

2. Ordering by Distance

$sorted = Model::near($lat, $lng, 50)
    ->orderByDistance()
    ->get();

3. Combining with Other Queries

$results = Model::near($lat, $lng, 20)
    ->where('category', 'pizza')
    ->whereOpen()
    ->get();

4. Custom Coordinate Columns

class Store extends Model
{
    use HasGeoDistance;

    protected $coordinates = 'lat,long'; // Custom column names
}

5. Distance Calculation Without Querying

$distance = Model::distanceTo($lat, $lng); // Returns distance in configured unit

Integration Tips

Database Optimization

  • Ensure your coordinate columns are indexed:
    Schema::table('restaurants', function (Blueprint $table) {
        $table->decimal('latitude', 10, 8)->index();
        $table->decimal('longitude', 11, 8)->index();
    });
    

Caching Results

  • Cache frequent radius queries to reduce database load:
    $cacheKey = "nearby_{$lat}_{$lng}_{$radius}";
    $results = Cache::remember($cacheKey, now()->addHours(1), function () use ($lat, $lng, $radius) {
        return Model::near($lat, $lng, $radius)->get();
    });
    

Geohashing for Performance

  • For high-traffic apps, consider geohashing coordinates to optimize spatial queries:
    // Add a geohash column and index it
    $table->string('geohash')->index();
    

Unit Testing

  • Mock the GeoDistance calculations in tests:
    $model = new Model();
    $this->partialMock(GeoDistance::class, ['haversine'])
        ->shouldReceive('haversine')
        ->with($lat, $lng, $model->latitude, $model->longitude)
        ->andReturn(5.5);
    

Gotchas and Tips

Pitfalls

1. Precision Issues

  • Problem: Floating-point precision errors can cause inaccurate distance calculations.
  • Fix: Use protected $precision = 6; in your model or config to limit decimal places.

2. Unit Confusion

  • Problem: Default unit is kilometers; forget to specify miles or meters in queries.
  • Fix: Always explicitly set the unit if not using the default:
    Model::near($lat, $lng, 5, 'miles')->get();
    

3. Coordinate Order

  • Problem: Mixing up latitude/longitude order in queries.
  • Fix: Stick to (latitude, longitude) convention or document your model’s order.

4. Database Driver Limitations

  • Problem: Some databases (e.g., SQLite) lack spatial extensions, forcing pure PHP calculations.
  • Fix: Test on your target database; SQLite may return slower results for large datasets.

5. Time Zone Quirks

  • Problem: Distance calculations assume a spherical Earth; edge cases near poles may be off.
  • Fix: For high-precision needs, consider a dedicated spatial database like PostgreSQL with PostGIS.

Debugging Tips

1. Log Raw Queries

Enable Laravel’s query logging to inspect generated SQL:

DB::enableQueryLog();
Model::near($lat, $lng, 10)->get();
dd(DB::getQueryLog());

2. Validate Coordinates

Ensure coordinates are within valid ranges:

if (!($lat >= -90 && $lat <= 90) || !($lng >= -180 && $lng <= 180)) {
    throw new \InvalidArgumentException("Invalid coordinates");
}

3. Check for NULL Values

NULL coordinates will break distance calculations. Add guards:

if (is_null($model->latitude) || is_null($model->longitude)) {
    return Model::query()->whereNull('latitude');
}

Extension Points

1. Custom Distance Formula

Override the default Haversine formula in your model:

use Jackpopp\GeoDistance\Contracts\DistanceCalculator;

class CustomModel extends Model implements DistanceCalculator
{
    use HasGeoDistance;

    public function distance($lat1, $lon1, $lat2, $lon2)
    {
        // Implement your custom logic (e.g., Vincenty formula)
    }
}

2. Add Distance to Serialized Output

Extend the model’s toArray() or toJson():

public function toArray()
{
    return array_merge(parent::toArray(), [
        'distance' => $this->distanceTo($lat, $lng),
    ]);
}

3. Create a Radius Scope

Add reusable scopes to your model:

public function scopeWithinCity($query, $lat, $lng)
{
    return $query->near($lat, $lng, 50); // 50km radius
}

4. Integrate with Laravel Scout

For full-text + geo search, combine with Scout:

use Jackpopp\GeoDistance\ScoutExtensions\HasGeoScout;

class Product extends Model
{
    use HasGeoScout;

    public function toSearchableArray()
    {
        return [
            'name' => $this->name,
            'coordinates' => [$this->latitude, $this->longitude],
        ];
    }
}
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity