Weave 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

Location Bundle Laravel Package

jul/location-bundle

jul/location-bundle is a Symfony bundle for PHP apps that need location-aware features. It packages reusable services and conventions for integrating geographic data, helping keep location logic organized and out of your core application code.

View on GitHub
Deep Wiki
Context7

Getting Started

Before writing any code, confirm what you are actually installing: jul/location-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no config/location.php to publish, no Eloquent models, no migrations. composer require jul/location-bundle will install it, but Laravel will not boot it, and any attempt to use its entity manager, forms, or DI wiring will fail or require you to bootstrap Symfony components manually. The realistic day-one decision is "use as reference, reimplement the pieces I need" rather than "install and configure."

If you are auditing it as prior art, read in this order:

  • composer.json — Symfony/Doctrine version constraints tell you how stale it is against your PHP version.
  • README.md — map provider configuration and the intended workflow.
  • Entity/ — the location data model you will mirror.
  • DependencyInjection/ and Resources/config/ — how providers and services are wired.
  • Form/ — the input validation contract for address/coordinate capture.

First use case in Laravel — a reusable locations table instead of address columns scattered across users, orders, and stores:

Schema::create('locations', function (Blueprint $table) {
    $table->id();
    $table->string('label')->nullable();
    $table->string('line1');
    $table->string('line2')->nullable();
    $table->string('city');
    $table->string('region')->nullable();
    $table->string('postal_code')->nullable();
    $table->string('country', 2);
    $table->decimal('latitude', 10, 7)->nullable();
    $table->decimal('longitude', 10, 7)->nullable();
    $table->string('geocoded_address')->nullable();
    $table->timestamp('geocoded_at')->nullable();
    $table->timestamps();
});

Attach it to domain records with location_id or a polymorphic locationable relation. That one table, plus a geocoding job, covers most of what the bundle would give you — without the framework mismatch.

Implementation Patterns

Location as a shared entity, not a column sprawl. Mirror the bundle's model shape: address fields + coordinates + optional type/label + a geocode timestamp. When you need categories (warehouse, retail, event venue), add a location_types table or an enum — do not denormalize a string into every location row.

Wrap the provider behind an interface. The bundle's real value is the architectural pattern: a swappable map/geocoding adapter. In Laravel:

interface Geocoder {
    public function geocode(string $address): ?Coordinates;
}

final class Coordinates {
    public function __construct(public float $lat, public float $lng) {}
}

Bind it in AppServiceProvider to a GoogleGeocoder, MapboxGeocoder, or a FakeGeocoder for tests. Controllers, models, and jobs depend on Geocoder, never on a vendor SDK.

Geocode on write, asynchronously. The bundle's forms assume synchronous geocoding during save; that is a bad pattern for an HTTP request. Save the address, dispatch a queued job, store coordinates on success:

class GeocodeLocation implements ShouldQueue
{
    public function __construct(public int $locationId) {}

    public function handle(Geocoder $geocoder)
    {
        $location = Location::findOrFail($this->locationId);
        $coords = $geocoder->geocode($location->fullAddress());
        if ($coords) {
            $location->update([
                'latitude' => $coords->lat,
                'longitude' => $coords->lng,
                'geocoded_at' => now(),
            ]);
        }
    }
}

Cache by normalized address. Geocoding is billed per call. Normalize (trim, lowercase, collapse whitespace, canonicalize country), key the cache on the hash, and store the coordinate pair. This turns a repeated create/update into a free operation and is the single biggest cost lever.

Validation and resource layers. A LocationRequest validating address fields and coordinate ranges (lat −90..90, lng −180..180) plus a LocationResource shaping API responses keeps the model thin and avoids leaking provider response shapes to the front end.

If you genuinely run Symfony, use the bundle natively: register it, configure credentials, and reuse its entities/forms through Doctrine. Do not try to hybridize — pick one framework.

Gotchas and Tips

Framework mismatch is the deal-breaker. With 13 stars and 0 dependents, there is no community troubleshooting this in Laravel. Any time you spend making symfony/form or symfony/doctrine-bridge work inside a Laravel app is time you will spend again on every upgrade. Write the 200 lines yourself.

Do not store coordinates as float. MySQL float loses precision. Use decimal(10,7) for latitude and decimal(10,7) for longitude, and handle null explicitly — a location without coordinates is a valid intermediate state.

Geocoding is unreliable by nature. Addresses are ambiguous, providers return partial matches (city centroid instead of a rooftop), and responses vary between providers. Persist the geocoded string alongside the coordinates so you can detect drift when the address changes and prompt for re-geocoding.

Quotas and terms of service bite at scale. Google, Mapbox, and Nominatim have different caching rules — some forbid storing results indefinitely, others require attribution. Read the ToS before building a permanent cache of provider output, and log provider errors and quota-exhaustion responses so failures surface in observability rather than as silent nulls.

Proximity search is not in this package. "Find the nearest 5 locations" is a database problem. The bundle's model gives you lat/lng but no spatial index. Plan for ST_Distance_Sphere on MySQL 8, PostGIS, or a search index (Meilisearch, Typesense, Algolia) — not for a bundle feature.

Debugging. In Symfony, trace through DI bundle config and the geocoder service. In Laravel, instrument the HTTP call: log the normalized address, the raw provider response, and the stored coordinates. Most "wrong pin" bugs are address normalization or a provider returning the nearest match rather than the exact one.

Extension points worth copying. The bundle's design — entity + type + provider adapter — is the right seam. In Laravel, the equivalents are: a Location model (extend with accessors/relations rather than forking), a Geocoder interface with adapters, and config-driven provider selection (config('services.geocoder.driver')). Those three give you the same swap-providers-on-config-change property the bundle was aiming for.

Treat it as unmaintained-by-default. No dependents means no bug reports, no upstream fixes, and no PHP version bumps applied for you. If you do adopt any of its code (even copied classes), pin the version, add your own tests around the geocoder and coordinate handling, and assign an internal owner for future upgrades.

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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource