Installation
composer require ekyna/shipment-bundle
Add to config/bundles.php:
Ekyna\ShipmentBundle\EkynaShipmentBundle::class => ['all' => true],
Publish Config & Migrations
php artisan vendor:publish --provider="Ekyna\ShipmentBundle\EkynaShipmentBundle" --tag="config"
php artisan vendor:publish --provider="Ekyna\ShipmentBundle\EkynaShipmentBundle" --tag="migrations"
php artisan migrate
First Use Case Create a shipment via CLI:
php artisan shipment:create --name="Test Shipment" --reference="REF123"
Verify in database (shipments table) or via Tinker:
$shipment = \Ekyna\ShipmentBundle\Entity\Shipment::first();
Shipment Creation
ShipmentFactory (service) or CLI command.OrderPlaced).
use Ekyna\ShipmentBundle\Event\ShipmentEvents;
event(new ShipmentEvents\ShipmentCreated($shipment));
Tracking & Status Updates
$shipment->setStatus('delivered');
$this->shipmentRepository->save($shipment);
$shipment->addTrackingEvent('scanned', 'Warehouse A', new \DateTime());
Integration with Orders
ManyToMany relationship:
$shipment->addOrder($order);
$this->shipmentRepository->save($shipment);
$shipments = $order->getShipments();
Carrier Integration
CarrierInterface for custom carriers:
class CustomCarrier implements CarrierInterface {
public function generateLabel(Shipment $shipment) { ... }
public function getTrackingUrl(Shipment $shipment) { ... }
}
ekyna_shipment:
carriers:
custom:
class: App\Carrier\CustomCarrier
API Exposure
namespace App\Http\Resources;
use Ekyna\ShipmentBundle\Entity\Shipment;
use Illuminate\Http\Resources\Json\JsonResource;
class ShipmentResource extends JsonResource {
public function toArray($request) {
return [
'id' => $this->id,
'reference' => $this->reference,
'status' => $this->status,
'tracking_url' => $this->getTrackingUrl(),
];
}
}
Missing Configuration
Configuration not found.php artisan vendor:publish) and verify config/ekyna_shipment.php exists.Entity Not Found
Shipment entity not autowired or EntityManager errors.EkynaShipmentBundle is loaded in config/bundles.php before your bundle if using Symfony.Carrier-Specific Quirks
CarrierInterface implementation and log carrier-specific errors:
try {
$carrier->generateLabel($shipment);
} catch (\Exception $e) {
\Log::error("Carrier {$carrier->getName()} failed: " . $e->getMessage());
}
Migration Conflicts
Schema::hasTable('shipments') fails during migration.php artisan migrate --path=/vendor/ekyna/shipment-bundle/src/Resources/migrations
Custom Fields
Extend the Shipment entity via traits or inheritance:
namespace App\Entity;
use Ekyna\ShipmentBundle\Entity\Shipment as BaseShipment;
class Shipment extends BaseShipment {
/**
* @ORM\Column(type="string", nullable=true)
*/
private $customField;
}
Event-Driven Workflows Listen for shipment events to trigger notifications or updates:
// In a service provider
$this->eventDispatcher->addListener(
ShipmentEvents::SHIPMENT_CREATED,
function ($event) {
// Send email, update inventory, etc.
}
);
Testing Use factories for shipments:
$shipment = ShipmentFactory::create()
->withName('Test')
->withStatus('pending')
->create();
Performance
updateStatusBulk() if available.$shipments = $this->shipmentRepository->findBy([], ['orders' => 'id']);
Debugging
ekyna_shipment:
debug: true
How can I help you explore Laravel packages today?