mercynet/maps

A package to load maps with support for Leaflet and Google Maps

1.0.3 2024-10-08 10:35 UTC

This package is not auto-updated.

Last update: 2024-10-08 13:53:29 UTC


README

=======

Maps

Maps is a PHP library designed to facilitate the integration and rendering of various map providers, such as Leaflet and Google Maps, in web applications. It adheres to SOLID principles, design patterns, and clean code practices, ensuring maintainability and scalability. The package allows developers to either use built-in views for map rendering or customize their own views by providing necessary data. It includes comprehensive tests using PestPHP to ensure reliability and correctness. The package is structured to be easily extendable, allowing the addition of more map providers in the future.

Installation

  1. Clone the repository:
   git clone https://github.com/mercynet/maps-project.git
   cd maps-project
  1. Install dependencies using Composer:
   composer install

Configuration

Configure your map providers in src/config/maps.php:

return [
    'providers' => [
        'leaflet' => \Maps\Providers\Leaflet\LeafletMap::class,
        'google' => \Maps\Providers\GoogleMaps\GoogleMapsMap::class,
    ],
];

Usage

Google Maps

To use Google Maps, ensure you have a valid API key. Add the API key to the GoogleMapConfig class:

namespace Maps\Providers\GoogleMaps;

class GoogleMapConfig
{
    public static function defaultOptions(): array
    {
        return [
            'center' => [37.7749, -122.4194],
            'zoom' => 12,
            'mapType' => 'roadmap',
            'polygons' => [],
            'markers' => [],
            'overlays' => []
        ];
    }

    public static function getMapType(): string
    {
        return 'roadmap';
    }

    public static function getZoom(): int
    {
        return 12;
    }

    public static function getApiKey(): string
    {
        return 'YOUR_API_KEY';
    }
}

Example view file for Google Maps (src/Providers/GoogleMaps/Views/map.php):

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Google Map</title>
    <script src="https://maps.googleapis.com/maps/api/js?key=<?php echo $apiKey ?? ''; ?>"></script>
    <script>
        function initMap() {
            const mapOptions = {
                center: { lat: <?php echo $center[0] ?? 0; ?>, lng: <?php echo $center[1] ?? 0; ?> },
            zoom: <?php echo $zoom ?? 8; ?>,
            mapTypeId: '<?php echo $mapType ?? 'roadmap'; ?>'
        };
            const map = new google.maps.Map(document.getElementById('<?php echo $id ?? 'map'; ?>'), mapOptions);

            const markers = <?php echo json_encode($markers ?? []); ?>;
            markers.forEach(marker => {
                const markerOptions = {
                    position: { lat: marker.coordinates[0], lng: marker.coordinates[1] },
                    map: map,
                    icon: marker.icon
                };
                const mapMarker = new google.maps.Marker(markerOptions);
                if (marker.popupText) {
                    const infoWindow = new google.maps.InfoWindow({
                        content: marker.popupText
                    });
                    mapMarker.addListener('click', () => {
                        infoWindow.open(map, mapMarker);
                    });
                }
            });

            const overlays = <?php echo json_encode($overlays ?? []); ?>;
            overlays.forEach(overlay => {
                const overlayBounds = new google.maps.LatLngBounds(
                        new google.maps.LatLng(overlay.bounds[0][0], overlay.bounds[0][1]),
                        new google.maps.LatLng(overlay.bounds[1][0], overlay.bounds[1][1])
                );
                new google.maps.GroundOverlay(overlay.url, overlayBounds).setMap(map);
            });
        }
    </script>
</head>
<body onload="initMap()">
<div id="<?php echo $id ?? 'map'; ?>" style="width: 100%; height: 500px;"></div>
</body>
</html>

Leaflet

Example view file for Leaflet (src/Providers/Leaflet/Views/map.php):

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Leaflet Map</title>
    <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
    <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
    <script>
        function initMap() {
            const mapOptions = {
                center: ['<?php echo $center[0] ?? 0; ?>', '<?php echo $center[1] ?? 0; ?>'],
                zoom: <?php echo $zoom ?? 8; ?>
            };
            const map = L.map('<?php echo $id ?? 'map'; ?>').setView(mapOptions.center, mapOptions.zoom);

            L.tileLayer('<?php echo $tileLayer ?? ''; ?>', {
                maxZoom: <?php echo $maxZoom ?? 18; ?>
            }).addTo(map);

            // Adding custom markers
            const markers = <?php echo json_encode($markers ?? []); ?>;
            markers.forEach(marker => {
                L.marker(marker.coordinates, { icon: L.icon(marker.icon) }).addTo(map).bindPopup(marker.popupText);
            });

            // Adding overlays
            const overlays = <?php echo json_encode($overlays ?? []); ?>;
            overlays.forEach(overlay => {
                L.imageOverlay(overlay.url, overlay.bounds).addTo(map);
            });
        }
    </script>
</head>
<body onload="initMap()">
    <div id="<?php echo $id ?? 'map'; ?>" style="width: 100%; height: 500px;"></div>
</body>
</html>

Creating a Map Provider

You can create a map using the specific map class (e.g., LeafletMap):

use Maps\Providers\Leaflet\LeafletMap;

$map = new LeafletMap('mapId');

Creating a Map Using Factory

You can create a map using the MapProviderFactory:

use MapPackage\Factories\MapProviderFactory;

$map = MapProviderFactory::create('leaflet', 'mapId');

Rendering a Map

To render a map, use the render method of the map class:

$options = [
    'center' => [51.505, -0.09],
    'zoom' => 13,
    'tileLayer' => 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
    'maxZoom' => 18
];

echo $map->render($options);

Setting a Custom View

To set a custom view for rendering the map, use the setCustomView method:

$map->setCustomView('path/to/custom-view.php');

Handling Exceptions

MapPackage provides custom exceptions to handle specific errors. Here are some examples:

  • InvalidCenterException: Thrown when the center coordinates are invalid.
  • InvalidZoomException: Thrown when the zoom level is invalid.
  • InvalidTileLayerException: Thrown when the tile layer URL is invalid.
  • InvalidMaxZoomException: Thrown when the maximum zoom level is invalid.
  • InvalidViewPathException: Thrown when the custom view path is invalid.

Example of using exceptions:

use Maps\Exceptions\InvalidCenterException;
use Maps\Exceptions\InvalidZoomException;

try {
    echo $map->render($options);
} catch (InvalidCenterException $e) {
    echo "Error: " . $e->getMessage();
} catch (InvalidZoomException $e) {
    echo "Error: " . $e->getMessage();
}

Directory Structure

  • src/: Contains the source code of the package.
  • tests/: Contains the tests.
  • composer.json: Composer configuration file.

Testing

To run the tests, use PestPHP:

./vendor/bin/pest

Extending the Package

To add support for a new map provider, implement the MapInterface interface:

namespace MapPackage\Providers;

use MapPackage\Contracts\MapProvider;

class NewMapProvider implements MapProvider
{
    public function render(array $options): string
    {
        // Implementation for rendering the map
    }

    public function getData(array $options): array
    {
        // Implementation for providing map data
    }
}

Then, register the new provider with the MapProviderFactory using a configuration file or a service provider. Here is an example using a configuration file:

Configuration File

Create a configuration file config/map_providers.php:

return [
    'providers' => [
        'leaflet' => \MapPackage\Providers\LeafletProvider::class,
        'google' => \MapPackage\Providers\GoogleMapsProvider::class,
        'newmap' => \MapPackage\Providers\NewMapProvider::class,
    ],
];

License

This project is licensed under the MIT License. See the LICENSE file for more details.