NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Set GOOGLE_PLACES_CACHE=true to cache idempotent lookups (details, geocode, forward geocode, distance, distance matrix, text & nearby search). Autocomplete is never cached. Cache keys never contain the API key:

GOOGLE_PLACES_CACHE=true
GOOGLE_PLACES_CACHE_STORE=redis   # optional; null = the default store
GOOGLE_PLACES_CACHE_TTL=86400     # seconds
  • Cached: details(), geocode(), geocodeAddress(), textSearch(), nearbySearch(), findPlace() (it runs a text search), distance(), computeMatrix() and matrix().
  • Not cached: autocomplete(), the paginated helpers textSearchPaginated() / nearbySearchPaginated(), photo requests (photo(), photoUri(), photoContents()) and check().
  • A details 404 is an answer — “no such place” — and is cached like any other result, so repeats are not re-billed.
  • Transient failures always throw and are never cached.
  • The package caches Google’s raw payload and rebuilds the DTOs on read, so entries work with Laravel’s cache.serializable_classes restriction.
  • Cache hits make no request, so they dispatch no lifecycle event.

Bypassing the cache

Every cached query takes a fresh flag — a trailing constructor argument (fresh: true) or the fresh() wither, which every fluent method keeps; the matrix() handle has its own fresh(). A fresh lookup skips the cache read, asks Google and writes the answer back to the same key:

use RoundlyConsulting\GooglePlaces\DataTransferObjects\DetailsQuery;
use RoundlyConsulting\GooglePlaces\Facades\GooglePlaces;

$place = GooglePlaces::details(new DetailsQuery($placeId, fresh: true));
$place = GooglePlaces::details((new DetailsQuery($placeId))->fresh());   // the same

GooglePlaces::matrix($origins, $destinations)->fresh()->driving();
  • Write-through — the next plain read gets the refreshed payload, and the entry’s TTL starts again.
  • A details 404 — a fresh one stores null, like a plain one, so later plain reads return null.
  • Failure — a fresh call that fails throws a PlacesException. Failures are never cached, so the old entry stays in place and plain reads keep getting it.
  • A real request — a fresh call takes a rate-limit slot, dispatches PlacesResponseReceived or PlacesRequestFailed and is logged like a miss.
  • Cache off — with cache.enabled false every call goes to Google anyway, so the flag changes nothing.
  • Off the wire — the flag is never sent to Google and is not part of the cache key, so a fresh call and a plain call share one entry.
Cached callCarries the flag
details()DetailsQuery
geocode()ReverseGeocodingQuery
geocodeAddress()GeocodingQuery
textSearch()TextSearchQuery
nearbySearch()NearbySearchQuery
distance()DistanceQuery
computeMatrix() / matrix()MatrixQuery / PendingMatrix::fresh()

A details() call inside a billing session keeps the flag too. The string and Location shortcuts (details('ChIJ…'), geocode($lat, $lng)) and findPlace() take no flag — pass the query object instead. Endpoints that are never cached have no flag: there is nothing to bypass.

use RoundlyConsulting\GooglePlaces\DataTransferObjects\TextSearchQuery;

// findPlace() takes no flag — run its one-result text search fresh instead:
$place = GooglePlaces::textSearch((new TextSearchQuery('Googleplex'))->take(1)->fresh())->first();

Google’s 30-day limit on stored content

Google’s Maps Platform terms cap how long you may keep Places content: at most 30 consecutive days for what may be stored at all (place IDs are exempt). The terms change, so check Google’s current Maps Service Specific Terms for your use. Two things follow:

  • Keep cache.ttl well below 30 days. The package does not cap it.
  • If you store snapshots yourself (a places table, for example), refresh them with a fresh lookup. A plain lookup can return a cached payload that is already up to cache.ttl old, so the snapshot you stamp as “refreshed now” would really be older.

Clearing

Entries expire after cache.ttl. To refresh one entry, repeat its lookup with fresh. There is no package command to flush them all — clear the store, or use a dedicated one via GOOGLE_PLACES_CACHE_STORE, when you need a clean slate.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.