PHP code example of cheesegrits / filament-google-maps
1. Go to this page and download the library: Download cheesegrits/filament-google-maps 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/ */
cheesegrits / filament-google-maps example snippets
use Cheesegrits\FilamentGoogleMaps\Fields\Map
...
->schema[
...
// must use the computed attribute name you used on your model
// which must NOT exist on the table itself
Map::make('location'),
...
]
GOOGLE_MAPS_API_KEY=your_map_key_here
return [
/*
| Your Google Maps API key, usually set in .env (but see 'keys' section below).
*/
'key' => env('GOOGLE_MAPS_API_KEY'),
/*
| If you need to use both a browser key (restricted by HTTP Referrer) for use in the Javascript API on the
| front end, and a server key (restricted by IP address) for server side API calls, you will need to set those
| keys here (or preferably set the appropriate .env variables)
*/
'keys' => [
'web_key' => env('FILAMENT_GOOGLE_MAPS_WEB_API_KEY', env('GOOGLE_MAPS_API_KEY')),
'server_key' => env('FILAMENT_GOOGLE_MAPS_SERVER_API_KEY', env('GOOGLE_MAPS_API_KEY')),
'signing_key' => env('FILAMENT_GOOGLE_MAPS_SIGNING_KEY', null),
],
/*
| By default the browser side Google Maps API will be loaded with just the 'places' library. If you need
| additional libraries for your own custom code, just add them as a comma separated list here (or in the
| appropriate env key)
*/
'libraries' => env('FILAMENT_GOOGLE_MAPS_ADDITIONAL_LIBRARIES', null),
/*
| Region and country codes.
|
| Google STRONGLY ENCOURAGED you to set a region code (US, GB, etc) which they use to bias the results
|
| https://developers.google.com/maps/coverage
|
| Google discourage you from setting a language, as this should be controlled by the user's browser setting,
| and only controls localization of the UI. So we do not apply a language code to the Javascript API. However,
| we will apply any language code set here to server side API calls like static maps (as used in the Column).
|
| https://developers.google.com/maps/faq#languagesupport
*/
'locale' => [
'region' => env('FILAMENT_GOOGLE_MAPS_REGION_CODE', null),
'language' => env('FILAMENT_GOOGLE_MAPS_LANGUAGE_CODE', null),
],
/*
| Rate limit for API calls, although you REALLY should also set usage quota limits in your Google Console
*/
'rate-limit' => env('FILAMENT_GOOGLE_MAPS_RATE_LIMIT', 150),
/*
| Log channel to use, default is 'null' (no logging), set to your desired channel from logging.php if you want
| logs. Typically only useful for debugging, or if you want to keep track of a scheduled geocoding task.
*/
'log' => [
'channel' => env('FILAMENT_GOOGLE_MAPS_LOG_CHANNEL', 'null'),
],
/*
| Cache store and duration (in seconds) to use for API results. Specify store as null to use the default from
| your cache.php config, false will disable caching (STRONGLY discouraged, unless you want a big Google
| API bill!). For heavy usage, we suggest using a dedicated Redis store. Max cache duration permitted by
| Google is 30 days.
*/
'cache' => [
'duration' => env('FILAMENT_GOOGLE_MAPS_CACHE_DURATION_SECONDS', 60 * 60 * 24 * 30),
'store' => env('FILAMENT_GOOGLE_MAPS_CACHE_STORE', null),
]
/*
| Force https for Google API calls, rather than matching the schema of the current request,
| may be needed if your app is behind a reverse proxy.
*/
'force-https' => env('FILAMENT_GOOGLE_MAPS_FORCE_HTTPS', false),
];
use Cheesegrits\FilamentGoogleMaps\Fields\Map
...
->schema[
...
Map::make('location'),
...
]
use Cheesegrits\FilamentGoogleMaps\Fields\Map
...
Map::make('location')
->mapControls([
'mapTypeControl' => true,
'scaleControl' => true,
'streetViewControl' => true,
'rotateControl' => true,
'fullscreenControl' => true,
'searchBoxControl' => false, // creates geocomplete field inside map
'zoomControl' => false,
])
->height(fn () => '400px') // map height (width is controlled by Filament options)
->defaultZoom(5) // default zoom level when opening form
->autocomplete('full_address') // field on form to use as Places geocompletion field
->autocompleteReverse(true) // reverse geocode marker location to autocomplete field
->reverseGeocode([
'street' => '%n %S',
'city' => '%L',
'state' => '%A1',
'zip' => '%z',
]) // reverse geocode marker location to form fields, see notes below
->debug() // prints reverse geocode format strings to the debug console
->defaultLocation([39.526610, -107.727261]) // default for new forms
->draggable() // allow dragging to move marker
->clickable(false) // allow clicking to move marker
->type('roadmap') // map type (hybrid, satellite, roadmap, terrain)
->geolocate() // adds a button to request device location and set map marker accordingly
->geolocateLabel('Get Location') // overrides the default label for geolocate button
->geolocateOnLoad(true, false) // geolocate on load, second arg 'always' (default false, only for new form))
->layers([
'https://googlearchive.github.io/js-v2-samples/ggeoxml/cta.kml',
]) // array of KML layer URLs to add to the map
->geoJson('https://fgm.test/storage/AGEBS01.geojson') // GeoJSON file, URL or JSON
->geoJsonContainsField('geojson') // field to capture GeoJSON polygon(s) which contain the map marker
Forms\Components\TextInput::make('latitude')
->reactive()
->afterStateUpdated(function ($state, callable $get, callable $set) {
$set('location', [
'lat' => floatVal($state),
'lng' => floatVal($get('longitude')),
]);
})
->lazy(), // important to use lazy, to avoid updates as you type
Forms\Components\TextInput::make('longitude')
->reactive()
->afterStateUpdated(function ($state, callable $get, callable $set) {
$set('location', [
'lat' => floatval($get('latitude')),
'lng' => floatVal($state),
]);
})
->lazy(), // important to use lazy, to avoid updates as you type
//
use Cheesegrits\FilamentGoogleMaps\Concerns\InteractsWithMaps;
class EditLocation extends EditRecord
{
use InteractsWithMaps;
//
}
Map::make('location')
->reverseGeocodeUsing(function (callable $set, array $results) {
// get whatever you need from $results, and $set your field(s)
$set('street', $results['address_components'][1]['long_name'])
})
Map::make('location')
->placeUpdatedUsing(function (callable $set, array $place) {
// do whatever you need with the $place results, and $set your field(s)
$set('city', 'foo wibble');
}),
use Cheesegrits\FilamentGoogleMaps\Fields\Geocomplete
...
Geocomplete::make('full_address'),
use Cheesegrits\FilamentGoogleMaps\Fields\Geocomplete
...
Geocomplete::make('location') // field name must be the computed attribute name on your model
->isLocation()
->geocodeOnLoad(), // server side geocode of lat/lng to address when form is loaded
Geocomplete::make('location')
->isLocation()
->reverseGeocode([
'city' => '%L',
'zip' => '%z',
'state' => '%A1',
'street' => '%n %S',
])
->countries(['us']) // restrict autocomplete results to these countries
->debug() // output the results of reverse geocoding in the browser console, useful for figuring out symbol formats
->updateLatLng() // update the lat/lng fields on your form when a Place is selected
->maxLength(1024)
->minChars(0) // minimum number of characters before autocomplete starts
->prefix('Choose:')
->placeholder('Start typing an address ...')
->geolocate() // add a suffix button which requests and reverse geocodes the device location
->geolocateIcon('heroicon-o-map'), // override the default icon for the geolocate button
use Cheesegrits\FilamentGoogleMaps\Infolists\MapEntry;
//
public function infolist(Infolist $infolist): Infolist
{
return $infolist->schema([
TextEntry::make('street'),
TextEntry::make('city'),
TextEntry::make('state'),
TextEntry::make('zip'),
MapEntry::make('location')
->columnSpan(2),
]);
}
WidgetMap::make('widget_map')
->mapControls([
'zoomControl' => true,
])
->markers(function () {
// retrieve and display all records from the Geocode model
$markers = [];
Geocode::all()->each(function (Geocode $record) use (&$markers) {
$markers[] = [
'location' => [
'lat' => $record->lat ? round(floatval($record->lat), 8) : 0,
'lng' => $record->lng ? round(floatval($record->lat), 8) : 0,
],
'label' => $record->name,
];
});
return $markers;
})
->columnSpan(2)
use Cheesegrits\FilamentGoogleMaps\Columns\MapColumn;
...
MapColumn::make('location')
->extraAttributes([
'class' => 'my-funky-class'
]) // Optionally set any additional attributes, merged into the wrapper div around the image tag
->extraImgAttributes(
fn ($record): array => ['title' => $record->latitude . ',' . $record->longitude]
) // Optionally set any additional attributes you want on the img tag
->height('150') // API setting for map height in PX
->width('250') // API setting got map width in PX
->type('hybrid') // API setting for map type (hybrid, satellite, roadmap, tarrain)
->zoom(15) // API setting for zoom (1 through 20)
->ttl(60 * 60 * 24 * 30), // number of seconds to cache image before refetching from API
use Cheesegrits\FilamentGoogleMaps\Filters\RadiusFilter;
...
RadiusFilter::make('radius')
->latitude('lat') // optional lat and lng fields on your table, default to the getLatLngAttributes() method
->longitude('lng') // you should have one your model from the fgm:model-code command when you installed
->selectUnit() // add a Kilometer / Miles select
->kilometers() // use (or default the select to) kilometers (defaults to miles)
->section('Radius Search') // optionally wrap the filter in a section with heading
RadiusFilter::make('radius')
->attribute('place.location') // the relationship, with the computed location attribute
->color('primary')
->icon('heroicon-m-map'),
use Cheesegrits\FilamentGoogleMaps\Actions\RadiusAction;
//
protected function getTableActions(): array
{
return [
//
RadiusAction::make(),
];
}
use Cheesegrits\FilamentGoogleMaps\Actions\RadiusAction;
//
protected function getTableActions(): array
{
return [
//
RadiusAction::make()
->relationship('location')
->color('primary')
->icon('heroicon-m-map'),
];
}
use Cheesegrits\FilamentGoogleMaps\Actions\StaticMapAction;
//
->bulkActions([
//
StaticMapAction::make(),
//
]);
//
namespace App\Http\Livewire\Widgets;
use App\Models\Dealerships;
use Cheesegrits\FilamentGoogleMaps\Widgets\MapWidget;
class DealershipMap extends MapWidget
{
protected static ?string $heading = 'Dealership Locations';
protected static ?bool $clustering = true;
protected function getData(): array
{
$dealerships = Dealerships::all();
$data = [];
foreach ($dealerships as $dealership)
{
if ($dealership->latitude && $dealership->longitude)
{
/**
* Each element in the returned data must be an array
* containing a 'location' array of 'lat' and 'lng',
* and a 'label' string.
*
* You should also aan 'id' attribute for internal use by this plugin.
*/
$data[] = [
'location' => [
'lat' => $dealership->latitude,
'lng' => $dealership->longitude,
],
'label' => $dealership->name,
'id' => $dealership->getKey(),
/**
* Optionally you can provide custom icons for the map markers,
* either as scalable SVG's, or PNG, which doesn't support scaling.
* If you don't provide icons, the map will use the standard Google marker pin.
*/
'icon' => [
'url' => url('images/dealership.svg'),
'type' => 'svg',
'scale' => [35,35],
],
];
}
}
return $data;
}
}
use Filament\Actions\Action;
use Filament\Infolists\Components\Card;
use Filament\Infolists\Components\TextEntry;
class DealershipMap extends MapWidget
{
// must be the name of both the Action and your method that returns the Action
protected static ?string $markerAction = 'markerAction';
//
public function markerAction(): Action
{
return Action::make('markerAction')
->label('Details')
->infolist([
Card::make([
TextEntry::make('name'),
TextEntry::make('street'),
TextEntry::make('city'),
TextEntry::make('state'),
TextEntry::make('zip'),
TextEntry::make('formatted_address'),
])
->columns(3)
])
->record(function (array $arguments) {
return array_key_exists('model_id', $arguments) ? Location::find($arguments['model_id']) : null;
})
->modalSubmitAction(false);
}
//
}