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

Map Address Laravel Package

naif/map_address

A Laravel/PHP package for working with map addresses, providing a simple, configurable way to integrate address lookup and location mapping into your application. It offers a clean API for handling address data and adding location-aware features to PHP projects.

View on GitHub
Deep Wiki
Context7

Getting Started

naif/map_address is a Nova form field that renders a Google Map with a draggable marker, reverse-geocodes the pin position, and returns a formatted street address as the field value.

Viability check first. Last release was January 2019 (Nova 1.x era, Vue 2 assets, Laravel Mix build). Nova 4/5 moved to Vue 3 and a different asset pipeline, so expect the field's JavaScript not to load on a modern Nova install. Before writing any code, open the repo and check: (a) the composer.json Nova constraint, (b) src/MapAddress.php for the actual fluent option names, (c) resources/js/field.js for which Google APIs it calls. If you're on Nova 3+, plan from the start on vendoring/forking it rather than composer require.

Minimal setup

  1. Install into a Nova app:
composer require naif/map_address
php artisan vendor:publish --provider="Naif\MapAddress\FieldServiceProvider"
  1. Create storage on the model. Decide now whether the attribute stores the address string, the coordinates, or both — the field only persists whatever value it assigns:
Schema::table('stores', function (Blueprint $table) {
    $table->string('address')->nullable();
    $table->decimal('latitude', 10, 7)->nullable();
    $table->decimal('longitude', 10, 7)->nullable();
});
  1. Add the field to a resource:
use Naif\MapAddress\MapAddress;

public function fields(Request $request)
{
    return [
        MapAddress::make('Address', 'address')
            ->rules('required', 'string', 'max:255'),
    ];
}

First use case: an admin picks a store/venue/property location by clicking the map instead of typing coordinates. Treat latitude/longitude as the source of truth and address as a derived, human-readable cache — reverse geocoding is lossy and locale-dependent, and you'll want the numbers for distance math, map embeds, and geo queries.

Implementation Patterns

Split coordinates out of the field value. The field's rendered component is one input; the coordinates live in the field's Vue/withMeta payload and are not saved automatically. Bridge them in the field definition or on the model:

MapAddress::make('Address')
    ->fillUsing(function ($request, $model, $attribute) {
        $model->{$attribute}        = $request->input($attribute);
        $model->latitude            = $request->input('latitude');
        $model->longitude           = $request->input('longitude');
    })

If the package exposes ->latField('latitude')->lngField('longitude')-style options (check src/MapAddress.php), prefer those — but verify they actually hit the request payload, because Nova only posts registered fields by default; hidden lat/lng attributes need ->onlyOnForms() companions or a fillUsing hook as above.

Form vs. detail. Use ->onlyOnForms() for the picker and render a read-only map or a static embed on detail:

MapAddress::make('Address')->onlyOnForms(),
Text::make('Coordinates', fn () => "{$this->latitude}, {$this->longitude}")
    ->onlyOnDetail(),

Backfilling existing rows. The field is useless for imports and seeders because reverse geocoding happens in the browser. Write a small server-side service that hits the Google Geocoding API and cache the result — one class, reused by an artisan command and by an observer:

class Geocoder
{
    public function reverse(float $lat, float $lng): ?string
    {
        $res = Http::get('https://maps.googleapis.com/maps/api/geocode/json', [
            'latlng' => "{$lat},{$lng}",
            'key'    => config('services.google.maps_key'),
        ]);

        return data_get($res->json(), 'results.0.formatted_address');
    }
}

Keep the address fresh. Addresses drift (renames, renumbering). Schedule a nightly job that re-geocodes rows where updated_at is older than N days, or where address is null — never re-geocode on every save.

Downstream consumers. Once coordinates are stored, the normal Laravel/Nova follow-ons apply: ->sortable() on lat/lng, Haversine selectRaw for "nearest to" filters, and MapAddress-independent map widgets for detail views.

Gotchas and Tips

  • Google API key exposure. Reverse geocoding fires from the browser, so the key is visible in the page. Restrict it by HTTP referrer in Google Cloud, enable both Maps JavaScript API and Geocoding API, and keep a separate referrer-unrestricted key for your server-side Geocoder in config/services.php. A missing/disabled API produces a grey map with no PHP error — check the browser console for ApiNotActivatedMapError.
  • HTTPS in production. Maps JS refuses to render on non-secure origins; staging over plain HTTP will silently look broken.
  • Async race on save. Geocoding is a network round-trip. A user who drops a pin and immediately clicks Save can persist an empty address. Disable the submit button while a lookup is in flight, or re-geocode server-side in saving when address is blank but coordinates are present.
  • Nova version mismatch. On Nova 4/5 the published .js won't register. Debug path: php artisan nova:publish, confirm files land in public/vendor/naif/map-address, check the network tab for a 404 on js/field.js, and check whether Vue.component(...) in the bundle matches Nova's Vue version. If it doesn't, the pragmatic fix is a thin fork: keep the PHP field class, replace resources/js/field.js with a Vue 3 component using @googlemaps/js-api-loader, and register it via Nova::script yourself.
  • Precision and type. Store coordinates as decimal(10,7), not float or string. Cast them to float on the model, otherwise comparisons and radius queries behave oddly.
  • Address format is not stable. Google returns locale- and region-specific strings, sometimes with a plus code or a country name in the wrong position. Never parse the address string; if you need structured parts (street, city, postcode), extend the server-side geocoder to read address_components and store them separately.
  • Cost control. Geocoding is billed per request. Debounce marker drags (only geocode on dragend), cache by rounded lat,lng key, and set a billing quota alert — a 13-star package with no rate limiting will happily fire a request per pixel of drag.
  • No tests, single maintainer, zero dependents. Treat it as sample code: fork it into your app's nova-components directory, pin the fork, and add a feature test that posts the form and asserts lat/lng/address all persist. That test is also your fastest regression signal when you upgrade Nova.
  • Extension points worth knowing: fillUsing() for custom persistence, resolveUsing() for formatting what the detail view shows, and withMeta() for injecting the API key, default center, and zoom from config rather than hardcoding them in the field call.
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.
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle