geocoder-php / Geocoder

The most featured Geocoder library written in PHP.
https://geocoder-php.org
MIT License
3.94k stars 517 forks source link

Compatibility with CakePHP #1050

Closed dereuromark closed 4 years ago

dereuromark commented 4 years ago

https://github.com/geocoder-php/google-maps-provider/blob/master/GoogleMaps.php

This one is installed along the original repo, together with https://github.com/php-http/cakephp-adapter:cake4 branch

The AbstractHttpProvider is

public function __construct(HttpClient $client, MessageFactory $factory = null)

But the GoogleMaps extends AbstractHttpProvider implements Provider:

/**
 * @param HttpClient $client An HTTP adapter
 * @param string     $region Region biasing (optional)
 * @param string     $apiKey Google Geocoding API key (optional)
 */
public function __construct(HttpClient $client, string $region = null, string $apiKey = null)
{
    parent::__construct($client);

    $this->region = $region;
    $this->apiKey = $apiKey;
}

This way, the provided factory is never used, resulting in errors:

$adapter = new $adapterClass(new \Cake\Http\Client(), new \Geo\Geocoder\ResponseFactory());

Http\Discovery\Exception\DiscoveryFailedException: Could not find resource using any discovery strategy. Find more information at http://docs.php-http.org/en/latest/discovery.html#common-errors

If those versions are not compatible composer should probably outline a conflict of sorts. Best to fix this though to be compatible with the interface and thus contracting of these classes.

Composer:

jbelien commented 4 years ago

Hello @dereuromark ,

I'm not sure I understand the issue here. You're trying to use our Google Maps provider with Cake PHP HTTP Client (instead of Guzzle, for instance) and it doesn't work, is that it ?


What is your $adapterClass variable ? What is the \Geo\Geocoder\ResponseFactory class ?

dereuromark commented 4 years ago
$adapterClass = $this->getConfig('adapter');

So Http\Adapter\Cake\Client as per linked repo, implements HttpClient (as per psr7).

namespace Geo\Geocoder;

use Cake\Http\Client\Response;
use Http\Message\ResponseFactory as ResponseFactoryInterface;

class ResponseFactory implements ResponseFactoryInterface {

    /**
     * @inheritDoc
     */
    public function createResponse($statusCode = 200, $reasonPhrase = null, array $headers = [], $body = null, $protocolVersion = '1.1') {
        return new Response($headers, (string)$body);
    }

}

This should all work if the GoogleMaps class constructor signature would follow the spec of the interface, HttpClient $client, MessageFactory $factory = null)

jbelien commented 4 years ago

@Nyholm Any idea ?

dereuromark commented 4 years ago

I now managed in my PR to get it working. What is quite annoying is the overuse of final and private, making it hard to extend at least somehow without having to copy over complete classes. But fair enough for the time being. Closing then.