A simple Nette DI extension for the znojil/heureka PHP client, allowing for easy integration and configuration of one or more API clients.
Install via Composer:
composer require znojil/nette-heurekaFirst, register the extension in your config.neon:
extensions:
heureka: Znojil\Nette\Heureka\DI\HeurekaExtensionIf you only need to communicate with one Heureka region, you can configure a single client. This client service (Znojil\Heureka\Client) will be registered and autowired by the Nette DI container.
heureka:
region: cz
key: 'your-secret-api-key'Configuration options:
region: (required) The Heureka region to use. The value must be one of the cases inZnojil\Heureka\Enum\Region.key: (optional) Your API key for authenticated requests.httpClient: (optional) A custom HTTP client implementingZnojil\Heureka\Http\Client(e.g.,@myCustomHttpClient).
If you need to work with multiple regions or API keys, you can configure multiple named clients.
heureka:
cz_shop:
region: cz
key: 'your-main-cz-api-key'
sk_shop:
region: sk
key: 'your-sk-subsidiary-api-key'
cz_shop_no_key:
region: czIn this setup, a single Znojil\Nette\Heureka\ClientProvider service is registered. Individual clients are not autowired.
You can provide a custom HTTP client that implements the Znojil\Heureka\Http\Client interface. This interface requires PSR-7 compatibility (Psr\Http\Message\ResponseInterface and UriInterface) but is not PSR-18.
The interface signature:
interface Client{
function send(
string $method,
Message\UriInterface $uri,
array $headers = [],
mixed $data = null,
array $options = []
): Message\ResponseInterface;
}This is useful for adding custom headers, timeouts, proxy settings, or other HTTP-specific configuration.
Reference an existing service by name using the @ prefix:
services:
myCustomHttpClient: Your\Custom\HttpClient
heureka:
region: cz
key: 'your-api-key'
httpClient: @myCustomHttpClientProvide a fully qualified class name as a string:
heureka:
region: cz
key: 'your-api-key'
httpClient: Your\Custom\HttpClientYou can configure any HTTP client directly in your NEON configuration using Nette DI's inline service definitions. This example demonstrates the approach using the default implementation (Znojil\Heureka\Http\ZnojilClient), but the same technique works with any custom client.
Example: Custom User-Agent and Timeouts
parameters:
curlOptMap:
userAgent: ::CURLOPT_USERAGENT
timeout: ::CURLOPT_TIMEOUT
connectTimeout: ::CURLOPT_CONNECTTIMEOUT
services:
myCustomHttpClient: Znojil\Heureka\Http\ZnojilClient(
Znojil\Http\Client(
defaultCurlOptions: [
%curlOptMap.userAgent%: 'MyApp/1.0 (Heureka Integration)'
%curlOptMap.timeout%: 30
%curlOptMap.connectTimeout%: 10
]
)
)
heureka:
region: cz
key: 'your-api-key'
httpClient: @myCustomHttpClientWhy use parameter mapping?
The parameters.curlOptMap approach is necessary because NEON's ::CONSTANT_NAME syntax works only for values, not for array keys. Since cURL options require constants as keys (e.g., CURLOPT_USERAGENT => 'value'), we use parameter mapping to work around this limitation.
How it works:
- Define constants in
parameterssection:userAgent: ::CURLOPT_USERAGENT(value position - works!) - Reference them as keys using
%curlOptMap.userAgent%(expands to the constant value)
This keeps your configuration readable and type-safe while leveraging cURL's native options without resorting to magic numbers.
When using the single client setup, you can inject the Znojil\Heureka\Client directly into your services.
<?php
declare(strict_types=1);
use Znojil\Heureka\Client;
final class SomeService{
public function __construct(
private readonly Client $heurekaClient
){}
public function doSomething(): void{
// Use the client to send a request
// $this->heurekaClient->send(...);
}
}When using the multiple clients setup, inject the Znojil\Nette\Heureka\ClientProvider and use it to get the client you need by its name.
<?php
declare(strict_types=1);
use Znojil\Nette\Heureka\ClientProvider;
final class AnotherService{
public function __construct(
private readonly ClientProvider $clientProvider
){}
public function doSomethingWithMultipleClients(): void{
$czClient = $this->clientProvider->getClient('cz_shop');
// $czClient->send(...);
$skClient = $this->clientProvider->getClient('sk_shop');
// $skClient->send(...);
}
}The ClientProvider has the following public methods:
getClient(string $name): Client: Returns the client by name. ThrowsZnojil\Nette\Heureka\Exception\ClientNotFoundExceptionif the name is invalid.hasClient(string $name): bool: Checks if a client with the given name is configured.getNames(): array: Returns an array of all configured client names.
This library is open-source software licensed under the MIT license.