PHPackages                             ihangan/laravel-moldova-cuatm - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. ihangan/laravel-moldova-cuatm

ActiveLibrary[Database &amp; ORM](/categories/database)

ihangan/laravel-moldova-cuatm
=============================

Moldova's CUATM administrative-territorial divisions (raioane, cities, towns and villages) as Eloquent models with multilingual names and coordinates.

v1.0.1(today)01↑2900%[1 PRs](https://github.com/ihangan/laravel-moldova-cuatm/pulls)MITPHPPHP ^8.3CI passing

Since Jun 30Pushed todayCompare

[ Source](https://github.com/ihangan/laravel-moldova-cuatm)[ Packagist](https://packagist.org/packages/ihangan/laravel-moldova-cuatm)[ Docs](https://github.com/ihangan/laravel-moldova-cuatm)[ RSS](/packages/ihangan-laravel-moldova-cuatm/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (10)Versions (4)Used By (0)

[![Moldova CUATM for Laravel](art/social-card.png)](art/social-card.png)

Moldova CUATM for Laravel
=========================

[](#moldova-cuatm-for-laravel)

[![Latest version](https://camo.githubusercontent.com/009be9b69846c77f0de695a38dce336e5adc34ff1c464146c1f943064770fbf8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6968616e67616e2f6c61726176656c2d6d6f6c646f76612d637561746d2e737667)](https://packagist.org/packages/ihangan/laravel-moldova-cuatm)[![Tests](https://github.com/ihangan/laravel-moldova-cuatm/actions/workflows/run-tests.yml/badge.svg)](https://github.com/ihangan/laravel-moldova-cuatm/actions/workflows/run-tests.yml)[![PHPStan](https://camo.githubusercontent.com/b6d441ad4fe8332cb16c72aa27f22cc685181dfd74ae34964afc92c6c1146b3c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c2532306d61782d627269676874677265656e2e737667)](https://github.com/ihangan/laravel-moldova-cuatm/actions/workflows/static.yml)[![Total downloads](https://camo.githubusercontent.com/9ec5d787a8a4b7d1b57464a9eff1e90306aee06f97743b249b87df2cc6b805ce/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6968616e67616e2f6c61726176656c2d6d6f6c646f76612d637561746d2e737667)](https://packagist.org/packages/ihangan/laravel-moldova-cuatm)[![License](https://camo.githubusercontent.com/96c14acb920519a0d50ec4356db4c140b8d2fc44d4d6f8ed6497745d8e647e3d/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6968616e67616e2f6c61726176656c2d6d6f6c646f76612d637561746d2e737667)](LICENSE.md)

Every administrative-territorial unit of the Republic of Moldova, as an Eloquent model you can query straight away. The data comes from CUATM, the official classifier maintained by the National Bureau of Statistics, so the codes and the hierarchy match what government systems use.

You get the 32 raioane, the municipalities, the sectors of Chișinău, every town and all ~1,600 villages, plus Gagauzia and the Stînga Nistrului units. Each one carries its official CUATM code, a parent link, names in Romanian, Russian and Ukrainian, and WGS84 coordinates.

I built this for a rental classifieds site that needed a real location tree (region → city → sector → village) instead of a free-text address field, and pulled it out into a package because the dataset is useful on its own.

Requirements
------------

[](#requirements)

- PHP 8.3 or higher
- Laravel 12 or 13

Installation
------------

[](#installation)

```
composer require ihangan/laravel-moldova-cuatm
```

Publish and run the migration, then load the data:

```
php artisan vendor:publish --tag="moldova-cuatm-migrations"
php artisan migrate
php artisan cuatm:import
```

`cuatm:import` is idempotent, so you can run it again whenever a new CUATM edition ships without ending up with duplicates.

Usage
-----

[](#usage)

The model is `Ihangan\MoldovaCuatm\Models\Location`. It behaves like any other Eloquent model.

```
use Ihangan\MoldovaCuatm\Models\Location;
use Ihangan\MoldovaCuatm\Enums\LocationType;

// By the official CUATM code or by slug.
Location::whereCode('0111001')->first();
Location::where('slug', 'chisinau')->first();

// Every raion.
Location::ofType(LocationType::Raion)->get();

// Top-level units only.
Location::roots()->get();
```

### Names

[](#names)

Names are translatable (backed by [spatie/laravel-translatable](https://github.com/spatie/laravel-translatable)). Romanian is always present; Russian and Ukrainian exist for most localities; English is filled in for the larger cities.

```
$chisinau = Location::where('slug', 'chisinau')->first();

$chisinau->name;                          // current locale
$chisinau->getTranslation('name', 'ru');  // "Кишинёв"
$chisinau->getTranslation('name', 'uk');  // "Кишинів"
```

Set a fallback once (for example in a service provider) so a missing locale returns Romanian instead of an empty string:

```
use Spatie\Translatable\Facades\Translatable;

Translatable::fallback(fallbackLocale: 'ro', fallbackAny: true);
```

### Hierarchy

[](#hierarchy)

The tree is a self-referencing `parent_id`.

```
$village = Location::where('slug', 'dobrogea')->first();

$village->parent;       // the town it belongs to
$village->ancestors();  // [town, sector, municipality], nearest first

$sector = Location::where('slug', 'botanica')->first();
$sector->children;      // towns and villages under Botanica
```

### Coordinates

[](#coordinates)

```
$location = Location::where('slug', 'chisinau')->first();

[$location->lat, $location->lng]; // 47.005..., 28.857...
```

### Facade

[](#facade)

A small facade wraps the common lookups when you would rather not write the queries by hand:

```
use Ihangan\MoldovaCuatm\Facades\Cuatm;

Cuatm::findByCode('0111001');
Cuatm::findBySlug('chisinau');
Cuatm::roots();          // raioane, municipalities, Gagauzia, Transnistria
Cuatm::raioane();
Cuatm::childrenOf($raion);
Cuatm::tree();           // roots with their children eager-loaded
```

### Cascading location picker

[](#cascading-location-picker)

`roots()` and `childrenOf()` are all you need to build a "pick a region, then a locality below it" selector. The hierarchy isn't a fixed depth (a raion goes straight to its villages, while Chișinău goes municipality → sector → town → village), so the picker keeps offering another dropdown while the chosen unit still has children.

```
use Ihangan\MoldovaCuatm\Facades\Cuatm;
use Livewire\Component;

class LocationPicker extends Component
{
    /** @var array the selected location id at each level */
    public array $path = [];

    public function selectLevel(int $level, ?int $id): void
    {
        $this->path = array_slice($this->path, 0, $level); // drop the deeper levels

        if ($id !== null) {
            $this->path[$level] = $id;
        }
    }

    public function render()
    {
        $levels = collect([Cuatm::roots()]);

        foreach ($this->path as $id) {
            $children = Cuatm::childrenOf($id);

            if ($children->isEmpty()) {
                break; // reached the bottom of the tree
            }

            $levels->push($children);
        }

        return view('livewire.location-picker', ['levels' => $levels]);
    }
}
```

```
{{-- resources/views/livewire/location-picker.blade.php --}}

    @foreach ($levels as $level => $options)

            —
            @foreach ($options as $location)
                id)>
                    {{ $location->name }}

            @endforeach

    @endforeach

```

The selected location is the last entry in `$path`. Outside Livewire the same two calls drive any UI: render `Cuatm::roots()` first, then `Cuatm::childrenOf($id)`each time a level is chosen.

Configuration
-------------

[](#configuration)

Publish the config file if you need to change the table name, the connection or the locales:

```
php artisan vendor:publish --tag="moldova-cuatm-config"
```

```
return [
    'table' => 'cuatm_locations',
    'connection' => null,
    'locales' => ['ro', 'ru', 'uk', 'en'],
    'fallback_locale' => 'ro',
];
```

The table is named `cuatm_locations` rather than `locations` so it does not clash with one your application may already have.

Data and updates
----------------

[](#data-and-updates)

The dataset lives in `database/data/cuatm.json` and ships with the package.

- Codes, hierarchy and Romanian names come from CUATM (Clasificatorul unităților administrativ-teritoriale ale Republicii Moldova), published by the National Bureau of Statistics.
- Russian and Ukrainian names are Wikidata exonyms.
- Coordinates are from public geodata.

CUATM changes rarely. When the Bureau publishes a new edition, replace the JSON file and run `php artisan cuatm:import` again.

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md) and the [releases](https://github.com/ihangan/laravel-moldova-cuatm/releases).

Contributing
------------

[](#contributing)

See [CONTRIBUTING.md](CONTRIBUTING.md).

Security
--------

[](#security)

Found a security issue? Email  instead of using the issue tracker. See [SECURITY.md](.github/SECURITY.md).

Credits
-------

[](#credits)

- [Igor Hangan](https://github.com/ihangan)
- The administrative data comes from the CUATM classifier published by the National Bureau of Statistics of Moldova, with Russian and Ukrainian names from Wikidata.

License
-------

[](#license)

The MIT License. See [LICENSE.md](LICENSE.md).

The administrative data is public information from the National Bureau of Statistics of Moldova; Wikidata content is CC0.

###  Health Score

42

—

FairBetter than 89% of packages

Maintenance100

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity50

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

0d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/f57b8b98fa05fa2831b92420b9e126f1978adc9a7c86c31719eb1ebb319139f7?d=identicon)[ihangan](/maintainers/ihangan)

---

Top Contributors

[![ihangan](https://avatars.githubusercontent.com/u/17790228?v=4)](https://github.com/ihangan "ihangan (2 commits)")

---

Tags

laravelgeoMoldovalocationsadministrative-divisionslocalitiescuatm

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/ihangan-laravel-moldova-cuatm/health.svg)

```
[![Health](https://phpackages.com/badges/ihangan-laravel-moldova-cuatm/health.svg)](https://phpackages.com/packages/ihangan-laravel-moldova-cuatm)
```

###  Alternatives

[spatie/laravel-health

Monitor the health of a Laravel application

87511.3M154](/packages/spatie-laravel-health)[larastan/larastan

Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel

6.4k51.0M7.8k](/packages/larastan-larastan)[spatie/laravel-medialibrary

Associate files with Eloquent models

6.1k41.3M607](/packages/spatie-laravel-medialibrary)[laravel/ai

The official AI SDK for Laravel.

1.0k2.1M169](/packages/laravel-ai)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.1M337](/packages/psalm-plugin-laravel)[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

438834.4k1](/packages/clickbar-laravel-magellan)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
