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

Geo Laravel Package

yandex/geo

yandex/geo is a PHP client for the Yandex Geocoder API that converts addresses to coordinates and coordinates to addresses. It supports configurable language, precision, and result limits, making geocoding and reverse geocoding straightforward in Laravel/PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

yandex/geo is a framework-agnostic HTTP client around the Yandex Geocoder XML/REST API. There is no ServiceProvider, no facade, and no config file — you instantiate Yandex\Geo\Api directly.

composer require yandex/geo

First smoke test in php artisan tinker:

$api = new \Yandex\Geo\Api();
$api->setQuery('Москва, Красная площадь')
    ->setLimit(5)
    ->setLang(\Yandex\Geo\Api::LANG_RU)
    ->load();

foreach ($api->getResponse()->getList() as $item) {
    dump($item->getAddress(), $item->getLatitude(), $item->getLongitude());
}

Where to look first:

  1. Yandex\Geo\Api — all set* setters (setQuery, setLatitude/setLongitude for reverse geocoding, setLimit, setOffset, setLang, setArea/setBoundingBox).
  2. Yandex\Geo\Response — getList(), getFound(), getRawResponse().
  3. Yandex\Geo\GeoObject — getAddress(), getLatitude(), getLongitude(), getKind(), getPrecision(), getData() (raw DOM node for anything not exposed).

Your first practical use case: geocode a user-entered shipping address into (lat, lng) so you can pass it to a map (Leaflet/Yandex Maps JS/Google Maps) or store it on an Address model next to the free-text address.

Implementation Patterns

Wrap it in a single service, not scattered new Api() calls. You will want to inject config (default lang, limits) and centralize caching and error mapping.

namespace App\Services;

use Yandex\Geo\Api;

class Geocoder
{
    public function forward(string $query, int $limit = 5): array
    {
        return \Cache::remember("geo:{$query}:{$limit}", 86400, function () use ($query, $limit) {
            $api = (new Api())->setQuery($query)->setLimit($limit)->setLang(Api::LANG_RU)->load();
            return array_map(fn($o) => [
                'address' => $o->getAddress(),
                'lat'     => (float) $o->getLatitude(),
                'lng'     => (float) $o->getLongitude(),
                'kind'    => $o->getKind(),
                'raw'     => $o->getData(),
            ], $api->getResponse()->getList());
        });
    }

    public function reverse(float $lat, float $lng): ?array
    {
        $api = (new Api())->setLatitude($lat)->setLongitude($lng)->setLang(Api::LANG_RU)->load();
        $list = $api->getResponse()->getList();
        return $list ? ['address' => $list[0]->getAddress()] : null;
    }
}

Never call the geocoder inside a request that also renders a form. Yandex is slow and rate-limited. Two patterns work well:

  • Address form → dispatch job: save the address on a model, dispatch GeocodeAddress job, update lat/lng when done, and broadcast/poll for completion.
  • Suggestion endpoint: expose /api/geocode?q= that hits the service (cached) and returns a JSON array for an autocomplete box. Debounce on the client (setLimit(5) → small payloads).

Config in config/services.php:

'yandex_geo' => [
    'lang'   => env('YANDEX_GEO_LANG', 'ru_RU'),
    'limit'  => env('YANDEX_GEO_LIMIT', 10),
    'cache_ttl' => 86400,
],

Storing addresses: persist the raw getAddress() string and the components (country, province, locality, street, house) parsed out of getData(), plus the coordinates. Address strings change; components are what you query.

Reverse geocoding for map pins: when a user drops a pin, reverse-geocode to fill the "nearest known address" field. Fall back to showing the raw lat/lng if the API returns empty.

Gotchas and Tips

  • The package is unmaintained (last release July 2019). It predates Yandex's API-key requirement and the recent apikey parameter is not exposed by Api. If Yandex rejects your requests due to auth, you'll need to fork the class (it's ~200 lines) or skip the package and call https://geocode-maps.yandex.ru/1.x/?apikey=...&geocode=... with Laravel's Http client. Prefer the latter for new code.
  • No apikey setter, no timeouts, no injectable HTTP client. If you must use it, wrap calls in rescue() / try-catch and set a timeout at the cURL level via setCurlOptions() in the underlying curl — otherwise a hung request will block your worker.
  • Exceptions you'll actually see: Yandex\Geo\Exception (API error envelope), Yandex\Geo\Exception\CurlError (network), Yandex\Geo\Exception\ServerError (5xx). Catch broadly in the service layer and return a typed result; never let them bubble to the UI.
  • Coordinate order matters. setLatitude()->setLongitude() is explicit — but getLatitude() returns a string, so cast to float before storing or comparing.
  • Cyrillic responses come back URL-encoded in older paths. getAddress() generally decodes fine, but if you see %D0%9C..., urldecode() before storing.
  • Cache aggressively. Same query repeated in a loop will get rate-limited. Key on md5($query . $lang . $limit). Consider negative caching (null result) for a short TTL so typo'd addresses don't hammer the API.
  • getList() returns an ArrayObject of GeoObject. Calling getList()[0] is fine, but count with count($list) or via $response->getFound() (the API's reported total, which can exceed what was returned).
  • getData() is a DOMElement. Use textContent/getElementsByTagName to pull fields not exposed (e.g. metaDataProperty, AdministrativeAreaName, ThoroughfareName). This is your escape hatch when the wrapper doesn't surface a field.
  • Precision/kind values are strings, not enums — "street", "house", "locality", "country". Compare with === and handle unknown values defensively because Yandex has expanded these over time.
  • Extension point: the package is small enough that the right move for a long-lived Laravel app is to swap Yandex\Geo\Api for a tiny Http::get(...) wrapper in your own service class, keeping the same forward()/reverse() interface. That gets you API-key support, timeouts, retries, and Http::fake() in tests for free.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle