What is Google Places Autocomplete and Why Use It in Laravel 12?

Google Places Autocomplete is part of the Google Maps JavaScript API. It provides predictive text suggestions for addresses and locations as users type into an input field. For example, typing "New Y" might suggest "New York, NY, USA" or "New York Avenue, Washington, DC."

Key benefits include:

  • Improved User Experience: Reduces typing errors and speeds up form completion.
  • Accuracy: Leverages Google's global location data for precise results.
  • Customization: You can restrict suggestions to specific countries, types (e.g., cities only), or components (e.g., street address).
  • Integration Ease: Works seamlessly with web frameworks like Laravel via JavaScript.

In Laravel 12, we'll use the API by loading the Google Maps script and initializing the Autocomplete object on a form input. This requires an API key from Google Cloud Console, which we'll set up in the next section.



How to Implement Google Places Autocomplete for Locations in Laravel 12: A Complete Guide

Table Of Content

1 Prerequisites

Before starting, make sure you have:
  • PHP ≥ 8.2
  • Google Cloud Account
  • Google Places API enabled
  • A valid Google Maps API key
  • MySQL / PostgreSQL / SQLite (or any supported DB)
  • Basic knowledge of Laravel routing, controllers, and Blade

2 Introduction

Google Places Autocomplete provides real-time address suggestions powered by Google Maps data. Integrating it into a Laravel 12 application helps users fill in location fields quickly and accurately, which is especially valuable for delivery apps, real estate platforms, and any form that collects addresses.

In this tutorial, we will build a simple Laravel 12 form where users type a location, select from autocomplete suggestions, and save the full address along with latitude and longitude coordinates to a MySQL database. We will use the Google Maps JavaScript API on the frontend and a standard Laravel controller on the backend.

This tutorial assumes you have basic knowledge of Laravel, PHP, and JavaScript. If you're new to Laravel 12, note that it builds on previous versions with improvements in performance, security, and developer experience, including better support for modern PHP features.

3 Create a Fresh Laravel 12 Project

Let's start by creating a new Laravel 12 project and configuring the database connection. If you already have an existing Laravel 12 project, you can skip ahead to Step 4: Obtaining Your Google Places API Key.

3.1 Install Laravel Project

First, ensure Composer is installed on your system. Use the following command to install a new Laravel Project:

composer create-project laravel/laravel:^12.0 laravel12-google-location

Navigate to your project directory:

cd laravel12-google-location

3.2 Configure Your Database (.env)

Open the .env file and input the necessary database credentials:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_google_location
DB_USERNAME=root
DB_PASSWORD=

4 Obtaining Your Google Places API Key

To use Google Places Autocomplete, you need a valid API key from Google Cloud Console. Follow these steps:

  • Go to Google Cloud Console and create or select a project.
  • Navigate to "APIs & Services" > "Library."
  • Search for "Places API" and enable it.
  • Also enable "Maps JavaScript API" (required for the frontend script).
  • Go to "Credentials" and create an API key.
  • Restrict the key to "Places API" and "Maps JavaScript API" and add your website's referrer URL for security.

Add the key to your .env file:

    
GOOGLE_MAPS_API_KEY=YOUR_GOOGLE_API_KEY
    

Replace YOUR_GOOGLE_API_KEY with your actual key. Never commit API keys to version control.

Register the key in config/services.php so Laravel can access it:

    
'google' => [
    'maps_api_key' => env('GOOGLE_MAPS_API_KEY'),
],
    

After saving, clear the config cache with php artisan config:clear to ensure Laravel picks up the new value.

5 Create Migration & Model

We need a database table to store the selected location data. Let's create a migration and model for UserLocation.

    
php artisan make:migration create_user_locations_table
    

Open the generated migration file and define the table schema:

    
<?php
// database/migrations/xxxx_xx_xx_create_user_locations_table.php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration {
    public function up(): void
    {
        Schema::create('user_locations', function (Blueprint $table) {
            $table->id();
            $table->string('address');
            $table->decimal('lat', 10, 8)->nullable();
            $table->decimal('lng', 11, 8)->nullable();
            $table->timestamps();
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('user_locations');
    }
};

Run the migration to create the table:


php artisan migrate

Create the Eloquent Model

    
php artisan make:model UserLocation
    

Edit app/Models/UserLocation.php and add the fillable fields:

    
<?php
// app/Models/UserLocation.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class UserLocation extends Model
{
    protected $fillable = [
        'address',
        'lat',
        'lng',
    ];
}

The $fillable array tells Laravel which columns can be mass-assigned when using UserLocation::create().

6 Creating the Controller


php artisan make:controller LocationController

Edit app/Http/Controllers/LocationController.php to handle showing the form and saving the location:

    
<?php
namespace App\Http\Controllers;

use App\Models\UserLocation;
use Illuminate\Http\Request;

class LocationController extends Controller
{
    public function create()
    {
        return view('location.create');
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'address' => ['required', 'string', 'max:255'],
            'lat'     => ['nullable', 'numeric'],
            'lng'     => ['nullable', 'numeric'],
        ]);

        UserLocation::create($validated);

        return redirect()
            ->route('location.create')
            ->with('success', 'Location saved successfully!');
    }
}

The create() method renders the Blade form, while store() validates the input and saves the address, latitude, and longitude to the database using Eloquent.

7 Crafting the Blade View

Create the directory resources/views/location/ and then create resources/views/location/create.blade.php for the main view:

    
   <!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Google Autocomplete Location - Laravel 12</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 760px; margin: 40px auto; padding: 0 16px; }
        .box { border: 1px solid #ddd; padding: 16px; border-radius: 10px; }
        input { width: 100%; padding: 12px; margin-top: 8px; border: 1px solid #ccc; border-radius: 8px; }
        button { margin-top: 14px; padding: 12px 16px; border: 0; border-radius: 8px; cursor: pointer; }
        .msg { padding: 10px 12px; border-radius: 8px; margin-bottom: 12px; }
        .success { background: #e9ffe9; border: 1px solid #9be59b; }
        .error { background: #ffecec; border: 1px solid #f0a0a0; }
        .small { font-size: 12px; color: #666; margin-top: 6px; }
        .row { display: flex; gap: 12px; }
        .row > div { flex: 1; }
        label { font-weight: 600; display: block; margin-top: 10px; }
    </style>
</head>
<body>

    <h1>Google Autocomplete Location in Laravel 12</h1>

    <div class="box">

        @if (session('success'))
            <div class="msg success">{{ session('success') }}</div>
        @endif

        @if ($errors->any())
            <div class="msg error">
                <strong>Please fix:</strong>
                <ul>
                    @foreach ($errors->all() as $error)
                        <li>{{ $error }}</li>
                    @endforeach
                </ul>
            </div>
        @endif

        <form method="POST" action="{{ route('location.store') }}" autocomplete="off">
            @csrf

            <label for="address">Search location</label>
            <input
                type="text"
                id="address"
                name="address"
                placeholder="Start typing an address..."
                value="{{ old('address') }}"
                required
            >
            <div class="small">Tip: Select from dropdown suggestions to capture lat/lng.</div>

            <input type="hidden" id="lat" name="lat" value="{{ old('lat') }}">
            <input type="hidden" id="lng" name="lng" value="{{ old('lng') }}">

            <div class="row">
                <div>
                    <label>Latitude (auto)</label>
                    <input type="text" id="lat_preview" value="{{ old('lat') }}" readonly>
                </div>
                <div>
                    <label>Longitude (auto)</label>
                    <input type="text" id="lng_preview" value="{{ old('lng') }}" readonly>
                </div>
            </div>

            <button type="submit">Save Location</button>
        </form>
    </div>

    <script>
        // Clear lat/lng if user types manually (not selecting from dropdown)
        const addressInput = document.getElementById('address');
        const latInput = document.getElementById('lat');
        const lngInput = document.getElementById('lng');
        const latPreview = document.getElementById('lat_preview');
        const lngPreview = document.getElementById('lng_preview');

        function clearLatLng() {
            latInput.value = '';
            lngInput.value = '';
            latPreview.value = '';
            lngPreview.value = '';
        }

        addressInput.addEventListener('input', clearLatLng);

        function initAutocomplete() {
            if (!window.google || !google.maps || !google.maps.places) {
                console.error("Google Places library not loaded.");
                return;
            }

            const autocomplete = new google.maps.places.Autocomplete(addressInput, {
                types: ['geocode'],
                // Optional: restrict to a country:
                // componentRestrictions: { country: ["de"] }
            });

            autocomplete.addListener('place_changed', () => {
                const place = autocomplete.getPlace();

                // If user didn't select a suggestion properly
                if (!place.geometry || !place.geometry.location) {
                    clearLatLng();
                    return;
                }

                const lat = place.geometry.location.lat();
                const lng = place.geometry.location.lng();

                latInput.value = lat;
                lngInput.value = lng;

                latPreview.value = lat;
                lngPreview.value = lng;

                // Optional: replace input with formatted address
                if (place.formatted_address) {
                    addressInput.value = place.formatted_address;
                }
            });
        }

        window.initAutocomplete = initAutocomplete;
    </script>

    <script
        src="https://maps.googleapis.com/maps/api/js?key={{ config('services.google.maps_api_key') }}&libraries=places&callback=initAutocomplete"
        async defer>
    </script>

</body>
</html>

    

8 Define Routes

In routes/web.php, define the necessary routes:

use App\Http\Controllers\LocationController;
use Illuminate\Support\Facades\Route;

Route::get('/location', [LocationController::class, 'create'])->name('location.create');
Route::post('/location', [LocationController::class, 'store'])->name('location.store');


9 Folder Structure

10 Run the project


php artisan serve

Visit: http://127.0.0.1:8000/location

You should see the location form. Start typing an address and Google's autocomplete dropdown will appear. Select a suggestion to auto-fill the latitude and longitude fields.

How It Works Under the Hood:

  • The Google Maps script is loaded asynchronously using the API key stored securely in .env.
  • new google.maps.places.Autocomplete() attaches to the address input field and displays location suggestions as the user types.
  • When a suggestion is selected, getPlace() returns a PlaceResult object containing formatted_address, geometry.location.lat(), and geometry.location.lng().
  • The hidden fields for latitude and longitude are populated automatically, then submitted with the form to the Laravel backend.
  • If the user manually edits the address text after selecting a suggestion, the latitude and longitude fields are cleared to prevent mismatched data.

11 Conclusion

In this tutorial, we built a complete location autocomplete feature in Laravel 12 using the Google Places API. We covered setting up the API key, creating the migration and model, building a controller with validation, and writing a Blade view with JavaScript integration.

This approach gives you accurate address data with latitude and longitude coordinates that you can use for mapping, distance calculations, delivery zones, or any location-based feature in your application.

Next Steps:

  • Restrict autocomplete to specific countries using componentRestrictions.
  • Display selected locations on a Google Map embedded in the same page.
  • Use AJAX instead of a full form submit for a smoother single-page experience.
  • Add reverse geocoding to let users click on a map to fill the address field.

If you found this guide helpful, check out our other Laravel tutorials for more hands-on guides.

If you enjoyed this tutorial, explore these related Laravel 12 guides on our site:

Revathi M - PHP and CodeIgniter Developer

Written by Revathi M

PHP Developer & Technical Writer · 10+ years building web applications with CodeIgniter and Laravel

Revathi specializes in PHP backend development, authentication systems, and REST API design. She writes practical, production-tested tutorials at Get Sample Code to help developers build secure applications faster.

Frequently Asked Questions

Add componentRestrictions: { country: ["us"] } to the Autocomplete options object, replacing "us" with your desired country code.

Check that your API key is valid, the Places API and Maps JavaScript API are both enabled in Google Cloud Console, and your key restrictions allow your domain.

This tutorial uses the legacy Autocomplete class. Google also offers the Place Autocomplete (New) widget. You can migrate by following Google official migration guide.

Enable Google Places API, include Maps JavaScript API, and initialize autocomplete on input field.

It offers free monthly credits, but billing must be enabled.

Yes, use place.geometry.location.lat() and lng() and store them in database.

Yes, it works on all modern mobile browsers.

Yes, it improves UX and reduces invalid address entries, indirectly helping SEO.