The problem
Managing shipments in any eCommerce app is something that may be tricky. There are many shipping providers, and each of them has probably its API format, which allows us to provide shipment data and book a courier. To make this process more straightforward and generic, we decided to create an abstract layer for Sylius platform-based applications, which allows you to write just a simple API call and configuration form for the specific shipping provider. The workflow is quite simple – configure proper data that are needed to export a shipment, like access key or pickup hour, book a courier for an order with one click, and get a shipping label file if any was received from the API. The implementation limits to writing a shipping provider gateway configuration form, one event listener, and a web services access layer.
You can find the Shipping Export Plugin on our GitHub >>
Installation
Install package via composer:
$ composer require bitbag/shipping-export-plugin
Enable plugin in your AppKernel.php:
final class AppKernel extends Kernel
{
/**
* {@inheritdoc}
*/
public function registerBundles()
{
return array_merge(parent::registerBundles(), [
...
new BitBagSyliusShippingExportPluginBitBagSyliusShippingExportPlugin(),
]);
}
}
Import config in app/config/config.yml:
imports:
...
- { resource: "@BitBagSyliusShippingExportPlugin/Resources/config/config.yml" }
Import routing in you app/config/routing.yml:
bitbag_shipping_export_plugin:
resource: "@BitBagSyliusShippingExportPlugin/Resources/config/routing.yml"
prefix: /admin
Now when you go to the admin dashboard page, two new menu items should appear under “Sales” and “Configuration” named “Export shipping data” and “Shipping gateways”. Shipments to export will appear once someone will place an order with shipping method which has a configured shipping gateway.
Update your database either with migrations or $ bin/console doctrine:schema:update –force command.
Shipping gateway configuration form
Example form type definition:
namespace AppBundleFormType;
use SymfonyComponentFormAbstractType;
use SymfonyComponentFormExtensionCoreTypeTextType;
use SymfonyComponentFormFormBuilderInterface;
use SymfonyComponentValidatorConstraintsNotBlank;
final class FrankMartinShippingGatewayType extends AbstractType
{
/**
* {@inheritdoc}
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('iban', TextType::class, [
'label' => 'IBAN',
'constraints' => [
new NotBlank([
'message' => 'IBAN number cannot be blank.',
'groups' => 'bitbag',
])
],
])
->add('address', TextType::class, [
'label' => 'Address',
'constraints' => [
new NotBlank([
'message' => 'Address cannot be blank.',
'groups' => 'bitbag',
])
],
])
;
}
}
Service definition:
services:
app.form.type.frank_martin_shipping_gateway:
class: AppBundleFormTypeFrankMartinShippingGatewayType
tags:
- { name: bitbag.shipping_gateway_configuration_type, type: "frank_martin_shipping_gateway", label: "Transporter Gateway" }
Shipping export event listener
Basic event listener definition:
namespace AppBundleEventListener;
use BitBagShippingExportPluginEventExportShipmentEvent;
final class FrankMartinShippingExportEventListener
{
/**
* @param ExportShipmentEvent $event
*/
public function exportShipment(ExportShipmentEvent $event)
{
$shippingExport = $event->getShippingExport();
$shippingGateway = $shippingExport->getShippingGateway();
if ($shippingGateway->getCode() !== 'frank_martin_shipping_gateway') {
return;
}
if (false) {
$event->addErrorFlash(); // Add an error notification
return;
}
$event->addSuccessFlash(); // Add success notification
$event->saveShippingLabel("Some label content received from external API", 'pdf'); // Save label
$event->exportShipment(); // Mark shipment as "Exported"
}
}
Service definition:
services:
...
app.event_listener.frank_martin_shipping_export:
class: AppBundleEventListenerFrankMartinShippingExportEventListener
tags:
- { name: kernel.event_listener, event: 'bitbag.export_shipment', method: exportShipment }
Plugin parameters:
parameters:
bitbag.shipping_gateway.validation_groups: ['bitbag']
bitbag.shipping_labels_path: '%kernel.root_dir%/../shipping_labels'
Final thoughts
You can read more use-cases of this plugin in feature files which can be found in this plugin directory. Contributors are always welcomed! You can check out our GitHub profile where more Sylius plugins you may love can be found.