christianvermeulen/postalcode-bundle
Installation:
composer require christianvermeulen/postalcode-bundle:dev-master
Add the bundle to config/bundles.php:
return [
// ...
ChristianVermeulen\PostalcodeBundle\ChristianVermeulenPostalcodeBundle::class => ['all' => true],
];
Configuration:
Add your API credentials to config/packages/christian_vermeulen_postalcode.yaml:
christian_vermeulen_postalcode:
key: "%env(POSTCODE_API_KEY)%"
secret: "%env(POSTCODE_API_SECRET)%"
Ensure .env contains:
POSTCODE_API_KEY=your_key_here
POSTCODE_API_SECRET=your_secret_here
First Use Case: Fetch address details by postal code in a controller:
use ChristianVermeulen\PostalcodeBundle\Service\PostcodeService;
public function showAddress(PostcodeService $postcodeService)
{
$address = $postcodeService->getAddressByPostalCode('1012AA');
return response()->json($address);
}
Address Lookup:
Use PostcodeService to fetch address data:
$postcodeService->getAddressByPostalCode('1234AB');
Returns structured data (e.g., street, city, latitude/longitude).
Validation: Validate a postal code before processing:
if ($postcodeService->isValidPostalCode('1234AB')) {
// Proceed with address lookup
}
Reverse Geocoding: Convert coordinates to address:
$address = $postcodeService->getAddressByCoordinates(52.3676, 4.9021);
Integration with Forms:
Use the AJAX endpoint (/postal/autocomplete) for real-time suggestions:
fetch('/postal/autocomplete?q=1012')
.then(response => response.json())
.then(data => console.log(data));
Dependency Injection:
Inject PostcodeService into controllers/services to avoid direct instantiation.
public function __construct(private PostcodeService $postcodeService) {}
Caching Responses: Cache API responses to reduce calls (e.g., using Symfony’s cache system):
$cache = $this->container->get('cache.app');
$cachedAddress = $cache->get('address_1012AA');
if (!$cachedAddress) {
$address = $postcodeService->getAddressByPostalCode('1012AA');
$cache->set('address_1012AA', $address, 3600); // Cache for 1 hour
}
Error Handling: Wrap API calls in try-catch blocks to handle rate limits or invalid responses:
try {
$address = $postcodeService->getAddressByPostalCode('INVALID');
} catch (\ChristianVermeulen\PostalcodeBundle\Exception\ApiException $e) {
$this->addFlash('error', 'Invalid postal code or API error.');
}
API Key/Secret Mismanagement:
config.yml violates security best practices. Always use environment variables (.env).PostcodeService to throw exceptions on missing/empty keys).Rate Limiting:
The free tier of api.postcode.nl has strict rate limits (e.g., 100 requests/day). Uncached repeated calls will hit limits quickly.
Postal Code Format:
The API expects exact Dutch postal code formats (e.g., 1234AB, not 1234-ab or 1234).
$normalizedPostcode = preg_replace('/[^0-9A-Za-z]/', '', $userInput);
Deprecated Symfony2 Syntax: The bundle targets Symfony 2.x but may not work out-of-the-box with Symfony 5/6.
PostcodeService to use modern DI (e.g., autowiring) and replace AppKernel with config/bundles.php.Missing Documentation: The bundle lacks examples for advanced use cases (e.g., bulk lookups, custom field mapping).
// Example: Custom method for bulk lookups
public function getAddressesByPostalCodes(array $postalCodes): array
{
return array_map([$this->client, 'getAddressByPostalCode'], $postalCodes);
}
Enable API Debugging:
Set debug: true in config to log API responses:
christian_vermeulen_postalcode:
key: "%env(POSTCODE_API_KEY)%"
secret: "%env(POSTCODE_API_SECRET)%"
debug: true # Logs raw API responses to var/log/dev.log
Test with Mock Data:
Override PostcodeService to return mock data during development:
// config/services.yaml
ChristianVermeulen\PostalcodeBundle\Service\PostcodeService:
class: App\Service\MockPostcodeService
Handle Timeouts: The API may timeout for large payloads. Increase PHP’s timeout:
$this->client->setOption('timeout', 30); // 30 seconds
Custom Field Mapping:
Extend the response model to include additional fields (e.g., municipality_code):
// src/Entity/ExtendedAddress.php
class ExtendedAddress extends \ChristianVermeulen\PostalcodeBundle\Entity\Address
{
public function setMunicipalityCode(string $code): self
{
$this->municipality_code = $code;
return $this;
}
}
Add Geocoding: Integrate with Google Maps or OpenStreetMap for enhanced coordinates:
public function getEnhancedAddress(string $postalCode): array
{
$address = $this->getAddressByPostalCode($postalCode);
$address['google_place_id'] = $this->geocodeService->getPlaceId(
$address['latitude'], $address['longitude']
);
return $address;
}
Batch Processing: Process multiple postal codes asynchronously using Symfony’s Messenger:
// src/Message/ProcessPostalCodes.php
class ProcessPostalCodes implements MessageInterface
{
public function __construct(public array $postalCodes) {}
}
// src/MessageHandler/ProcessPostalCodesHandler.php
class ProcessPostalCodesHandler
{
public function __invoke(ProcessPostalCodes $message, PostcodeService $service)
{
return array_map([$service, 'getAddressByPostalCode'], $message->postalCodes);
}
}
How can I help you explore Laravel packages today?