├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── composer.json ├── docs └── Examples.php └── src ├── Directions.php ├── Facade └── GoogleMapsFacade.php ├── GoogleMaps.php ├── Parameters.php ├── Routes.php ├── ServiceProvider └── GoogleMapsServiceProvider.php ├── WebService.php └── config └── googlemaps.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/ 2 | composer.lock 3 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at alexpechkarev@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Alexander Pechkarev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Collection of Google Maps API Web Services for Laravel 2 | 3 | Provides a convenient way of setting up and making requests to Google Maps APIs from your [Laravel](http://laravel.com/) application. 4 | 5 | For services documentation, API key usage limits, and terms of service, please refer to the official Google Maps documentation: 6 | - [Google Maps API Web Services](https://developers.google.com/maps/documentation/webservices/) 7 | - [Maps API Terms of Service & License Restrictions](https://developers.google.com/maps/terms#section_10_12). 8 | 9 | --- 10 | 11 | ### Important Update: Routes API replaces Directions & Distance Matrix 12 | 13 | **The Google Maps Directions API and Distance Matrix API are deprecated.** 14 | 15 | This package now includes support for the **new Google Maps Routes API**, which is the recommended replacement for calculating routes and route matrices. The Routes API offers enhanced features and performance. 16 | 17 | **Please update your application code to use the `routes` and `routematrix` services provided by this package instead of the deprecated `directions` and `distancematrix` services.** 18 | 19 | --- 20 | 21 | ## Features 22 | This package provides easy access to the following Google Maps APIs: 23 | 24 | - **[Routes API](https://developers.google.com/maps/documentation/routes/route-usecases) (Recommended replacement for Directions & Distance Matrix)** 25 | - `routes`: Compute routes between locations. 26 | - `routematrix`: Compute route matrices between origins and destinations. 27 | - [Elevation API](https://developers.google.com/maps/documentation/elevation/) 28 | - [Geocoding API](https://developers.google.com/maps/documentation/geocoding/) 29 | - [Geolocation API](https://developers.google.com/maps/documentation/geolocation/) 30 | - [Roads API](https://developers.google.com/maps/documentation/roads/) 31 | - [Time Zone API](https://developers.google.com/maps/documentation/timezone/) 32 | - [Places API Web Services](https://developers.google.com/places/web-service/) 33 | 34 | --- 35 | 36 | ## Dependency 37 | 38 | - [PHP cURL](http://php.net/manual/en/curl.installation.php) 39 | - [PHP >= 7.3.0](http://php.net/) 40 | 41 | 42 | ## API Deprecation Notes 43 | 44 | In addition to the Directions and Distance Matrix deprecation mentioned above: 45 | 46 | **Places API:** 47 | - **Removed Features:** Requests attempting to use Place Add, Place Delete, or Radar Search will receive an error. [More Info](https://cloud.google.com/blog/products/maps-platform/announcing-deprecation-of-place-add) 48 | - **Deprecated Parameters/Fields:** 49 | - Nearby Search: The `types` parameter is deprecated; use the `type` parameter (string) instead. 50 | - Place Details: The `reference` field is deprecated; use `placeid` (this package uses `placeid` by default). 51 | - Place Add & Place Autocomplete: Still use the `types` parameter as per Google's documentation (links provided in the original README). 52 | 53 | --- 54 | 55 | ## Installation 56 | 57 | Issue following command in console: 58 | 59 | ```php 60 | composer require alexpechkarev/google-maps 61 | ``` 62 | 63 | ## Configuration 64 | 65 | Register Service Provider & Facade (in `config/app.php`): 66 | 67 | ```php 68 | 'providers' => [ 69 | ... 70 | GoogleMaps\ServiceProvider\GoogleMapsServiceProvider::class, 71 | ] 72 | 73 | 'aliases' => [ 74 | ... 75 | 'GoogleMaps' => GoogleMaps\Facade\GoogleMapsFacade::class, 76 | ] 77 | ``` 78 | 79 | Publish configuration file: 80 | 81 | ```php 82 | php artisan vendor:publish --tag=googlemaps 83 | ``` 84 | 85 | Add API Key: Open **config/googlemaps.php*** and add your Google Maps API key: 86 | 87 | ```php 88 | /* 89 | |---------------------------------- 90 | | Service Keys 91 | |------------------------------------ 92 | */ 93 | 94 | 'key' => 'ADD YOUR SERVICE KEY HERE', 95 | ``` 96 | 97 | If you like to use different keys for any of the services, you can overwrite master API Key by specifying it in the `service` array for selected web service. 98 | 99 | ## Usage 100 | 101 | General Pattern: 102 | Load the desired service using `\GoogleMaps::load('service-name')`. 103 | Set parameters using `setParam([...])` or `setParamByKey('key', 'value')`. 104 | Execute the request: 105 | - Use `->get()` for all APIs EXCEPT the Routes API. 106 | - Use `->fetch()` ONLY for the Routes API (routes and routematrix services). 107 | 108 | #### Example: Geocoding API (using `get()`): 109 | ```php 110 | $response = \GoogleMaps::load('geocoding') 111 | ->setParam (['address' =>'santa cruz']) 112 | ->get(); 113 | ``` 114 | 115 | By default, where appropriate, `output` parameter set to `JSON`. Don't forget to decode JSON string into PHP variable. 116 | 117 | 118 | #### Example: Routes API - Compute Route (using `fetch()`): 119 | 120 | Note: The Routes API uses the fetch() method and returns a PHP array directly (no JSON decoding needed). 121 | Note: The config for routes includes a decodePolyline parameter (default true), which adds a decodedPolyline key to the response if a polyline is present. 122 | 123 | ```php 124 | $routeParams = [ 125 | 'origin' => [ /* ... origin details ... */ ], 126 | 'destination' => [ /* ... destination details ... */ ], 127 | 'travelMode' => 'DRIVE', 128 | // ... other Routes API parameters ... 129 | ]; 130 | 131 | $responseArray = \GoogleMaps::load('routes') // Use 'routes' service 132 | ->setParam($routeParams) 133 | ->setFieldMask('routes.duration,routes.distanceMeters,routes.polyline.encodedPolyline') // optional - used to specify fields to return 134 | ->fetch(); // Use fetch() for Routes API 135 | 136 | // $responseArray is already a PHP array 137 | if (!empty($responseArray['routes'])) { 138 | // Process the route data 139 | } else { 140 | // Handle errors or no routes found 141 | } 142 | ``` 143 | 144 | #### Example: Routes API - Compute Route Matrix (using `fetch()`): 145 | 146 | ```php 147 | $matrixParams = [ 148 | 'origins' => [ /* ... array of origins ... */ ], 149 | 'destinations' => [ /* ... array of destinations ... */ ], 150 | 'travelMode' => 'DRIVE', 151 | // ... other Route Matrix parameters ... 152 | ]; 153 | 154 | $responseArray = \GoogleMaps::load('routematrix') // Use 'routematrix' service 155 | ->setParam($matrixParams) 156 | ->setFieldMask('originIndex,destinationIndex,duration,distanceMeters,status,condition') // optional - used to specify fields to return 157 | ->fetch(); // Use fetch() for Routes API 158 | 159 | // $responseArray is already a PHP array 160 | // Process the matrix data 161 | ``` 162 | 163 | Required parameters can be specified as an array of `key:value` pairs 164 | 165 | ```php 166 | $response = \GoogleMaps::load('geocoding') 167 | ->setParam ([ 168 | 'address' =>'santa cruz', 169 | 'components' => [ 170 | 'administrative_area' => 'TX', 171 | 'country' => 'US', 172 | ] 173 | ]) 174 | ->get(); 175 | ``` 176 | 177 | Alternatively parameters can be set using `setParamByKey()` method. For deeply nested array use "dot" notation as per example below. 178 | 179 | ```php 180 | $endpoint = \GoogleMaps::load('geocoding') 181 | ->setParamByKey('address', 'santa cruz') 182 | ->setParamByKey('components.administrative_area', 'TX') //return $this 183 | ... 184 | ``` 185 | 186 | 187 | 188 | 189 | ## Available methods 190 | 191 | - [`load( $serviceName )`](#load): Loads the specified web service configuration. Returns $this. 192 | - [`setEndpoint( $endpoint )`](#setEndpoint): Sets the desired response format (json or xml) for APIs using get(). Default is json. Not applicable to Routes API (fetch()). Returns $this. 193 | - [`getEndpoint()`](#getEndpoint): Gets the currently configured endpoint format (json or xml). 194 | - [`setParamByKey( $key, $value)`](#setParamByKey): Sets a single request parameter. Use 'dot' notation for nested arrays (e.g., components.country). Returns $this. 195 | - [`setParam( $parameters)`](#setParam): Sets multiple request parameters from an array. Returns $this. 196 | - [`get()`](#get): (**For all APIs EXCEPT Routes API**) Executes the request. Returns a JSON string (or XML string if configured). If $key is provided (using 'dot' notation), attempts to return only that part of the response. 197 | - [`fetch()`](#fetch): (**ONLY for Routes API** - `routes` and `routematrix`) Executes the request against the Routes API. Returns a decoded PHP array directly or throws an `ErrorException`. 198 | - [`containsLocation( $lat, $lng )`](#containsLocation): (**Routes API only**) Checks if a point falls within the polygon returned by a routes API call. Requires a prior `setParam()` call for the route. Returns boolean. 199 | - [`isLocationOnEdge( $lat, $lng, $tolrance)`](#isLocationOnEdge): (**Routes API only**) Checks if a point falls on or near the polyline returned by a routes API call. Requires a prior `setParam()` call for the route. Returns boolean. 200 | 201 | --- 202 | 203 | 204 | **`load( $serviceName )`** - load web service by name 205 | 206 | Accepts string as parameter, web service name as specified in configuration file. 207 | Returns reference to it's self. 208 | 209 | ```php 210 | \GoogleMaps::load('geocoding') 211 | ... 212 | ``` 213 | 214 | --- 215 | 216 | 217 | **`setEndpoint( $endpoint )`** - set request output 218 | 219 | Accepts string as parameter, `json` or `xml`, if omitted defaulted to `json`. 220 | Returns reference to it's self. 221 | 222 | ```php 223 | $response = \GoogleMaps::load('geocoding') 224 | ->setEndpoint('json') // return $this 225 | ... 226 | ``` 227 | --- 228 | 229 | 230 | **`getEndpoint()`** - get current request output 231 | 232 | Returns string. 233 | 234 | ```php 235 | $endpoint = \GoogleMaps::load('geocoding') 236 | ->setEndpoint('json') 237 | ->getEndpoint(); 238 | 239 | echo $endpoint; // output 'json' 240 | ``` 241 | 242 | --- 243 | 244 | 245 | **`setParamByKey( $key, $value )`** - set request parameter using key:value pair 246 | 247 | Accepts two parameters: 248 | 249 | - `key` - body parameter name 250 | - `value` - body parameter value 251 | 252 | Deeply nested array can use 'dot' notation to assign value. 253 | Returns reference to it's self. 254 | 255 | ```php 256 | $endpoint = \GoogleMaps::load('geocoding') 257 | ->setParamByKey('address', 'santa cruz') 258 | ->setParamByKey('components.administrative_area', 'TX') //return $this 259 | ... 260 | ``` 261 | 262 | --- 263 | 264 | 265 | **`setParam( $parameters)`** - set all request parameters at once 266 | 267 | Accepts array of parameters 268 | Returns reference to it's self. 269 | 270 | ```php 271 | $response = \GoogleMaps::load('geocoding') 272 | ->setParam([ 273 | 'address' => 'santa cruz', 274 | 'components' => [ 275 | 'administrative_area' => 'TX', 276 | 'country' => 'US', 277 | ] 278 | ]) // return $this 279 | ... 280 | ``` 281 | 282 | --- 283 | 284 | 285 | 286 | - **`get()`** - perform web service request (irrespectively to request type POST or GET ) 287 | - **`get( $key )`** - accepts string response body key, use 'dot' notation for deeply nested array 288 | 289 | This method is not Available for Routes API. 290 | 291 | Returns web service response in the format specified by **`setEndpoint()`** method, if omitted defaulted to `JSON`. 292 | Use `json_decode()` to convert JSON string into PHP variable. See [Processing Response](https://developers.google.com/maps/documentation/webservices/#Parsing) for more details on parsing returning output. 293 | 294 | ```php 295 | $response = \GoogleMaps::load('geocoding') 296 | ->setParamByKey('address', 'santa cruz') 297 | ->setParamByKey('components.administrative_area', 'TX') 298 | ->get(); 299 | 300 | var_dump( json_decode( $response ) ); // output 301 | 302 | /* 303 | {\n 304 | "results" : [\n 305 | {\n 306 | "address_components" : [\n 307 | {\n 308 | "long_name" : "277",\n 309 | "short_name" : "277",\n 310 | "types" : [ "street_number" ]\n 311 | },\n 312 | ... 313 | */ 314 | ``` 315 | 316 | 317 | 318 | Example with `$key` parameter 319 | 320 | ```php 321 | $response = \GoogleMaps::load('geocoding') 322 | ->setParamByKey('latlng', '40.714224,-73.961452') 323 | ->get('results.formatted_address'); 324 | 325 | var_dump( json_decode( $response ) ); // output 326 | 327 | /* 328 | array:1 [▼ 329 | "results" => array:9 [▼ 330 | 0 => array:1 [▼ 331 | "formatted_address" => "277 Bedford Ave, Brooklyn, NY 11211, USA" 332 | ] 333 | 1 => array:1 [▼ 334 | "formatted_address" => "Grand St/Bedford Av, Brooklyn, NY 11211, USA" 335 | ] 336 | ... 337 | */ 338 | ``` 339 | --- 340 | 341 | 342 | 343 | - **`fetch()`** - only available for Routes API (whith 'routes' or 'routematrix' services) 344 | 345 | This method is ONLY available for Routes API. 346 | Note: config for routes included **decodePolyline** parameter, default **true**. If **true** it will attempts to decode the `polilyne.encodedPolyline` and add `decodePolyline` parameter to the response. 347 | 348 | Returns an **array** web service response or thows an **ErrorException**. 349 | See [Request Body](https://developers.google.com/maps/documentation/routes/reference/rest/v2/TopLevel/computeRoutes#request-body) for details. 350 | 351 | ```php 352 | $response = \GoogleMaps::load('routes') 353 | ->setParam($reqRoute) // <-- array see config file for all available parameters or Request Body 354 | ->fetch(); 355 | ``` 356 | 357 | --- 358 | 359 | 360 | **`isLocationOnEdge( $lat, $lng, $tolrance = 0.1 )`** - To determine whether a point falls on or near a polyline, or on or near the edge of a polygon, pass the point, the polyline/polygon, and optionally a tolerance value in degrees. 361 | 362 | This method only available with Google Maps Routes API. 363 | 364 | Accepted parameter: 365 | 366 | - `$lat` - double latitude 367 | - `$lng` - double longitude 368 | - `$tolrance` - double 369 | 370 | ```php 371 | $response = \GoogleMaps::load('routes') 372 | ->setParam([ 373 | 'origin' => [ 374 | 'location' => [ 375 | 'latLng' => [ 376 | 'latitude' => 37.419734, 377 | 'longitude' => -122.0827784, 378 | ], 379 | ], 380 | ], 381 | 'destination' => [ 382 | 'location' => [ 383 | 'latLng' => [ 384 | 'latitude' => 37.417670, 385 | 'longitude' => -122.079595, 386 | ], 387 | ], 388 | ], 389 | 'travelMode' => 'DRIVE', 390 | 'routingPreference' => 'TRAFFIC_AWARE', 391 | 'computeAlternativeRoutes' => false, 392 | 'routeModifiers' => [ 393 | 'avoidTolls' => false, 394 | 'avoidHighways' => false, 395 | 'avoidFerries' => false, 396 | ], 397 | 'languageCode' => 'en-US', 398 | 'units' => 'IMPERIAL', 399 | ]) 400 | ->isLocationOnEdge(37.41665,-122.08175); 401 | 402 | dd( $response ); // true 403 | ``` 404 | 405 | --- 406 | 407 | 408 | **`containsLocation( $lat, $lng )`** -To find whether a given point falls within a polygon. 409 | 410 | This method only available with Google Maps Routes API. 411 | 412 | Accepted parameter: 413 | 414 | - `$lat` - double latitude 415 | - `$lng` - double longitude 416 | 417 | ```php 418 | $response = \GoogleMaps::load('routes') 419 | ->setParam([ 420 | 'origin' => [ 421 | 'location' => [ 422 | 'latLng' => [ 423 | 'latitude' => 37.419734, 424 | 'longitude' => -122.0827784, 425 | ], 426 | ], 427 | ], 428 | 'destination' => [ 429 | 'location' => [ 430 | 'latLng' => [ 431 | 'latitude' => 37.417670, 432 | 'longitude' => -122.079595, 433 | ], 434 | ], 435 | ], 436 | 'travelMode' => 'DRIVE', 437 | 'routingPreference' => 'TRAFFIC_AWARE', 438 | 'computeAlternativeRoutes' => false, 439 | 'routeModifiers' => [ 440 | 'avoidTolls' => false, 441 | 'avoidHighways' => false, 442 | 'avoidFerries' => false, 443 | ], 444 | 'languageCode' => 'en-US', 445 | 'units' => 'IMPERIAL', 446 | ]) 447 | ->containsLocation(37.41764,-122.08293); 448 | 449 | dd( $response ); // true 450 | ``` 451 | 452 | 453 | 454 | 455 | ## Support 456 | 457 | [Please open an issue on GitHub](https://github.com/alexpechkarev/google-maps/issues) 458 | 459 | ## License 460 | 461 | Collection of Google Maps API Web Services for Laravel is released under the MIT License. See the bundled 462 | [LICENSE](https://github.com/alexpechkarev/google-maps/blob/master/LICENSE) 463 | file for details. 464 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "alexpechkarev/google-maps", 3 | "description": "Collection of Google Maps API Web Services for Laravel", 4 | "keywords": [ 5 | "google maps api", 6 | "google maps api for laravel", 7 | "google maps web service for laravel", 8 | "laravel google maps api", 9 | "geocoding api", 10 | "routes api", 11 | "elevation api", 12 | "geolocation api", 13 | "roads api", 14 | "time zone api", 15 | "places api web service" 16 | ], 17 | "homepage": "https://alexpechkarev.github.io/google-maps/", 18 | "license": "MIT", 19 | "authors": [ 20 | { 21 | "name": "Alexander Pechkarev", 22 | "email": "alexpechkarev@gmail.com" 23 | } 24 | ], 25 | "minimum-stability": "stable", 26 | "require": { 27 | "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.4", 28 | "illuminate/config": "^8.0|^9.0|^10.0|^11.0|^12.4", 29 | "alexpechkarev/geometry-library": "^1.0.5", 30 | "ext-json": "*", 31 | "ext-curl": "*", 32 | "jbroadway/urlify": "^1.2.4-stable" 33 | }, 34 | "require-dev": { 35 | "phpunit/phpunit": "^9.6|^10.5" 36 | }, 37 | "autoload": { 38 | "psr-4": { 39 | "GoogleMaps\\": "src/" 40 | } 41 | }, 42 | "extra": { 43 | "branch-alias": { 44 | "dev-master": "12.x-dev" 45 | }, 46 | "laravel": { 47 | "providers": [ 48 | "GoogleMaps\\ServiceProvider\\GoogleMapsServiceProvider" 49 | ], 50 | "aliases": { 51 | "GoogleMaps": "GoogleMaps\\Facade\\GoogleMapsFacade" 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /docs/Examples.php: -------------------------------------------------------------------------------- 1 | setParamByKey('place_id', 'ChIJd8BlQ2BZwokRAFUEcm_qrcA') 37 | ->get(); 38 | 39 | 40 | /** 41 | * Reverse geocoding with components parameters 42 | */ 43 | $d['b'] = \GoogleMaps::load('geocoding') 44 | > setParamByKey('latlng', '40.714224,-73.961452') 45 | ->setParamByKey('components.administrative_area', 'TX') 46 | ->setParamByKey('components.country', 'US') 47 | ->get(); 48 | 49 | /** 50 | * Setting all parameters at once and retrieve locations parameters from response 51 | */ 52 | $d['c'] = \GoogleMaps::load('geocoding') 53 | 54 | ->setParam([ 55 | 'address' => 'santa cruz', 56 | 'components' => [ 57 | 'administrative_area' => 'TX', 58 | 'country' => 'US', 59 | ] 60 | ]) 61 | ->getResponseByKey('results.geometry.location'); 62 | 63 | 64 | dd($d); 65 | } 66 | 67 | public function getRoutes() 68 | { 69 | $reqRoute = [ 70 | 'origin' => [ 71 | 'location' => [ 72 | 'latLng' => [ 73 | 'latitude' => 37.419734, 74 | 'longitude' => -122.0827784, 75 | ], 76 | ], 77 | ], 78 | 'destination' => [ 79 | 'location' => [ 80 | 'latLng' => [ 81 | 'latitude' => 37.417670, 82 | 'longitude' => -122.079595, 83 | ], 84 | ], 85 | ], 86 | 'travelMode' => 'DRIVE', 87 | 'routingPreference' => 'TRAFFIC_AWARE', 88 | 'computeAlternativeRoutes' => false, 89 | 'routeModifiers' => [ 90 | 'avoidTolls' => false, 91 | 'avoidHighways' => false, 92 | 'avoidFerries' => false, 93 | ], 94 | 'languageCode' => 'en-US', 95 | 'units' => 'IMPERIAL', 96 | ]; 97 | $r = \GoogleMaps::load('routes') 98 | ->setParam($reqRoute) 99 | #->setFieldMask('routes.duration,routes.distanceMeters,routes.polyline.encodedPolyline') // optional - specify which fields to return 100 | ->fetch(); 101 | #->isLocationOnEdge(37.41665,-122.08175); 102 | #->containsLocation(37.41764,-122.08293); 103 | 104 | dd($r); 105 | } 106 | 107 | public function getRouteMatrix() 108 | { 109 | 110 | $reqRouteMatrix = [ 111 | 'origins' => [ 112 | [ 113 | 'waypoint' => [ 114 | 'location' => [ 115 | 'latLng' => [ 116 | 'latitude' => 37.420761, 117 | 'longitude' => -122.081356, 118 | ], 119 | ], 120 | ], 121 | ], 122 | [ 123 | 'waypoint' => [ 124 | 'location' => [ 125 | 'latLng' => [ 126 | 'latitude' => 37.403184, 127 | 'longitude' => -122.097371, 128 | ], 129 | ], 130 | ], 131 | ], 132 | ], 133 | 'destinations' => [ 134 | [ 135 | 'waypoint' => [ 136 | 'location' => [ 137 | 'latLng' => [ 138 | 'latitude' => 37.420999, 139 | 'longitude' => -122.086894, 140 | ], 141 | ], 142 | ], 143 | ], 144 | [ 145 | 'waypoint' => [ 146 | 'location' => [ 147 | 'latLng' => [ 148 | 'latitude' => 37.383047, 149 | 'longitude' => -122.044651, 150 | ], 151 | ], 152 | ], 153 | ], 154 | ], 155 | // Optional parameters 156 | "travelMode" => "DRIVE", 157 | "routingPreference" => "TRAFFIC_AWARE" 158 | ]; 159 | $r = \GoogleMaps::load('routematrix') 160 | ->setParam($reqRouteMatrix) 161 | ->setFieldMask('originIndex,destinationIndex,duration,distanceMeters,status,condition') // optional - specify which fields to return 162 | ->fetch(); 163 | 164 | 165 | dd($r); 166 | } 167 | 168 | public function getElevation() 169 | { 170 | 171 | $d['a'] = \GoogleMaps::load('elevation') 172 | ->setParamByKey('locations', '39.7391536,-104.9847034') // can be given as an array ['36.578581,-118.291994', '36.23998,-116.83171'] 173 | ->get(); 174 | 175 | $d['b'] = \GoogleMaps::load('elevation') 176 | ->setParamByKey('path', ['40.714728,-73.998672', '-34.397,150.644']) 177 | ->setParamByKey('samples', 3) 178 | ->get(); 179 | 180 | $d['c'] = \GoogleMaps::load('elevation') 181 | ->setParamByKey('path', 'enc:gfo}EtohhUxD@bAxJmGF') 182 | ->setParamByKey('samples', 3) 183 | ->getResponseByKey('results.elevation'); 184 | 185 | dd($d); 186 | } 187 | 188 | 189 | 190 | public function getGeolocation() 191 | { 192 | 193 | 194 | 195 | $data = [ 196 | 'homeMobileCountryCode' => 310, 197 | 'homeMobileNetworkCode' => 260, 198 | 'radioType' => "gsm", 199 | 'carrier' => "T-Mobile", 200 | 'cellTowers' => [ 201 | 'cellId' => 39627456, 202 | 'locationAreaCode' => 40495, 203 | 'mobileCountryCode' => 310, 204 | 'mobileNetworkCode' => 260, 205 | 'age' => 0, 206 | 'signalStrength' => -95, 207 | ], 208 | 'wifiAccessPoints' => [ 209 | [ 210 | 'macAddress' => "01:23:45:67:89:AB", 211 | 'signalStrength' => 8, 212 | 'age' => 0, 213 | 'channel' => 8, 214 | 'signalToNoiseRatio' => -65, 215 | ], 216 | [ 217 | 'macAddress' => "01:23:45:67:89:AC", 218 | 'signalStrength' => 4, 219 | 'age' => 0, 220 | ], 221 | ], 222 | 223 | 224 | ]; 225 | 226 | $d['a'] = \GoogleMaps::load('geolocate') 227 | ->setParam($data) 228 | ->get(); 229 | 230 | 231 | $d['b'] = \GoogleMaps::load('geolocate') 232 | ->setParamByKey('homeMobileCountryCode', 310) 233 | ->setParamByKey('homeMobileNetworkCode', 260) 234 | ->setParamByKey('radioType', 'gsm') 235 | ->setParamByKey('carrier', 'T-Mobile') 236 | ->setParamByKey('cellTowers', ['cellId' => 39627456]) 237 | ->setParamByKey('cellTowers', ['locationAreaCode' => 40495]) 238 | ->setParamByKey('cellTowers', ['mobileCountryCode' => 310]) 239 | ->setParamByKey('cellTowers', ['mobileNetworkCode' => 260]) 240 | ->setParamByKey('cellTowers', ['age' => 0]) 241 | ->setParamByKey('wifiAccessPoints', ['macAddress' => '01:23:45:67:89:AB']) 242 | ->setParamByKey('wifiAccessPoints', ['signalStrength' => 8]) 243 | ->setParamByKey('wifiAccessPoints', ['age' => 0]) 244 | ->setParamByKey('wifiAccessPoints', ['channel' => 8]) 245 | ->setParamByKey('wifiAccessPoints', ['signalToNoiseRatio' => -65]) 246 | 247 | ->setParamByKey('wifiAccessPoints', ['macAddress' => '01:23:45:67:89:AC']) 248 | ->setParamByKey('wifiAccessPoints', ['signalStrength' => 4]) 249 | ->setParamByKey('wifiAccessPoints', ['age' => 0]) 250 | 251 | 252 | ->getResponseByKey('location'); 253 | 254 | dd($d); 255 | } 256 | 257 | 258 | public function getSnapToRoads() 259 | { 260 | $d['a'] = \GoogleMaps::load('snapToRoads') 261 | ->setParamByKey('path', '-35.27801,149.12958|-35.28032,149.12907|-35.28099,149.12929|-35.28144,149.12984|-35.28194,149.13003|-35.28282,149.12956|-35.28302,149.12881|-35.28473,149.12836') 262 | ->get(); 263 | 264 | $d['b'] = \GoogleMaps::load('snapToRoads') 265 | ->setParamByKey('path', ['60.170880,24.942795', '60.170879,24.942796', '60.170877,24.942796']) 266 | ->getResponseByKey('snappedPoints'); 267 | 268 | dd($d); 269 | } 270 | 271 | 272 | public function getSpeedLimits() 273 | { 274 | $d['a'] = \GoogleMaps::load('speedLimits') 275 | ->setParamByKey('path', '60.170880,24.942795|60.170879,24.942796|60.170877,24.942796') 276 | ->get(); 277 | 278 | 279 | $d['b'] = \GoogleMaps::load('speedLimits') 280 | ->setParamByKey('placeId', ['ChIJ1Wi6I2pNFmsRQL9GbW7qABM', 'ChIJ58xCoGlNFmsRUEZUbW7qABM', 'ChIJ9RhaiGlNFmsR0IxAbW7qABM']) 281 | ->getResponseByKey('snappedPoints'); 282 | 283 | 284 | dd($d); 285 | } 286 | 287 | 288 | 289 | public function getTimeZone() 290 | { 291 | 292 | $d = \GoogleMaps::load('timezone') 293 | ->setParam([ 294 | 'location' => '39.6034810,-119.6822510', 295 | 'timestamp' => '1331161200' 296 | ]) 297 | ->get(); 298 | 299 | dd($d); 300 | } 301 | 302 | public function getNearbySearch() 303 | { 304 | 305 | $d = \GoogleMaps::load('nearbysearch') 306 | 307 | ->setParam([ 308 | 'location' => '-33.8670522,151.1957362', 309 | 'radius' => '500', 310 | 'name' => 'sydney', 311 | 'type' => 'airport', 312 | ]) 313 | ->getResponseByKey('results.photos'); 314 | 315 | dd($d); 316 | } 317 | 318 | 319 | public function getTextSearch() 320 | { 321 | 322 | $d = \GoogleMaps::load('textsearch') 323 | ->setParam([ 324 | 'query' => 'restaurants in Lytham St Annes', 325 | 'radius' => '500', 326 | 'types' => 'restaurant', 327 | ]) 328 | ->getResponseByKey('results.formatted_address'); 329 | 330 | dd($d); 331 | } 332 | 333 | public function getRadarSearch() 334 | { 335 | 336 | $d = \GoogleMaps::load('radarsearch') 337 | ->setParam([ 338 | 'location' => '51.503186,-0.126446', 339 | 'radius' => '500', 340 | 'type' => 'museum', 341 | ]) 342 | ->getResponseByKey('results.place_id'); 343 | 344 | dd($d); 345 | } 346 | 347 | public function getPlaceDetails() 348 | { 349 | 350 | $d = \GoogleMaps::load('placedetails') 351 | ->setParamByKey('placeid', 'ChIJN1t_tDeuEmsRUsoyG83frY4') 352 | ->getResponseByKey('result.geometry.location'); 353 | 354 | 355 | dd($d); 356 | } 357 | 358 | 359 | 360 | 361 | public function getPlacePhoto() 362 | { 363 | 364 | $d = \GoogleMaps::load('placephoto') 365 | ->setParamByKey('maxwidth', '400') 366 | ->setParamByKey('photoreference', 'CnRtAAAATLZNl354RwP_9UKbQ_5Psy40texXePv4oAlgP4qNEkdIrkyse7rPXYGd9D_Uj1rVsQdWT4oRz4QrYAJNpFX7rzqqMlZw2h2E2y5IKMUZ7ouD_SlcHxYq1yL4KbKUv3qtWgTK0A6QbGh87GB3sscrHRIQiG2RrmU_jF4tENr9wGS_YxoUSSDrYjWmrNfeEHSGSc3FyhNLlBU') 367 | ->get(); 368 | 369 | dd($d); 370 | } 371 | 372 | public function getPlaceAutoComplete() 373 | { 374 | 375 | $d = \GoogleMaps::load('placeautocomplete') 376 | ->setParamByKey('input', 'Vict') 377 | ->setParamByKey('types', 'cities') 378 | ->setParamByKey('language', 'fr') 379 | ->getResponseByKey('predictions.place_id'); 380 | 381 | 382 | dd($d); 383 | } 384 | 385 | public function getPlaceQueryAutoComplete() 386 | { 387 | 388 | $d = \GoogleMaps::load('placequeryautocomplete') 389 | ->setParamByKey('input', 'Pizza near Lon') 390 | ->setParamByKey('language', 'gb') 391 | ->getResponseByKey('predictions.place_id'); 392 | 393 | 394 | dd($d); 395 | } 396 | } 397 | -------------------------------------------------------------------------------- /src/Directions.php: -------------------------------------------------------------------------------- 1 | 10 | * @deprecated see Routes 11 | */ 12 | class Directions extends WebService{ 13 | /** 14 | * Get Web Service Response 15 | * 16 | * @param string|false $needle 17 | * @return string 18 | * @throws \ErrorException 19 | */ 20 | public function get( $needle = false ){ 21 | 22 | if( $this->service['decodePolyline'] ){ 23 | $this->setEndpoint('json'); 24 | 25 | return $this->decode( parent::get( $needle )); 26 | } 27 | 28 | return parent::get( $needle ); 29 | } 30 | /***/ 31 | 32 | /** 33 | * To determine whether a point falls on or near a polyline, or on or near 34 | * the edge of a polygon, pass the point, the polyline/polygon, and 35 | * optionally a tolerance value in degrees 36 | * https://developers.google.com/maps/documentation/javascript/geometry#isLocationOnEdge 37 | * 38 | * @param double $lat 39 | * @param double $lng 40 | * @param double $tolerance 41 | * @return boolean 42 | * @throws \ErrorException 43 | */ 44 | public function isLocationOnEdge( $lat, $lng, $tolerance = 0.1){ 45 | 46 | $point = [ 47 | 'lat' => $lat, 48 | 'lng' => $lng 49 | ]; 50 | 51 | $polygon = Arr::get( json_decode( $this->get(), true ), 'routes.0.overview_polyline.points') ; 52 | 53 | return PolyUtil::isLocationOnEdge($point, $polygon, $tolerance); 54 | } 55 | 56 | /** 57 | * To find whether a given point falls within a polygon 58 | * https://developers.google.com/maps/documentation/javascript/geometry#containsLocation 59 | * 60 | * @param double $lat 61 | * @param double $lng 62 | * @return boolean 63 | * @throws \ErrorException 64 | */ 65 | public function containsLocation($lat, $lng){ 66 | 67 | $point = [ 68 | 'lat' => $lat, 69 | 'lng' => $lng 70 | ]; 71 | 72 | $polygon = Arr::get( json_decode( $this->get(), true ), 'routes.0.overview_polyline.points') ; 73 | 74 | return PolyUtil::containsLocation($point, $polygon); 75 | } 76 | 77 | /* 78 | |-------------------------------------------------------------------------- 79 | | Protected methods 80 | |-------------------------------------------------------------------------- 81 | | 82 | */ 83 | 84 | /** 85 | * Get web service polyline parameter being decoded 86 | * @param $rsp - string 87 | * @param string $param - response key 88 | * @return string - JSON 89 | */ 90 | protected function decode( $rsp, $param = 'routes.overview_polyline.points' ){ 91 | $needle = metaphone($param); 92 | 93 | // get response 94 | $obj = json_decode( $rsp, true); 95 | 96 | // flatten array into single level array using 'dot' notation 97 | $obj_dot = Arr::dot($obj); 98 | // create empty response 99 | $response = []; 100 | // iterate 101 | foreach( $obj_dot as $key => $val){ 102 | 103 | // Calculate the metaphone key and compare with needle 104 | $val = strcmp( metaphone($key, strlen($needle)), $needle) === 0 105 | ? PolyUtil::decode($val) // if matched decode polyline 106 | : $val; 107 | 108 | Arr::set($response, $key, $val); 109 | } 110 | 111 | return json_encode($response, JSON_PRETTY_PRINT) ; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/Facade/GoogleMapsFacade.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | class GoogleMaps extends WebService{ 9 | 10 | /** 11 | * Array of classes to handle web service request 12 | * By default WebService class will be used 13 | * @var string[] 14 | */ 15 | protected $webServices = [ 16 | 'directions' => Directions::class, 17 | 'routes' => Routes::class, 18 | 'routematrix' => Routes::class, 19 | ]; 20 | 21 | /** 22 | * Bootstrapping Web Service 23 | * 24 | * @param string $service 25 | * @return \GoogleMaps\WebService 26 | * @throws \ErrorException 27 | */ 28 | public function load($service) { 29 | 30 | // is overwrite class specified 31 | $class = array_key_exists($service, $this->webServices) 32 | ? new $this->webServices[$service] 33 | : $this; 34 | 35 | $class->build($service); 36 | 37 | return $class; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Parameters.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | use URLify; 9 | 10 | class Parameters{ 11 | 12 | 13 | protected static $urlParam; 14 | 15 | /** 16 | * Generate Service URL parameters string 17 | * @param array $param 18 | * @return string 19 | */ 20 | public static function getQueryString( &$param ){ 21 | 22 | // Geocoding components parameter 23 | if( isset($param['components']) && is_array($param['components'])){ 24 | $param['components'] = self::joinParam( $param['components'], ':', '|'); 25 | } 26 | 27 | // Direction parameters 28 | if( isset($param['origin']) && is_array($param['origin'])){ 29 | $param['origin'] = self::joinParam( $param['origin'], '', ':', false ); 30 | } 31 | 32 | if( isset($param['destination']) && is_array($param['destination'])){ 33 | $param['destination'] = self::joinParam( $param['destination'], '', ':', false ); 34 | } 35 | 36 | if( isset($param['waypoints']) && is_array($param['waypoints'])){ 37 | $param['waypoints'] = self::joinParam( $param['waypoints'], '', '|', false ); 38 | } 39 | 40 | if( isset($param['avoid']) && is_array($param['avoid'])){ 41 | $param['avoid'] = self::joinParam( $param['avoid'], '', '|', false ); 42 | } 43 | 44 | // Distance Matrix parameters 45 | if( isset($param['origins']) && is_array($param['origins'])){ 46 | $param['origins'] = self::joinParam( $param['origins'], '', '|', false ); 47 | } 48 | 49 | if( isset($param['destinations']) && is_array($param['destinations'])){ 50 | $param['destinations'] = self::joinParam( $param['destinations'], '', '|', false ); 51 | } 52 | 53 | if( isset($param['transit_mode']) && is_array($param['transit_mode'])){ 54 | $param['transit_mode'] = self::joinParam( $param['transit_mode'], '', '|', false ); 55 | } 56 | 57 | if( isset($param['alternatives']) && is_bool($param['alternatives'])){ 58 | $param['alternatives'] = $param['alternatives'] ? 'true' : 'false'; 59 | } 60 | 61 | 62 | // Elevation & Road parameters 63 | if( isset($param['locations']) && is_array($param['locations'])){ 64 | $param['locations'] = self::joinParam( $param['locations'], '', '|', false ); 65 | } 66 | if( isset($param['path']) && is_array($param['path'])){ 67 | $param['path'] = self::joinParam( $param['path'], '', '|', false ); 68 | } 69 | 70 | // Places & Time Zone parameters 71 | if( isset($param['location']) && is_array($param['location'])){ 72 | $param['location'] = self::joinParam( $param['location'], '', ',', false ); 73 | } 74 | 75 | /** 76 | * Place Search 77 | * Deprecation notices: Premium data (Zagat), types parameter, id and reference fields 78 | * Restricts the results to places matching the specified type. 79 | * Only one type may be specified (if more than one type is provided, all types following the first entry are ignored). 80 | */ 81 | if( isset($param['types']) && is_array($param['types'])){ 82 | #$param['types'] = self::joinParam( $param['types'], '', '|', false ); 83 | $param['type'] = !empty( $param['types'][0] ) ? $param['types'][0] : ""; 84 | } 85 | 86 | // reset to empty array 87 | self::$urlParam = []; 88 | 89 | return self::joinParam( $param ); 90 | 91 | } 92 | 93 | /** 94 | * Join array pairs into URL encoded string 95 | * @param array $param - single dimension array 96 | * @param string $join 97 | * @param string $glue 98 | * @param boolean $useKey 99 | * @return string 100 | */ 101 | protected static function joinParam( $param = [], $join = '=', $glue = '&', $useKey = true){ 102 | 103 | $allParam = []; 104 | 105 | foreach ($param as $key => $val) 106 | { 107 | if( is_array( $val ) ){ 108 | if ($useKey && isset($val[0]) && is_array($val[0]) === false) { 109 | $newValue = []; 110 | foreach ($val as $element) { 111 | $newValue[] = $key . $join . self::replaceCharacters($element); 112 | } 113 | 114 | return implode($glue, $newValue); 115 | } else { 116 | $val = self::joinParam( $val, $join, $glue, $useKey); 117 | } 118 | } 119 | 120 | // omit parameters with empty values 121 | if( !empty( $val )){ 122 | #self::$urlParam[] = $useKey 123 | $allParam[] = $useKey 124 | ? $key . $join .urlencode(URLify::downcode($val)) 125 | : $join .urlencode(URLify::downcode($val)); 126 | } 127 | } 128 | 129 | // no parameters given 130 | if( is_null( $allParam ) ) { 131 | return ''; 132 | } 133 | 134 | $allParam = self::replaceCharacters($allParam); 135 | 136 | return implode($glue, $allParam); 137 | } 138 | 139 | /** 140 | * Replace special characters 141 | * @param array $allParam 142 | * @return mixed 143 | */ 144 | private static function replaceCharacters($allParam) 145 | { 146 | // replace special characters 147 | $allParam = str_replace(['%2C'], [','], $allParam); 148 | $allParam = str_replace(['%252C'], [','], $allParam); 149 | $allParam = str_replace(['%3A'], [':'], $allParam); 150 | return str_replace(['%7C'], ['|'], $allParam); 151 | } 152 | 153 | public static function resetParams() 154 | { 155 | self::$urlParam = []; 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /src/Routes.php: -------------------------------------------------------------------------------- 1 | 12 | * 13 | */ 14 | class Routes extends WebService 15 | { 16 | 17 | /** 18 | * A response field mask 19 | * @var string 20 | */ 21 | protected $fieldMask = '*'; 22 | /** 23 | * Merge request parameters 24 | * 25 | * @param string|false $needle 26 | * @return void 27 | * @throws \ErrorException 28 | */ 29 | public function setParam($param) 30 | { 31 | // merge with existing parameters 32 | try { 33 | $this->service['param'] = array_merge($this->service['param'], $param); 34 | } catch (ErrorException $e) { 35 | throw new ErrorException('Invalid parameter: ' . $e->getMessage()); 36 | } 37 | // Check if the parameter is an array 38 | if (!is_array($param)) { 39 | throw new ErrorException('Invalid parameter: ' . $param); 40 | } 41 | 42 | 43 | 44 | // Fileter out null values from the array 45 | $this->service['param'] = array_filter($this->service['param'], function ($value) { 46 | return $value !== null; 47 | }); 48 | return $this; 49 | } 50 | 51 | 52 | /** 53 | * Set field mask 54 | * 55 | * @param string $fieldMask 56 | * @return void 57 | * @throws \ErrorException 58 | */ 59 | public function setFieldMask($fieldMask) 60 | { 61 | try { 62 | $this->fieldMask = strval($fieldMask); 63 | } catch (ErrorException $e) { 64 | throw new ErrorException('Error setting field mask ' . $e->getMessage()); 65 | } 66 | return $this; 67 | } 68 | 69 | 70 | 71 | /** 72 | * Make cURL request to given URL 73 | * @param boolean $isPost 74 | * @return bool|object 75 | * @throws \ErrorException 76 | */ 77 | public function fetch() 78 | { 79 | 80 | $ch = curl_init($this->requestUrl); 81 | 82 | curl_setopt($ch, CURLOPT_HTTPHEADER, [ 83 | 'Content-Type: application/json', 84 | 'X-Goog-Api-Key: ' . $this->key, 85 | 'X-Goog-FieldMask: ' . $this->fieldMask, 86 | ]); 87 | curl_setopt($ch, CURLOPT_POST, 1); 88 | curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($this->service['param'])); 89 | 90 | 91 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectionTimeout); 92 | curl_setopt($ch, CURLOPT_TIMEOUT, $this->requestTimeout); 93 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verifySSL); 94 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 95 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 96 | 97 | if ($this->requestUseCompression) { 98 | curl_setopt($ch, CURLOPT_ENCODING, ""); 99 | } 100 | 101 | $output = curl_exec($ch); 102 | 103 | if ($output === false) { 104 | throw new ErrorException(curl_error($ch)); 105 | } 106 | 107 | curl_close($ch); 108 | 109 | // get API response 110 | $rsp = json_decode($output, true); 111 | 112 | if ($rsp === null) { 113 | throw new ErrorException('Invalid JSON response: ' . json_last_error_msg()); 114 | } 115 | 116 | 117 | if (array_key_exists('decodePolyline', $this->service) && $this->service['decodePolyline']) { 118 | 119 | // check if encoded polyline is present 120 | if (!$rsp['routes'][0]['polyline']['encodedPolyline']) { 121 | throw new ErrorException('Encoded Polyline not found: ' . json_encode($rsp)); 122 | } 123 | 124 | // decode polyline 125 | $rsp['routes'][0]['polyline']['decodedPolyline'] = PolyUtil::decode($rsp['routes'][0]['polyline']['encodedPolyline']); 126 | } 127 | 128 | 129 | return $rsp; 130 | } 131 | 132 | 133 | /** 134 | * Decode polyline 135 | * 136 | * @param string $encoded 137 | * @return array 138 | */ 139 | public function decodePolyline($encoded) 140 | { 141 | $decoded = []; 142 | $index = 0; 143 | $len = strlen($encoded); 144 | $lat = 0; 145 | $lng = 0; 146 | 147 | while ($index < $len) { 148 | $shift = 0; 149 | $result = 0; 150 | do { 151 | $b = ord($encoded[$index++]) - 63; 152 | $result |= ($b & 0x1f) << $shift; 153 | $shift += 5; 154 | } while ($b >= 0x20); 155 | $dlat = (($result & 1) ? ~($result >> 1) : ($result >> 1)); 156 | $lat += $dlat; 157 | 158 | $shift = 0; 159 | $result = 0; 160 | do { 161 | $b = ord($encoded[$index++]) - 63; 162 | $result |= ($b & 0x1f) << $shift; 163 | $shift += 5; 164 | } while ($b >= 0x20); 165 | $dlng = (($result & 1) ? ~($result >> 1) : ($result >> 1)); 166 | $lng += $dlng; 167 | 168 | $decoded[] = [(float)$lat / 1e5, (float)$lng / 1e5]; 169 | } 170 | 171 | return $decoded; 172 | } 173 | 174 | /** 175 | * To determine whether a point falls on or near a polyline, or on or near 176 | * the edge of a polygon, pass the point, the polyline/polygon, and 177 | * optionally a tolerance value in degrees 178 | * https://developers.google.com/maps/documentation/javascript/geometry#isLocationOnEdge 179 | * 180 | * @param double $lat 181 | * @param double $lng 182 | * @param double $tolerance 183 | * @return boolean 184 | * @throws \ErrorException 185 | */ 186 | public function isLocationOnEdge($lat, $lng, $tolerance = 0.1) 187 | { 188 | 189 | $point = [ 190 | 'lat' => $lat, 191 | 'lng' => $lng 192 | ]; 193 | 194 | // get API response 195 | $rsp = $this->fetch(); 196 | 197 | // check if encoded polyline is present 198 | if (!$rsp['routes'][0]['polyline']['encodedPolyline']) { 199 | throw new ErrorException('Encoded Polyline not found: ' . json_encode($rsp)); 200 | } 201 | 202 | // decode polyline and check if location is on edge 203 | try { 204 | return PolyUtil::isLocationOnEdge($point, PolyUtil::decode($rsp['routes'][0]['polyline']['encodedPolyline']), $tolerance); 205 | } catch (ErrorException $e) { 206 | throw new ErrorException('Error decoding polyline: ' . $e->getMessage()); 207 | return false; 208 | } 209 | } 210 | 211 | /** 212 | * To find whether a given point falls within a polygon 213 | * https://developers.google.com/maps/documentation/javascript/geometry#containsLocation 214 | * 215 | * @param double $lat 216 | * @param double $lng 217 | * @return boolean 218 | * @throws \ErrorException 219 | */ 220 | public function containsLocation($lat, $lng) 221 | { 222 | 223 | $point = [ 224 | 'lat' => $lat, 225 | 'lng' => $lng 226 | ]; 227 | 228 | // get API response 229 | $rsp = $this->fetch(); 230 | 231 | // check if encoded polyline is present 232 | if (!$rsp['routes'][0]['polyline']['encodedPolyline']) { 233 | throw new ErrorException('Encoded Polyline not found: ' . json_encode($rsp)); 234 | } 235 | 236 | 237 | // decode polyline and check if contains location 238 | try { 239 | 240 | return PolyUtil::containsLocation($point, PolyUtil::decode($rsp['routes'][0]['polyline']['encodedPolyline'])); 241 | } catch (ErrorException $e) { 242 | throw new ErrorException('Error decoding polyline: ' . $e->getMessage()); 243 | return false; 244 | } 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /src/ServiceProvider/GoogleMapsServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 23 | __DIR__.'/../config/googlemaps.php' => config_path('googlemaps.php'), 24 | ], 'googlemaps'); 25 | } 26 | 27 | /** 28 | * Register the application services. 29 | * 30 | * @return void 31 | */ 32 | public function register() 33 | { 34 | $this->app->bind('GoogleMaps', function(){ 35 | return new GoogleMaps; 36 | }); 37 | } 38 | /***/ 39 | 40 | /** 41 | * Get the services provided by the provider. 42 | * 43 | * @return array 44 | */ 45 | public function provides() 46 | { 47 | return array('GoogleMaps'); 48 | } 49 | 50 | 51 | 52 | 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/WebService.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class WebService{ 13 | 14 | 15 | /* 16 | |-------------------------------------------------------------------------- 17 | | Default Endpoint 18 | |-------------------------------------------------------------------------- 19 | | 20 | */ 21 | protected $endpoint; 22 | 23 | 24 | 25 | /* 26 | |-------------------------------------------------------------------------- 27 | | Web Service 28 | |-------------------------------------------------------------------------- 29 | | 30 | | 31 | | 32 | */ 33 | protected $service; 34 | 35 | 36 | /* 37 | |-------------------------------------------------------------------------- 38 | | API Key 39 | |-------------------------------------------------------------------------- 40 | | 41 | | 42 | | 43 | */ 44 | protected $key; 45 | 46 | 47 | /* 48 | |-------------------------------------------------------------------------- 49 | | Service URL 50 | |-------------------------------------------------------------------------- 51 | | 52 | | 53 | | 54 | */ 55 | protected $requestUrl; 56 | 57 | /* 58 | |-------------------------------------------------------------------------- 59 | | Verify SSL Peer 60 | |-------------------------------------------------------------------------- 61 | | 62 | | 63 | | 64 | */ 65 | protected $verifySSL; 66 | 67 | /* 68 | |-------------------------------------------------------------------------- 69 | | Request's timeout 70 | |-------------------------------------------------------------------------- 71 | | 72 | | 73 | | 74 | */ 75 | protected $requestTimeout; 76 | 77 | /* 78 | |-------------------------------------------------------------------------- 79 | | Connection timeout 80 | |-------------------------------------------------------------------------- 81 | | 82 | | 83 | | 84 | */ 85 | protected $connectionTimeout; 86 | 87 | /* 88 | |-------------------------------------------------------------------------- 89 | | Request's compression setting 90 | |-------------------------------------------------------------------------- 91 | | 92 | | 93 | | 94 | */ 95 | protected $requestUseCompression; 96 | 97 | /** 98 | * Setting endpoint 99 | * @param string $key 100 | * @return $this 101 | */ 102 | public function setEndpoint( $key = 'json' ){ 103 | 104 | $this->endpoint = Config::get("googlemaps.endpoint.{$key}", 'json?'); 105 | 106 | return $this; 107 | } 108 | 109 | /** 110 | * Getting endpoint 111 | * @return string 112 | */ 113 | public function getEndpoint( ){ 114 | 115 | return $this->endpoint; 116 | } 117 | 118 | /** 119 | * Set parameter by key 120 | * @param string $key 121 | * @param string $value 122 | * @return $this 123 | */ 124 | public function setParamByKey($key, $value){ 125 | 126 | if( array_key_exists( $key, Arr::dot( $this->service['param'] ) ) ){ 127 | Arr::set($this->service['param'], $key, $value); 128 | } 129 | 130 | return $this; 131 | } 132 | 133 | /** 134 | * Get parameter by the key 135 | * @param string $key 136 | * @return string|null 137 | */ 138 | public function getParamByKey($key){ 139 | return Arr::get($this->service['param'], $key, null); 140 | } 141 | 142 | /** 143 | * Set all parameters at once 144 | * @param array $param 145 | * @return $this 146 | */ 147 | public function setParam( $param ){ 148 | 149 | $this->service['param'] = array_merge( $this->service['param'], $param ); 150 | 151 | return $this; 152 | } 153 | 154 | /** 155 | * Return parameters array 156 | * @return array 157 | */ 158 | public function getParam(){ 159 | return $this->service['param']; 160 | } 161 | 162 | /** 163 | * Get Web Service Response 164 | * 165 | * @param string|false $needle - response key 166 | * @return string|array 167 | * @throws \ErrorException 168 | */ 169 | public function get( $needle = false ){ 170 | 171 | return empty( $needle ) 172 | ? $this->getResponse() 173 | : $this->getResponseByKey( $needle ); 174 | } 175 | 176 | /** 177 | * Get response value by key 178 | * 179 | * @param string|bool $needle - retrieves response parameter using "dot" notation 180 | * @return array 181 | * @throws \ErrorException 182 | */ 183 | public function getResponseByKey( $needle = false){ 184 | 185 | // set response to json 186 | $this->setEndpoint('json'); 187 | 188 | // set default key parameter 189 | $needle = empty( $needle ) 190 | ? metaphone($this->service['responseDefaultKey']) 191 | : metaphone($needle); 192 | 193 | // get response 194 | $obj = json_decode( $this->get(), true); 195 | 196 | // flatten array into single level array using 'dot' notation 197 | $obj_dot = Arr::dot($obj); 198 | // create empty response 199 | $response = []; 200 | // iterate 201 | foreach( $obj_dot as $key => $val){ 202 | 203 | // Calculate the metaphone key and compare with needle 204 | if( strcmp( metaphone($key, strlen($needle)), $needle) === 0 ){ 205 | // set response value 206 | Arr::set($response, $key, $val); 207 | } 208 | } 209 | 210 | // finally extract slice of the array 211 | #return array_slice($response, $offset, $length); 212 | 213 | return count($response) < 1 214 | ? $obj 215 | : $response; 216 | } 217 | 218 | /** 219 | * Get response status 220 | * 221 | * @return mixed 222 | * @throws \ErrorException 223 | */ 224 | public function getStatus(){ 225 | 226 | // set response to json 227 | $this->setEndpoint('json'); 228 | 229 | // get response 230 | $obj = json_decode( $this->get(), true); 231 | 232 | return Arr::get($obj, 'status', null); 233 | } 234 | 235 | /* 236 | |-------------------------------------------------------------------------- 237 | | Protected methods 238 | |-------------------------------------------------------------------------- 239 | | 240 | */ 241 | 242 | /** 243 | * Setup service parameters 244 | * 245 | * @param $service 246 | * @throws \ErrorException 247 | */ 248 | protected function build( $service ){ 249 | 250 | $this->validateConfig( $service ); 251 | 252 | // set default endpoint 253 | $this->setEndpoint(); 254 | 255 | // set web service parameters 256 | $this->service = Config::get('googlemaps.service.'.$service); 257 | 258 | // is service key set, use it, otherwise use default key 259 | $this->key = empty( $this->service['key'] ) 260 | ? Config::get('googlemaps.key') 261 | : $this->service['key']; 262 | 263 | // set service url 264 | $this->requestUrl = $this->service['url']; 265 | 266 | // is ssl_verify_peer key set, use it, otherwise use default key 267 | $this->verifySSL = empty(Config::get('googlemaps.ssl_verify_peer')) 268 | ? FALSE 269 | : Config::get('googlemaps.ssl_verify_peer'); 270 | 271 | // set the timeout for the connect phase 272 | $this->connectionTimeout = Config::get("googlemaps.connection_timeout"); 273 | 274 | // set the maximum time the transfer is allowed to complete 275 | $this->requestTimeout = Config::get("googlemaps.request_timeout"); 276 | 277 | // set the compression flag 278 | $this->requestUseCompression = Config::get("googlemaps.request_use_compression"); 279 | 280 | $this->clearParameters(); 281 | } 282 | 283 | /** 284 | * Validate configuration file 285 | * 286 | * @param $service 287 | * @throws \ErrorException 288 | */ 289 | protected function validateConfig( $service ){ 290 | 291 | // Check for config file 292 | if( ! Config::has('googlemaps')){ 293 | throw new ErrorException('Unable to find config file.'); 294 | } 295 | 296 | // Validate Key parameter 297 | if(Config::has('googlemaps.key') === false){ 298 | throw new ErrorException('Unable to find Key parameter in configuration file.'); 299 | } 300 | 301 | // Validate Key parameter 302 | if(Config::has('googlemaps.service') === false || Config::has('googlemaps.service.'.$service) === false){ 303 | throw new ErrorException('Web service must be declared in the configuration file.'); 304 | } 305 | 306 | // Validate Endpoint 307 | $endpointCount = count(Config::get('googlemaps.endpoint', [])); 308 | $endpointsKeyExists = Config::has('googlemaps.endpoint'); 309 | 310 | if($endpointsKeyExists === false || $endpointCount < 1){ 311 | throw new ErrorException('End point must not be empty.'); 312 | } 313 | } 314 | 315 | /** 316 | * Get Web Service Response 317 | * @return string 318 | * @throws \ErrorException 319 | */ 320 | protected function getResponse(){ 321 | 322 | $post = false; 323 | 324 | // use output parameter if required by the service 325 | $this->requestUrl.= $this->service['endpoint'] 326 | ? $this->endpoint 327 | : ''; 328 | 329 | // set API Key 330 | $this->requestUrl.= 'key='.urlencode( $this->key ); 331 | 332 | switch( $this->service['type'] ){ 333 | case 'POST': 334 | $post = json_encode( $this->service['param'] ); 335 | break; 336 | default: 337 | $this->requestUrl.='&'. Parameters::getQueryString( $this->service['param'] ); 338 | break; 339 | } 340 | 341 | return $this->make( $post ); 342 | } 343 | 344 | /** 345 | * Make cURL request to given URL 346 | * @param boolean $isPost 347 | * @return bool|string 348 | * @throws \ErrorException 349 | */ 350 | protected function make( $isPost = false ){ 351 | 352 | $ch = curl_init( $this->requestUrl ); 353 | 354 | if( $isPost ){ 355 | curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); 356 | curl_setopt($ch,CURLOPT_POST, 1); 357 | curl_setopt($ch,CURLOPT_POSTFIELDS, $isPost ); 358 | } 359 | 360 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectionTimeout); 361 | curl_setopt($ch, CURLOPT_TIMEOUT, $this->requestTimeout); 362 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->verifySSL); 363 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 364 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 365 | 366 | if ($this->requestUseCompression) { 367 | curl_setopt($ch, CURLOPT_ENCODING, ""); 368 | } 369 | 370 | $output = curl_exec($ch); 371 | 372 | if( $output === false ){ 373 | throw new ErrorException( curl_error($ch) ); 374 | } 375 | 376 | curl_close($ch); 377 | return $output; 378 | } 379 | 380 | protected function clearParameters() 381 | { 382 | Parameters::resetParams(); 383 | } 384 | } 385 | -------------------------------------------------------------------------------- /src/config/googlemaps.php: -------------------------------------------------------------------------------- 1 | 'ADD_YOUR_SERVICE_KEY_HERE', 18 | 19 | /* 20 | |-------------------------------------------------------------------------- 21 | | Verify SSL Peer 22 | |-------------------------------------------------------------------------- 23 | | 24 | | Will be used for all web services to verify 25 | | SSL peer (SSL certificate validation) 26 | | 27 | */ 28 | 'ssl_verify_peer' => FALSE, 29 | 30 | /* 31 | |-------------------------------------------------------------------------- 32 | | CURL's connection timeout 33 | |-------------------------------------------------------------------------- 34 | | 35 | | Will be used for all web services to limit 36 | | the maximum time tha connection can take in seconds 37 | | 38 | */ 39 | 'connection_timeout' => 5, 40 | 41 | /* 42 | |-------------------------------------------------------------------------- 43 | | CURL's request timeout 44 | |-------------------------------------------------------------------------- 45 | | 46 | | Will be used for all web services to limit 47 | | the maximum time a request can take 48 | | 49 | */ 50 | 'request_timeout' => 30, 51 | 52 | /* 53 | |-------------------------------------------------------------------------- 54 | | CURL's CURLOPT_ENCODING 55 | |-------------------------------------------------------------------------- 56 | | 57 | | Will be used for all web services to use compression on requests. 58 | | 59 | | Sets the contents of the "Accept-Encoding:" header a containing all 60 | | supported encoding types. 61 | | 62 | */ 63 | 'request_use_compression' => false, 64 | 65 | /* 66 | |-------------------------------------------------------------------------- 67 | | Service URL 68 | |-------------------------------------------------------------------------- 69 | | url - web service URL 70 | | type - request type POST or GET 71 | | key - API key, if different to API key above 72 | | endpoint - boolean, indicates whenever output parameter to be used in the request or not 73 | | responseDefaultKey - specify default field value to be returned when calling getByKey() 74 | | param - accepted request parameters 75 | | 76 | */ 77 | 78 | 'service' => [ 79 | 80 | 'geocoding' => [ 81 | 'url' => 'https://maps.googleapis.com/maps/api/geocode/', 82 | 'type' => 'GET', 83 | 'key' => null, 84 | 'endpoint' => true, 85 | 'responseDefaultKey' => 'place_id', 86 | 'param' => [ 87 | 'address' => null, 88 | 'bounds' => null, 89 | 'key' => null, 90 | 'region' => null, 91 | 'language' => null, 92 | 'result_type' => null, 93 | 'location_type' => null, 94 | 'latlng' => null, 95 | 'place_id' => null, 96 | 'components' => [ 97 | 'route' => null, 98 | 'locality' => null, 99 | 'administrative_area' => null, 100 | 'postal_code' => null, 101 | 'country' => null, 102 | ] 103 | ] 104 | ], 105 | 106 | // https://developers.google.com/maps/documentation/routes/reference/rest 107 | 'routes' => [ 108 | 'url' => 'https://routes.googleapis.com/directions/v2:computeRoutes', 109 | 'type' => 'POST', 110 | 'key' => null, 111 | 'endpoint' => true, 112 | 'decodePolyline' => true, // true = decode overview_polyline.points to an array of points 113 | 'param' => [ 114 | 'origin' => null, // required 115 | 'destination' => null, //required 116 | 'intermediates' => null, 117 | 'travelMode' => null, 118 | 'transitRoutingPreference' => null, 119 | 'polylineQuality' => null, 120 | 'polylineEncoding' => null, 121 | 'departureTime' => null, 122 | 'arrivalTime' => null, 123 | 'computeAlternativeRoutes' => null, 124 | 'routeModifiers' => null, 125 | 'languageCode' => null, 126 | 'regionCode' => null, 127 | 'units' => null, 128 | 'optimizeWaypointOrder' => false, 129 | 'requestedReferenceRoutes' => null, 130 | 'extraComputations' => null, 131 | 'trafficModel' => null, 132 | 'transitPreferences' => null, 133 | ] 134 | ], 135 | 136 | 137 | 138 | // https://developers.google.com/maps/documentation/routes/reference/rest/v2/TopLevel/computeRouteMatrix 139 | 'routematrix' => [ 140 | 'url' => 'https://routes.googleapis.com/distanceMatrix/v2:computeRouteMatrix', 141 | 'type' => 'POST', 142 | 'key' => null, 143 | 'endpoint' => true, 144 | 'param' => [ 145 | 'origins' => null, // required 146 | 'destinations' => null, //required 147 | 'travelMode' => null, 148 | 'routingPreference' => null, 149 | 'departureTime' => null, 150 | 'arrivalTime' => null, 151 | 'languageCode' => null, 152 | 'regionCode' => null, 153 | 'units' => null, 154 | 'extraComputations' => null, 155 | 'trafficModel' => null, 156 | 'transitPreferences' => null, 157 | ] 158 | ], 159 | 160 | 161 | // Deprecated 162 | 'directions' => [ 163 | 'url' => 'https://maps.googleapis.com/maps/api/directions/', 164 | 'type' => 'GET', 165 | 'key' => null, 166 | 'endpoint' => true, 167 | 'responseDefaultKey' => 'geocoded_waypoints', 168 | 'decodePolyline' => true, // true = decode overview_polyline.points to an array of points 169 | 'param' => [ 170 | 'origin' => null, // required 171 | 'destination' => null, //required 172 | 'mode' => null, 173 | 'waypoints' => null, 174 | 'place_id' => null, 175 | 'alternatives' => null, 176 | 'avoid' => null, 177 | 'language' => null, 178 | 'units' => null, 179 | 'region' => null, 180 | 'departure_time' => null, 181 | 'arrival_time' => null, 182 | 'transit_mode' => null, 183 | 'transit_routing_preference' => null, 184 | ] 185 | ], 186 | 187 | // Deprecated 188 | 'distancematrix' => [ 189 | 'url' => 'https://maps.googleapis.com/maps/api/distancematrix/', 190 | 'type' => 'GET', 191 | 'key' => null, 192 | 'endpoint' => true, 193 | 'responseDefaultKey' => 'origin_addresses', 194 | 'param' => [ 195 | 'origins' => null, 196 | 'destinations' => null, 197 | 'key' => null, 198 | 'mode' => null, 199 | 'language' => null, 200 | 'avoid' => null, 201 | 'units' => null, 202 | 'departure_time' => null, 203 | 'arrival_time' => null, 204 | 'transit_mode' => null, 205 | 'transit_routing_preference' => null, 206 | 207 | ] 208 | ], 209 | 210 | 211 | 'elevation' => [ 212 | 'url' => 'https://maps.googleapis.com/maps/api/elevation/', 213 | 'type' => 'GET', 214 | 'key' => null, 215 | 'endpoint' => true, 216 | 'responseDefaultKey' => 'elevation', 217 | 'param' => [ 218 | 'locations' => null, 219 | 'path' => null, 220 | 'samples' => null, 221 | 'key' => null, 222 | ] 223 | ], 224 | 225 | 226 | 'geolocate' => [ 227 | 'url' => 'https://www.googleapis.com/geolocation/v1/geolocate?', 228 | 'type' => 'POST', 229 | 'key' => null, 230 | 'endpoint' => false, 231 | 'responseDefaultKey' => 'location', 232 | 'param' => [ 233 | 'homeMobileCountryCode' => null, 234 | 'homeMobileNetworkCode' => null, 235 | 'radioType' => null, 236 | 'carrier' => null, 237 | 'considerIp' => null, 238 | 'cellTowers' => [ 239 | 'cellId' => null, 240 | 'locationAreaCode' => null, 241 | 'mobileCountryCode' => null, 242 | 'mobileNetworkCode' => null, 243 | 'age' => null, 244 | 'signalStrength' => null, 245 | 'timingAdvance' => null, 246 | ], 247 | 'wifiAccessPoints' => [ 248 | 'macAddress' => null, 249 | 'signalStrength' => null, 250 | 'age' => null, 251 | 'channel' => null, 252 | 'signalToNoiseRatio' => null, 253 | ], 254 | ] 255 | ], 256 | 257 | 258 | 259 | 'snapToRoads' => [ 260 | 'url' => 'https://roads.googleapis.com/v1/snapToRoads?', 261 | 'type' => 'GET', 262 | 'key' => null, 263 | 'endpoint' => false, 264 | 'responseDefaultKey' => 'snappedPoints', 265 | 'param' => [ 266 | 'locations' => null, 267 | 'path' => null, 268 | 'samples' => null, 269 | 'key' => null, 270 | ] 271 | ], 272 | 273 | 274 | 'speedLimits' => [ 275 | 'url' => 'https://roads.googleapis.com/v1/speedLimits?', 276 | 'type' => 'GET', 277 | 'key' => null, 278 | 'endpoint' => false, 279 | 'responseDefaultKey' => 'speedLimits', 280 | 'param' => [ 281 | 'path' => null, 282 | 'placeId' => null, 283 | 'units' => null, 284 | 'key' => null, 285 | ] 286 | ], 287 | 288 | 289 | 'timezone' => [ 290 | 'url' => 'https://maps.googleapis.com/maps/api/timezone/', 291 | 'type' => 'GET', 292 | 'key' => null, 293 | 'endpoint' => true, 294 | 'responseDefaultKey' => 'dstOffset', 295 | 'param' => [ 296 | 'location' => null, 297 | 'timestamp' => null, 298 | 'key' => null, 299 | 'language' => null, 300 | 301 | ] 302 | ], 303 | 304 | 305 | 306 | 'nearbysearch' => [ 307 | 'url' => 'https://maps.googleapis.com/maps/api/place/nearbysearch/', 308 | 'type' => 'GET', 309 | 'key' => null, 310 | 'endpoint' => true, 311 | 'responseDefaultKey' => 'results', 312 | 'param' => [ 313 | 'key' => null, 314 | 'location' => null, 315 | 'radius' => null, 316 | 'keyword' => null, 317 | 'language' => null, 318 | 'minprice' => null, 319 | 'maxprice' => null, 320 | 'name' => null, 321 | 'opennow' => null, 322 | 'rankby' => null, 323 | 'type' => null, // types depricated, one type may be specified 324 | 'pagetoken' => null, 325 | 'zagatselected' => null, 326 | ] 327 | ], 328 | 329 | 330 | 331 | 'textsearch' => [ 332 | 'url' => 'https://maps.googleapis.com/maps/api/place/textsearch/', 333 | 'type' => 'GET', 334 | 'key' => null, 335 | 'endpoint' => true, 336 | 'responseDefaultKey' => 'results', 337 | 'param' => [ 338 | 'key' => null, 339 | 'query' => null, 340 | 'location' => null, 341 | 'radius' => null, 342 | 'language' => null, 343 | 'minprice' => null, 344 | 'maxprice' => null, 345 | 'opennow' => null, 346 | 'type' => null, // types deprecated, one type may be specified 347 | 'pagetoken' => null, 348 | 'zagatselected' => null, 349 | ] 350 | ], 351 | 352 | 353 | 354 | 'radarsearch' => [ 355 | 'url' => 'https://maps.googleapis.com/maps/api/place/radarsearch/', 356 | 'type' => 'GET', 357 | 'key' => null, 358 | 'endpoint' => true, 359 | 'responseDefaultKey' => 'geometry', 360 | 'param' => [ 361 | 'key' => null, 362 | 'radius' => null, 363 | 'location' => null, 364 | 'keyword' => null, 365 | 'minprice' => null, 366 | 'maxprice' => null, 367 | 'opennow' => null, 368 | 'name' => null, 369 | 'type' => null, // types depricated, one type may be specified 370 | 'zagatselected' => null, 371 | ] 372 | ], 373 | 374 | 375 | 376 | 'placedetails' => [ 377 | 'url' => 'https://maps.googleapis.com/maps/api/place/details/', 378 | 'type' => 'GET', 379 | 'key' => null, 380 | 'endpoint' => true, 381 | 'responseDefaultKey' => 'result', 382 | 'param' => [ 383 | 'key' => null, 384 | 'placeid' => null, 385 | 'extensions' => null, 386 | 'language' => null, 387 | ] 388 | ], 389 | 390 | 391 | 'placeadd' => [ 392 | 'url' => 'https://maps.googleapis.com/maps/api/place/add/', 393 | 'type' => 'POST', 394 | 'key' => null, 395 | 'endpoint' => true, 396 | 'responseDefaultKey' => 'place_id', 397 | 'param' => [ 398 | 'key' => null, 399 | 'accuracy' => null, 400 | 'address' => null, 401 | 'language' => null, 402 | 'location' => null, 403 | 'name' => null, 404 | 'phone_number' => null, 405 | 'types' => null, // according to docs types still required as string parameter 406 | 'type' => null, // types deprecated, one type may be specified 407 | 'website' => null, 408 | ] 409 | ], 410 | 411 | 412 | 'placedelete' => [ 413 | 'url' => 'https://maps.googleapis.com/maps/api/place/delete/', 414 | 'type' => 'POST', 415 | 'key' => null, 416 | 'endpoint' => true, 417 | 'responseDefaultKey' => 'status', 418 | 'param' => [ 419 | 'key' => null, 420 | 'place_id' => null, 421 | 422 | ] 423 | ], 424 | 425 | 426 | 427 | 428 | 'placephoto' => [ 429 | 'url' => 'https://maps.googleapis.com/maps/api/place/photo?', 430 | 'type' => 'GET', 431 | 'key' => null, 432 | 'endpoint' => false, 433 | 'responseDefaultKey' => 'image', 434 | 'param' => [ 435 | 'key' => null, 436 | 'photoreference' => null, 437 | 'maxheight' => null, 438 | 'maxwidth' => null, 439 | ] 440 | ], 441 | 442 | 443 | 444 | 445 | 446 | 'placeautocomplete' => [ 447 | 'url' => 'https://maps.googleapis.com/maps/api/place/autocomplete/', 448 | 'type' => 'GET', 449 | 'key' => null, 450 | 'endpoint' => true, 451 | 'responseDefaultKey' => 'predictions', 452 | 'param' => [ 453 | 'key' => null, 454 | 'input' => null, 455 | 'offset' => null, 456 | 'location' => null, 457 | 'radius' => null, 458 | 'language' => null, 459 | 'types' => null, // use string as parameter 460 | 'type' => null, // types deprecated, one type may be specified 461 | 'components' => null, 462 | ] 463 | ], 464 | 465 | 466 | 467 | 'placequeryautocomplete' => [ 468 | 'url' => 'https://maps.googleapis.com/maps/api/place/queryautocomplete/', 469 | 'type' => 'GET', 470 | 'key' => null, 471 | 'endpoint' => true, 472 | 'responseDefaultKey' => 'predictions', 473 | 'param' => [ 474 | 'key' => null, 475 | 'input' => null, 476 | 'offset' => null, 477 | 'location' => null, 478 | 'radius' => null, 479 | 'language' => null, 480 | ] 481 | ], 482 | 483 | ], 484 | 485 | 486 | 487 | 488 | /* 489 | |-------------------------------------------------------------------------- 490 | | End point 491 | |-------------------------------------------------------------------------- 492 | | 493 | | 494 | */ 495 | 496 | 'endpoint' => [ 497 | 'xml' => 'xml?', 498 | 'json' => 'json?', 499 | ], 500 | 501 | 502 | 503 | ]; 504 | --------------------------------------------------------------------------------