Installation
composer require ekyna/gls-uni-box-bundle
Add to config/bundles.php:
Ekyna\GlsUniBoxBundle\EkynaGlsUniBoxBundle::class => ['all' => true],
First Use Case
Ekyna\GlsUniBox\UniBox service into a controller or command.
use Ekyna\GlsUniBox\UniBox;
public function generateLabel(UniBox $uniBox)
{
$label = $uniBox->generateLabel(
'your_gls_customer_id',
'your_gls_password',
[
'items' => [
['weight' => 1.5, 'length' => 20, 'width' => 15, 'height' => 10],
['weight' => 0.8, 'length' => 10, 'width' => 8, 'height' => 5],
],
'recipient' => [
'name' => 'Recipient Name',
'address' => 'Recipient Address',
'postcode' => '1234AB',
'city' => 'Recipient City',
'country' => 'NL',
],
]
);
return response()->streamDownload(
fn () => fwrite(STDOUT, $label),
'gls_label.pdf'
);
}
Configuration
php artisan vendor:publish --tag=gls-uni-box-config
config/gls_uni_box.php with your GLS credentials and API settings.Order Processing
Ekyna\CommerceBundle\Event\OrderShippedEvent) to trigger label generation after an order is marked as shipped.
public function handle(OrderShippedEvent $event)
{
$uniBox = app(UniBox::class);
$label = $uniBox->generateLabel(
config('gls_uni_box.customer_id'),
config('gls_uni_box.password'),
$this->mapOrderToUniBoxData($event->getOrder())
);
// Save label path to order or send via email
}
Batch Processing
public function generateLabelsForPendingOrders()
{
$orders = Order::where('status', 'shipped')->get();
foreach ($orders as $order) {
$uniBox->generateLabel(/* ... */);
}
}
Integration with EkynaCommerceBundle
Ekyna\CommerceBundle\Model\OrderInterface to include UniBox-specific fields (e.g., getUniBoxItems()).ShipmentProvider to register GLS as a shipping option:
# config/ekyna_commerce/shipping_providers.yml
gls_uni_box:
class: Ekyna\GlsUniBoxBundle\Provider\GlsUniBoxProvider
label: 'GLS Uni Box'
UniBox service to avoid tight coupling.try {
$label = $uniBox->generateLabel(/* ... */);
} catch (\Ekyna\GlsUniBox\Exception\ApiException $e) {
Log::error('GLS API Error: ' . $e->getMessage());
throw new \RuntimeException('Failed to generate GLS label.');
}
UniBox service in unit tests:
$this->mock(UniBox::class)->shouldReceive('generateLabel')->once()->andReturn('mocked_label');
API Credentials
config/gls_uni_box.php to version control. Use environment variables:
'customer_id' => env('GLS_CUSTOMER_ID'),
'password' => env('GLS_PASSWORD'),
base_url in the config.Item Dimensions
$items = array_map(function ($item) {
return [
'weight' => $item['weight_kg'], // Ensure this is in kg
'length' => $item['length_cm'], // Ensure this is in cm
'width' => $item['width_cm'],
'height' => $item['height_cm'],
];
}, $order->items);
Rate Limits
use Symfony\Component\HttpClient\RetryStrategy;
$client = \Symfony\Component\HttpClient\HttpClient::create([
'timeout' => 30,
'retry_on_status' => [429, 500, 502, 503, 504],
'retry_delay' => RetryStrategy::DELAY_MILLISECONDS,
]);
Label Formatting
API Responses: Enable debug mode in the config to log raw API responses:
'debug' => true, // In config/gls_uni_box.php
Check logs in storage/logs/laravel.log for detailed API interactions.
Validation Errors: GLS may return validation errors in the response body. Parse them explicitly:
$response = $uniBox->getClient()->post($url, [
'json' => $data,
]);
$content = $response->getContent();
if ($response->getStatusCode() === 400) {
$errors = json_decode($content, true);
throw new \InvalidArgumentException($errors['message'] ?? 'Unknown error');
}
Custom Label Templates
php artisan vendor:publish --tag=gls-uni-box-templates
Edit resources/views/gls_uni_box/label.html.twig.Additional API Features
UniBox class to support additional GLS API endpoints (e.g., tracking, returns):
namespace App\Services;
use Ekyna\GlsUniBox\UniBox as BaseUniBox;
class ExtendedUniBox extends BaseUniBox
{
public function getTrackingInfo(string $trackingNumber)
{
return $this->getClient()->get("/tracking/{$trackingNumber}");
}
}
Webhook Handling
Route::post('/gls/webhook', [GlsWebhookController::class, 'handle']);
Use the Ekyna\GlsUniBox\Webhook\Handler trait for validation:
use Ekyna\GlsUniBox\Webhook\Handler;
class GlsWebhookController extends Controller
{
use Handler;
public function handle(Request $request)
{
return $this->processWebhook($request);
}
}
Multi-Carrier Support
interface ShipperInterface
{
public function generateLabel(array $data);
}
class GlsShipper implements ShipperInterface
{
public function __construct(private UniBox $uniBox) {}
public function generateLabel(array $data)
{
return $this->uniBox->generateLabel(
config('gls_uni_box.customer_id'),
config('gls_uni_box.password'),
$data
);
}
}
How can I help you explore Laravel packages today?