## Getting Started
### Minimal Steps
1. **Installation**: Add the package via Composer:
```bash
composer require api-check/php-symfony-client
The bundle auto-enables via Symfony Flex.
Configuration: Set your API key in .env:
APICHECK_API_KEY=your_api_key_here
APICHECK_REFERER=https://yourdomain.com # Required if API key has "Allowed Hosts"
Or configure via config/packages/apicheck.yaml.
First Use Case: Inject ApiClient into a service and perform a global search (most versatile endpoint):
use ApiCheck\Api\ApiClient;
class AddressService {
public function __construct(private ApiClient $apiCheck) {}
public function findAddresses(string $query): array {
return $this->apiCheck->globalSearch('nl', $query, ['limit' => 5])->Results;
}
}
Call it from a controller:
$results = $this->addressService->findAddresses('Amsterdam');
Address Autocomplete
globalSearch() with a partial query (e.g., 'Amst') to populate a dropdown.type (e.g., city, street) to prioritize relevant matches.$results = $this->apiCheck->globalSearch('nl', $userInput, [
'limit' => 3,
'city_id' => $preferredCityId // Optional: Narrow by city
]);
Address Validation
lookup() to validate a full address:$address = $this->apiCheck->lookup('nl', [
'postalcode' => '1012LM',
'number' => '1'
]);
if ($address->valid) {
// Proceed with valid address
}
Belgium-Specific Addresses
searchMunicipality() to get municipality_id, then filter globalSearch():$municipalities = $this->apiCheck->searchMunicipality('be', 'Antwerpen');
$municipalityId = $municipalities->Results[0]->id;
$addresses = $this->apiCheck->globalSearch('be', 'Station', [
'municipality_id' => $municipalityId
]);
User Input Sanitization
$query = strtolower(trim($request->get('query')));
$cache = $this->container->get('cache.app');
$cities = $cache->get('nl_cities', function() {
return $this->apiCheck->search('nl', 'city', ['limit' => 1000]);
});
KernelEvents::TERMINATE to log API usage or update analytics.$form->add('street', EntityType::class, [
'class' => AddressResult::class,
'choice_label' => 'name',
'query_builder' => function(AddressRepository $repo) use ($query) {
return $repo->findBySearch($query);
}
]);
Rate Limiting
try {
$result = $this->apiCheck->globalSearch(...);
} catch (RateLimitException $e) {
sleep(2 ** $attempt); // Exponential backoff
}
Tip: Monitor usage via the ApiCheck dashboard.
Country-Specific Quirks
locality_id) and municipalities (municipality_id) are critical for precision. Always filter by these IDs when possible.1012LM). Validate format before API calls:
if (!preg_match('/^\d{4}[A-Za-z]{2}$/', $postalCode)) {
throw new \InvalidArgumentException('Invalid Dutch postal code');
}
ID Mismatches
city_id, street_id) are country-specific. Reuse IDs across countries only if documented (e.g., Luxembourg shares IDs with Netherlands for some endpoints).Number Additions
1A), use getNumberAdditions() to validate before lookup:$additions = $this->apiCheck->getNumberAdditions('nl', '1012LM', '1');
if (!in_array('A', $additions->numberAdditions)) {
throw new \RuntimeException('Invalid number addition');
}
APP_DEBUG=true in .env to log API responses:
# config/packages/apicheck.yaml
apicheck:
debug: '%kernel.debug%'
meta field in responses for errors:
if (isset($result->meta->error)) {
throw new \RuntimeException($result->meta->error->message);
}
Custom Response Mappers
ApiClient to transform responses (e.g., flatten nested objects):class CustomApiClient extends ApiClient {
public function searchWithFlattenedResults(string $country, string $type, array $params) {
$results = parent::search($country, $type, $params);
return array_map(function($item) {
return (array) $item + ['full_name' => "{$item->name} ({$item->type})"];
}, $results->Results);
}
}
Register it as a service override:
services:
ApiCheck\Api\ApiClient: '@custom_api_client'
Event Listeners
$container->get('api_check.api_client')->addListener(function($event) {
if ($event->getType() === 'globalSearch') {
$event->setParams(array_merge($event->getParams(), ['debug' => true]));
}
});
Symfony Messenger
$this->messageDispatcher->dispatch(
new SearchAddressesMessage($query, $country)
);
Process with a worker:
public function __invoke(SearchAddressesMessage $message) {
return $this->apiCheck->globalSearch($message->country, $message->query);
}
APICHECK_REFERER matches the request’s Host header. For local development, use:
APICHECK_REFERER=http://localhost
%env(resolve:APICHECK_API_KEY)% in YAML to resolve nested env vars:
apicheck:
api_key: '%env(resolve:APP_API_KEYS/apicheck)%'
Symfony\Component\Messenger\HandleTrait.lookup() until the user selects a result).
```markdown
## Example Debugging Workflow
1. **Symptom**: Global search returns empty results for a known address.
2. **Steps**:
- Verify the `country` code is correct (e.g., `'nl'` for Netherlands).
- Check if the `query` is too broad (e.g., `'A'` may return too many results; try `'Amsterdam'`).
- Enable debug mode (`APP_DEBUG=1`) and inspect the raw API response:
```php
$response = $this->apiCheck->getClient()->get('global-search', [
'query' => ['country' => 'nl', 'query' => 'Damrak']
]);
file_put_contents('debug.json', $response->getBody());
```
- Confirm
How can I help you explore Laravel packages today?