Search by

blemli / swissstreets-for-filament

blemli

Every Swiss address. Offline.

Package info

github.com/blemli/swissstreets-for-filament

pkg:composer/blemli/swissstreets-for-filament

Statistics

Installs: 5

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.8.0 2026-09-16 15:30 UTC

This package is auto-updated.

Last update: 2026-09-17 11:53:46 UTC


README

Every Swiss address. Offline. Daily.

swissstreets

Latest Version on Packagist Tests Code Style Total Downloads

Address field for Filament backed by the official Swiss building address register. Nightly update from the official source, works fully offline, sorts by vicinity — no spatial extension required. Support for foreign addresses, because life is messy.

Install

composer require blemli/swissstreets-for-filament
php artisan swissstreets:install        # add -n for provisioning scripts: migrates, schedules, imports

The installer schedules the nightly swissstreets:import in routes/console.php (suggested time 03:00–04:59, hashed from the app name so not every app hits swisstopo in the same minute) and runs the first import. Transient network errors against swisstopo are retried (2 s / 5 s / 10 s); a failed import exits non-zero and says what to do. A run killed mid-import leaves its lock behind — the next run says who held it since when, heals itself when that process is gone from the same host, or takes php artisan swissstreets:import --unlock.

Use

// Panel
->plugin(SwissstreetsPlugin::make()->cantons(['BS', 'BL'])->table()->notify(User::class))

// Model
class Customer extends Model { use HasAddress; }   // needs an address_id column

// Form: "spalen 113" → Spalenring 113, 4055 Basel
Address::make('address_id')->nonresidential()->nearMe()->allowCustom('address_text')
Address::cascade('address_id')->nearMe()->freetext()   // same, as three selects: town → street → number

// Map picker: search the register or drop the pin anywhere (swisstopo tiles, dark mode aware)
MapPicker::make('location')->lat('latitude')->lng('longitude')->address('address_id')

// Table / infolist
AddressColumn::make('address')->map()
AddressEntry::make('address')->map()

// Query
Address::search('bahnhof zürich')->near($lat, $lng, withinKm: 5)->used()

// Global search: "spalen 113" finds the customer living there
class CustomerResource extends Resource { use SearchesAddressGlobally; }   // then list 'address' in getGloballySearchableAttributes()

Events: AddressAdded, AddressRemoved, AddressRestored (per address, import or ->freetext() form) and ImportFinished (with the ImportResult) under Blemli\Swissstreets\Events.

Plugin options: ->cantons([...]) limits the import, ->table() adds the browsable addresses table to the panel (with an "Import from swisstopo" button that queues the import — gate it with AddressPolicy::import(), which Filament Shield generates as import_address), ->notify(User::class) (or a closure returning users) sends a database notification after each import that changed something, ->swissgrid() keeps LV95 easting/northing, ->unofficial(), ->planned(), ->health() registers the health check below. Removed addresses are soft-deleted and logged. Remove everything with php artisan swissstreets:uninstall.

Supported plugins

  • spatie/laravel-health (shown in the panel by shuvroroy/filament-spatie-laravel-health): SwissstreetsPlugin::make()->health() (or health.enabled in the config; the installer offers it when the package is installed) registers the "Swiss address register" check — red when no address was created, updated or removed for 21 days, yellow when the last 3 imports failed. Thresholds: ->health(maxAgeDays: 21, maxFailedRuns: 3).
  • spatie/laravel-activitylog: every added, removed and restored address is recorded as an activity (log name swissstreets) when the package is installed; switch off with the activitylog config key.

MIT © blemli