answear/dpd-pl-pickup-services-bundle
Installation:
composer require answear/dpd-pl-pickup-services-bundle
The bundle auto-registers in config/bundles.php via Symfony Flex.
Configuration:
Add your DPD API key to config/packages/answear_dpd_pl_pickup_services.yaml:
answear_dpd_pl_pickup_services:
key: 'your_api_key_here'
First Use Case: Fetch all pickup points (PUDO) in a Symfony controller:
use Answear\DpdPlPickupServicesBundle\Service\PUDOList;
public function index(PUDOList $pudoList)
{
$pudos = $pudoList->getAll();
return $this->json($pudos);
}
PUDOList: Fetches all pickup points at once (returns Collection of PUDO objects).PUDOListStreaming: Streams pickup points one-by-one (memory-efficient for large datasets).PUDO: Value object representing a single pickup point (address, opening hours, services, etc.).Bulk Fetch (for small datasets):
$pudos = $pudoList->getAll(); // Returns Collection<PUDO>
$firstPudo = $pudos->first();
Streaming Fetch (for large datasets):
$stream = $pudoListStreaming->getAll();
foreach ($stream as $pudo) {
// Process one PUDO at a time (memory-efficient)
}
Leverage PUDO properties (e.g., getType(), getOpeningHours(), hasService()):
$pudos = $pudoList->getAll()->filter(fn(PUDO $pudo) =>
$pudo->getType()->isPostOffice() &&
$pudo->hasService('DressingRoom')
);
Since this is a Symfony bundle, use Symfony Bridge in Laravel:
composer require symfony/http-kernel
app/Providers/DpdServiceProvider):
use Symfony\Component\HttpKernel\Kernel;
use Answear\DpdPlPickupServicesBundle\AnswearDpdPlPickupServicesBundle;
public function register()
{
$kernel = new class extends Kernel {
public function getBundles() { return [new AnswearDpdPlPickupServicesBundle()]; }
public function getCacheDir() { return sys_get_temp_dir(); }
public function getLogDir() { return sys_get_temp_dir(); }
};
$this->app->singleton('dpd.pudo.list', fn() => $kernel->getContainer()->get('answear_dpd_pl_pickup_services.pudo_list'));
}
use Illuminate\Support\Facades\App;
$pudoList = App::make('dpd.pudo.list');
Cache API responses to reduce calls (e.g., using Laravel’s cache):
$cacheKey = 'dpd_pudos_' . md5($config['key']);
$pudos = Cache::remember($cacheKey, now()->addHours(1), fn() =>
$pudoList->getAll()
);
Wrap API calls in try-catch:
try {
$pudos = $pudoList->getAll();
} catch (\Answear\DpdPlPickupServicesBundle\Exception\ApiException $e) {
Log::error('DPD API Error: ' . $e->getMessage());
return response()->json(['error' => 'Service unavailable'], 503);
}
Service Container Binding:
Bind the Symfony services to Laravel’s container in AppServiceProvider:
public function register()
{
$this->app->bind('dpd.pudo.list', function ($app) {
return $app->make('answear_dpd_pl_pickup_services.pudo_list');
});
}
Form Requests:
Validate pickup point data using Laravel’s FormRequest:
public function rules()
{
return [
'pudo_id' => 'required|exists:dpd_pudos,id',
];
}
Map PUDO objects to Laravel models:
$pudo = $pudoList->getAll()->first();
$pickupPoint = PickupPoint::create([
'id' => $pudo->getId(),
'name' => $pudo->getName(),
'address' => $pudo->getAddress(),
'type' => $pudo->getType()->value,
'opening_hours' => json_encode($pudo->getOpeningHours()),
]);
Mock the PUDOList service in tests:
$mockPudo = new PUDO(
id: '123',
name: 'Test PUDO',
address: 'Test Street 1',
type: PUDOType::PostOffice,
openingHours: new OpeningHours([...])
);
$pudoList = $this->createMock(PUDOList::class);
$pudoList->method('getAll')->willReturn(collect([$mockPudo]));
API Key Exposure:
config/packages/answear_dpd_pl_pickup_services.yaml to version control..env:
# config/packages/answear_dpd_pl_pickup_services.yaml
answear_dpd_pl_pickup_services:
key: '%env(DPD_API_KEY)%'
Rate Limiting:
use Symfony\Component\HttpClient\RetryableHttpClient;
$client = new RetryableHttpClient(
$httpClient,
[
'max_retries' => 3,
'delay' => 1000, // ms
'multiplier' => 2,
'max_delay' => 5000,
]
);
Deprecated Methods:
Streaming Quirks:
PUDOListStreaming is memory-efficient but cannot be reused. Reset the stream if needed:
$stream = $pudoListStreaming->getAll();
// Process stream...
$stream = $pudoListStreaming->getAll(); // New stream
Type Safety:
PUDO properties return enums (e.g., PUDOType). Always check types:
if (!$pudo->getType()->isPostOffice()) {
throw new \InvalidArgumentException('Invalid PUDO type');
}
Enable Guzzle Debugging:
Add to config/services.yaml:
answear_dpd_pl_pickup_services:
key: '%env(DPD_API_KEY)%'
debug: '%kernel.debug%' # Logs requests/responses
Log Raw Responses: Extend the service to log raw API responses:
use Psr\Log\LoggerInterface;
class CustomPUDOList extends PUDOList
{
public function __construct(
private LoggerInterface $logger,
private ClientInterface $client,
private ConfigProvider $config
) {
parent::__construct($client, $config);
}
public function getAll(): Collection
{
$response = $this->client->request('GET', $this->config->getUrl());
$this->logger->debug('DPD API Response', ['body' => $response->getBody()->getContents()]);
return parent::getAll();
}
}
Handle Missing Services:
The API may return pickup points without expected services. Use hasService():
if (!$pudo->hasService('DressingRoom')) {
$this->logger->warning('PUDO missing DressingRoom service', ['pudo_id' => $pudo->getId()]);
}
PUDO value object (composer.json autoloads classes in src/):
namespace App\ValueObject;
How can I help you explore Laravel packages today?