PHP code example of eduardoribeirodev / filament-leaflet
1. Go to this page and download the library: Download eduardoribeirodev/filament-leaflet library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
eduardoribeirodev / filament-leaflet example snippets
return [
'columns' => [ // Default column names for model binding (can be overridden in fromRecord() methods)
'latitude' => 'lat',
'longitude' => 'lng',
'coords' => 'location',
'radius' => 'radius',
'title' => 'title',
'description' => 'description',
'bounds' => 'bounds',
'points' => 'points',
],
'sync_record_attributes' => true, // Auto-sync changes back to models
'default_map_center' => [-14.235, -51.9253], // Default map center
];
use EduardoRibeiroDev\FilamentLeaflet\Enums\TileLayer;
class MyMapWidget extends MapWidget
{
protected TileLayer|string|array $tileLayersUrl = TileLayer::MapboxStreets;
}
use EduardoRibeiroDev\FilamentLeaflet\Fields\MapPicker;
use EduardoRibeiroDev\FilamentLeaflet\Enums\TileLayer;
MapPicker::make('location')
->height(300)
->center(-23.5505, -46.6333)
->zoom(11)
->autoCenter() // Auto-center to user's location
->tileLayersUrl(TileLayer::OpenStreetMap)
->columnSpanFull()
use EduardoRibeiroDev\FilamentLeaflet\Concerns\HasGeoJsonFile;
class DeliveryZone extends Model
{
use HasGeoJsonFile;
public function getGeoJsonFileAttributeName(): string
{
return 'geojson_file';
}
public function getGeoJsonFileDisk(): ?string
{
return 's3';
}
public function getExpirationTime(): ?DateTime
{
return now()->addHour();
}
}
use EduardoRibeiroDev\FilamentLeaflet\Fields\GeoSearchInput;
use EduardoRibeiroDev\FilamentLeaflet\Enums\GeoSearchProvider;
GeoSearchInput::make('location')
->provider(GeoSearchProvider::Nominatim) // Uses OpenStreetMap
->limit(10) // Max 10 results
->withAddressDetails() // Include structured address data
->language('ru') // Preferred language
->countryCodes('ru') // Restrict to Russia
->cacheResults(3600) // Cache for 1 hour
->textMode(false) // Stores full address instead of coordinates
->columnSpanFull()
// Restrict results to a geographic bounding box
GeoSearchInput::make('location')
->provider(GeoSearchProvider::Nominatim)
->viewbox(
minLon: 19.0, // West
minLat: 41.0, // South
maxLon: 190.0, // East
maxLat: 82.0 // North
)
->bounded(true) // Strictly restrict to viewbox
->minSearchLength(3) // Don't search until user types 3+ chars
->useShortLabels(true) // "Moscow Kremlin" instead of full address
use Filament\Support\Icons\Heroicon;
Marker::make(-23.5505, -46.6333)
->icon(Heroicon::BuildingLibrary) // Using Heroicon enum
->icon('heroicon-building-library') // Using string
->heroicon('building-library') // Using explicit heroicon() method
->iconSize([36, 54])
->title('Heroicon Marker')
->color(Color::Indigo);
Marker::make(-23.5505, -46.6333)
->color(Color::Blue) // Color class constant
->blue() // Convenience method
Marker::make(-23.5505, -46.6333)
->color('#3388ff') // Hex color
->color('rgb(51, 136, 255)') // RGB color
->color('oklch(59% 0.15 262)') // OKLCH color
// Basic usage
Marker::fromRecord(
record: $store,
coordsColumn: 'coordinates', // Column/attribute with Coordinate value object
titleColumn: 'name',
descriptionColumn: 'description',
popupFieldsColumns: ['address', 'phone'],
color: Color::Blue,
);
// With custom callback
Marker::fromRecord(
record: $store,
coordsColumn: 'coordinates',
mapRecordCallback: function (Marker $marker, Model $record) {
$marker->gold()->popupFields(['hours' => $record->hours]);
}
);
use EduardoRibeiroDev\FilamentLeaflet\ValueObjects\Coordinate;
class Store extends Model
{
protected $casts = [
'coordinates' => Coordinate::class,
];
}
use App\Models\Store;
use EduardoRibeiroDev\FilamentLeaflet\Layers\Marker;
use Filament\Support\Colors\Color;
protected function getMarkers(): array
{
return [
MarkerCluster::fromModel(
model: Store::class,
coordsColumn: 'coordinates', // Column/attribute with Coordinate value object
titleColumn: 'name',
descriptionColumn: 'description',
popupFieldsColumns: ['address', 'phone'],
color: Color::Green,
)
->maxClusterRadius(60)
->disableClusteringAtZoom(15),
];
}
MarkerCluster::fromModel(
model: Store::class,
coordsColumn: 'coordinates',
modifyQueryCallback: function ($query) {
return $query
->where('status', 'active')
->where('city', 'São Paulo')
->orderBy('name');
},
mapRecordCallback: function (Marker $marker, Model $record) {
// Customize each marker based on record properties
if ($record->isPremium()) {
$marker->gold()->icon('/images/premium-icon.png');
}
// Add status-based styling
match($record->status) {
'open' => $marker->green(),
'busy' => $marker->orange(),
'closed' => $marker->red(),
default => $marker->gray(),
};
// Add popup with custom fields
$marker->popupFields([
'manager' => $record->manager_name,
'staff' => $record->staff_count . ' employees',
'rating' => $record->rating . ' ⭐',
]);
}
);
MarkerCluster::make($markers)
->maxClusterRadius(80) // Cluster radius in pixels
->showCoverageOnHover(true) // Highlight cluster area on hover
->zoomToBoundsOnClick(true) // Zoom to cluster bounds when clicked
->spiderfyOnMaxZoom(true) // Spread markers at max zoom
->removeOutsideVisibleBounds(true) // Remove markers outside viewport for performance
->disableClusteringAtZoom(15) // Stop clustering at zoom level 15+
->animate(true); // Animate cluster changes;
use EduardoRibeiroDev\FilamentLeaflet\Layers\Shapes\Circle;
protected function getShapes(): array
{
return [
Circle::make(-23.5505, -46.6333)
->popupContent('10km radius coverage')
->title('Service Area')
->blue()
->fillBlue()
->fillOpacity(0.2)
->radius(10000) // Radius in meters (default)
->radiusInKilometers(10) // Radius in kilometers
->radiusInMiles(6.2) // Radius in miles
->radiusInFeet(32808) // Radius in feet
];
}
use EduardoRibeiroDev\FilamentLeaflet\Layers\Shapes\CircleMarker;
CircleMarker::make(-23.5505, -46.6333)
->radius(45) // Radius in pixels
->red()
->fillRed()
->weight(2)
->title('Point of Interest');
use EduardoRibeiroDev\FilamentLeaflet\Layers\Shapes\Polygon;
// Define a polygon area
Polygon::make(
[-23.5505, -46.6333],
[-23.5515, -46.6343],
[-23.5525, -46.6323],
[-23.5505, -46.6333], // Close the polygon
)
->green()
->fillGreen()
->fillOpacity(0.3)
->title('Delivery Zone')
->popupContent('We deliver to this area');
// Or build point by point
Polygon::make()
->addPoint(-23.5505, -46.6333)
->addPoint(-23.5515, -46.6343)
->addPoint(-23.5525, -46.6323)
->addPoint(-23.5505, -46.6333)
->blue();
use EduardoRibeiroDev\FilamentLeaflet\Layers\Shapes\Rectangle;
// Using corner coordinates
Rectangle::make(
[-23.5505, -46.6333], // Southwest corner
[-23.5525, -46.6353] // Northeast corner
)
->orange()
->fillOrange()
->fillOpacity(0.2)
->title('Restricted Area');
// Alternative syntax
Rectangle::makeFromCoordinates(
-23.5505, -46.6333, // Southwest lat, lng
-23.5525, -46.6353 // Northeast lat, lng
)
->red();
use App\Models\DeliveryZone;
use EduardoRibeiroDev\FilamentLeaflet\Layers\Shapes\Circle;
use EduardoRibeiroDev\FilamentLeaflet\Layers\Shapes\Polygon;
use EduardoRibeiroDev\FilamentLeaflet\Layers\Shapes\Polyline;
use EduardoRibeiroDev\FilamentLeaflet\Layers\Shapes\Rectangle;
use EduardoRibeiroDev\FilamentLeaflet\Layers\Shapes\CircleMarker;
protected function getShapes(): array
{
return DeliveryZone::all()->map(function ($zone) {
// Circle from record
return Circle::fromRecord(
record: $zone,
coordsColumn: 'center_coordinates',
radiusColumn: 'coverage_radius_km',
titleColumn: 'name',
descriptionColumn: 'description',
popupFieldsColumns: ['address', 'radius'],
);
})->all();
}
use EduardoRibeiroDev\FilamentLeaflet\ValueObjects\Coordinate;
class DeliveryZone extends Model
{
protected $casts = [
'center_coordinates' => Coordinate::class,
];
}
Circle::make(-23.5505, -46.6333)
->radius(5000)
// Border styling
->color(Color::Blue) // Border color
->weight(3) // Border width in pixels
->opacity(0.8) // Border opacity (0-1)
->dashArray('5, 10') // Dashed border pattern
// Fill styling
->fillColor(Color::Green) // Fill color
->fillOpacity(0.3) // Fill opacity (0-1)
class MyMapWidget extends MapWidget
{
protected bool $hasEditLayersControl = true;
protected function getMarkers(): array
{
return [
Marker::make(-23.5505, -46.6333)
->title('Editable Marker')
->editable(), // Make this marker editable
Circle::make(-23.5505, -46.6333)
->radiusInKilometers(5)
->editable(), // Make this circle editable
];
}
}
LayerGroup::make([
Marker::make(-23.5505, -46.6333)->title('Point 1'),
Marker::make(-23.5515, -46.6343)->title('Point 2'),
Marker::make(-23.5525, -46.6353)->title('Point 3'),
])
->name('Editable Points')
->editable(), // All markers in the group are now editable
Marker::make(-23.5505, -46.6333)
->tooltip(
content: 'São Paulo City',
permanent: false,
direction: 'top',
options: ['offset' => [0, -20]]
);
// Or using individual methods
Marker::make(-23.5505, -46.6333)
->tooltipContent('São Paulo')
->tooltipPermanent(true)
->tooltipDirection('top');
protected int $defaultZoom = 12; // City level
protected int $maxZoom = 18; // Street level
protected int $minZoom = 3; // Country level
public function handleMapClick(float $latitude, float $longitude): void
{
logger("Map clicked", compact('latitude', 'longitude'));
}
public function getCustomStyles(): string
{
return <<<CSS
.custom-marker {
filter: hue-rotate(45deg);
}
.leaflet-popup-content {
font-family: 'Inter', sans-serif;
}
CSS;
}
public function getCustomScripts(): string
{
return <<<JS
function customFunction() {
// Your code
}
JS;
}
use EduardoRibeiroDev\FilamentLeaflet\ValueObjects\Coordinate;
class Location extends Model
{
protected $casts = [
'coordinates' => Coordinate::class, // Stores as { "lat": -23.5505, "lng": -46.6333 }
];
}
// Usage
$location = Location::first();
echo $location->coordinates->lat; // -23.5505
echo $location->coordinates->lng; // -46.6333
use EduardoRibeiroDev\FilamentLeaflet\ValueObjects\Coordinate;
class Store extends Model
{
protected $casts = [
// Maps to latitude and longitude columns
'location' => Coordinate::class,
];
}
// Usage
$store = Store::first();
echo $store->location->lat; // Reads from 'latitude' column
echo $store->location->lng; // Reads from 'longitude' column
// Migration
Schema::create('stores', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->decimal('latitude', 10, 8); // Stores lat
$table->decimal('longitude', 11, 8); // Stores lng
$table->timestamps();
});
// Model
class Store extends Model
{
protected $casts = [
'location' => Coordinate::class . ':latitude,longitude', // If the lat/lng columns don't follow the config default names, specify them here
];
}