Creating Your First Shipping Method
Let's create a custom shipping method using both approaches available in Bagisto. We'll explore the package generator for quick setup and the manual method for complete understanding.
What You'll Learn
This guide covers the complete process of creating a Custom Express Shipping method, including:
- Package structure setup (generator vs manual)
- Configuration file creation
- Rate calculation implementation
- Admin interface integration
- Testing and deployment
Method 1: Using Bagisto Package Generator (Quick Setup)
The fastest way to create a shipping method is using Bagisto's package generator. This tool creates the proper structure and boilerplate code automatically.
Step 1: Install Package Generator
If you haven't installed the package generator yet:
composer require bagisto/bagisto-package-generator
Step 2: Generate Shipping Method Package
Navigate to your Bagisto root directory and run:
php artisan package:make-shipping-method Webkul/CustomExpressShipping
Command Parameters:
Webkul/CustomExpressShipping
: The vendor/package name for your shipping method
Step 3: Handle Existing Package (If Needed)
If the package directory already exists, use the --force
flag:
php artisan package:make-shipping-method Webkul/CustomExpressShipping --force
Package Generator Benefits
The generator automatically creates:
- Proper directory structure following Bagisto conventions
- Carrier configuration file with correct schema
- Base carrier class extending AbstractShipping
- System configuration for admin settings
- Service provider with proper registration
Step 4: Register the Generated Package
After generating the package, you need to register it with Bagisto:
Add to composer.json (in Bagisto root directory):
{
"autoload": {
"psr-4": {
// Other PSR-4 namespaces...
"Webkul\\CustomExpressShipping\\": "packages/Webkul/CustomExpressShipping/src"
}
}
}
Update autoloader:
composer dump-autoload
Register service provider in bootstrap/providers.php
:
<?php
return [
App\Providers\AppServiceProvider::class,
// ... other providers ...
Webkul\CustomExpressShipping\Providers\CustomExpressShippingServiceProvider::class,
];
Clear caches:
php artisan optimize:clear
Step 5: Configure Your Shipping Method
Now test the basic configuration that the generator created:
- Go to Admin Panel: Navigate to Configure → Shipping Methods
- Find Your Method: Look for "Custom Express Shipping" section
- Basic Configuration: You'll see some basic configuration fields that can be adjusted as per your needs
Translation Note
You may notice some translation keys are missing as we haven't registered translation files yet. For complete localization setup, refer to the Localization section in Package Development. The main purpose here is to understand shipping method functionality.
Generator Creates Basic Configuration
The package generator creates a simple shipping method with:
- Flat rate pricing: Single rate for all orders
- Basic admin fields: Essential configuration options
- Standard structure: Following Bagisto conventions
For advanced features like weight-based pricing, API integration, or complex calculations, you'll need to customize the generated code or use the manual approach below.
Method 2: Manual Setup (Complete Understanding)
For developers who want to understand every component, let's create the shipping method manually from scratch.
Step 1: Create Package Directory Structure
Create the complete directory structure for your shipping method package:
mkdir -p packages/Webkul/CustomExpressShipping/src/{Carriers,Config,Providers}
This creates the following structure:
packages
└── Webkul
└── CustomExpressShipping
└── src
├── Carriers/ # Shipping calculation logic
├── Config/ # Configuration files
└── Providers/ # Service provider
Step 2: Create Carrier Configuration
Create the carriers configuration file that defines your shipping method properties:
Create: packages/Webkul/CustomExpressShipping/src/Config/carriers.php
<?php
return [
'custom_express_shipping' => [
'code' => 'custom_express_shipping',
'title' => 'Express Delivery (1-2 Days)',
'description' => 'Premium express shipping with tracking and insurance',
'active' => true,
'default_rate' => '19.99',
'type' => 'per_order',
'class' => 'Webkul\CustomExpressShipping\Carriers\CustomExpressShipping',
]
];
Manual Configuration Benefits
Learning Value: Understanding each property helps you customize behavior
Flexibility: Complete control over configuration structure
Debugging: Easier to troubleshoot when you know every line
Customization: Add custom properties for advanced features
Step 3: Create Carrier Class
Create the main carrier class that handles rate calculation:
Create: packages/Webkul/CustomExpressShipping/src/Carriers/CustomExpressShipping.php
Don't Get Overwhelmed!
Don't worry about understanding every line of code right now - just go with the flow! We'll cover all these concepts in detail in the following sections:
- Carrier configuration and properties
- Rate calculation logic and methods
- System configuration and admin fields
- Advanced features and customizations
Focus on getting your shipping method working first, then dive deeper into each component.
<?php
namespace Webkul\CustomExpressShipping\Carriers;
use Webkul\Shipping\Carriers\AbstractShipping;
use Webkul\Checkout\Models\CartShippingRate;
use Webkul\Checkout\Facades\Cart;
class CustomExpressShipping extends AbstractShipping
{
/**
* Shipping method code - must match carriers.php key.
*/
protected $code = 'custom_express_shipping';
/**
* Calculate shipping rate for the current cart.
*/
public function calculate()
{
// check if shipping method is available
if (! $this->isAvailable()) {
return false;
}
$cart = Cart::getCart();
// create shipping rate object
$object = new CartShippingRate;
$object->carrier = 'custom_express_shipping';
$object->carrier_title = $this->getConfigData('title');
$object->method = 'custom_express_shipping_custom_express_shipping';
$object->method_title = $this->getConfigData('title');
$object->method_description = $this->getConfigData('description');
// calculate rate - start with base rate
$baseRate = $this->getConfigData('default_rate');
$finalRate = $baseRate;
// express shipping logic - you can customize this
if ($this->getConfigData('type') === 'per_unit') {
// calculate per item
$totalItems = 0;
foreach ($cart->items as $item) {
if ($item->product->getTypeInstance()->isStockable()) {
$totalItems += $item->quantity;
}
}
$finalRate = $baseRate * $totalItems;
} else {
// per order pricing (flat rate)
$finalRate = $baseRate;
}
// set calculated prices
$object->price = core()->convertPrice($finalRate);
$object->base_price = $finalRate;
return $object;
}
}
Step 4: Create System Configuration
Create the admin interface configuration for your shipping method:
Create: packages/Webkul/CustomExpressShipping/src/Config/system.php
<?php
return [
[
'key' => 'sales.carriers.custom_express_shipping',
'name' => 'Custom Express Shipping',
'info' => 'Configure the Custom Express Shipping method settings.',
'sort' => 1,
'fields' => [
[
'name' => 'title',
'title' => 'Method Title',
'type' => 'text',
'validation' => 'required',
'channel_based' => true,
'locale_based' => true
],
[
'name' => 'description',
'title' => 'Description',
'type' => 'textarea',
'channel_based' => true,
'locale_based' => false
],
[
'name' => 'default_rate',
'title' => 'Base Rate ($)',
'type' => 'text',
'validation' => 'required|numeric|min:0',
'channel_based' => true,
'locale_based' => false
],
[
'name' => 'type',
'title' => 'Pricing Type',
'type' => 'select',
'options' => [
[
'title' => 'Per Order (Flat Rate)',
'value' => 'per_order',
],
[
'title' => 'Per Item',
'value' => 'per_unit',
],
],
'channel_based' => true,
'locale_based' => false,
],
[
'name' => 'active',
'title' => 'Enabled',
'type' => 'boolean',
'validation' => 'required',
'channel_based' => true,
'locale_based' => false
]
]
]
];
Step 5: Create Service Provider
Create the service provider to register your shipping method with Bagisto:
Create: packages/Webkul/CustomExpressShipping/src/Providers/CustomExpressShippingServiceProvider.php
<?php
namespace Webkul\CustomExpressShipping\Providers;
use Illuminate\Support\ServiceProvider;
class CustomExpressShippingServiceProvider extends ServiceProvider
{
/**
* Register services.
*/
public function register(): void
{
// merge carrier configuration
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/carriers.php',
'carriers'
);
// merge system configuration
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/system.php',
'core'
);
}
/**
* Bootstrap services.
*/
public function boot(): void
{
}
}
Step 6: Register Your Package
After creating all the files, you need to register your package with Bagisto:
Add to composer.json (in Bagisto root directory):
{
"autoload": {
"psr-4": {
// Other PSR-4 namespaces...
"Webkul\\CustomExpressShipping\\": "packages/Webkul/CustomExpressShipping/src"
}
}
}
Update autoloader:
composer dump-autoload
Register service provider in bootstrap/providers.php
:
<?php
return [
App\Providers\AppServiceProvider::class,
// ... other providers ...
Webkul\CustomExpressShipping\Providers\CustomExpressShippingServiceProvider::class,
];
Clear caches:
php artisan optimize:clear
Testing Your Shipping Method
Now let's test your custom express shipping method:
Step 1: Enable in Admin
- Go to Admin Panel → Configure → Shipping Methods
- Find Custom Express Shipping section
- Set Enabled to Yes
- Configure your rates and settings
- Click Save Configuration
Step 2: Frontend Testing
- Add products to cart
- Proceed to checkout
- Enter shipping address
- Verify your express shipping option appears
- Check that rates calculate correctly
Step 3: Testing Checklist
Testing Checklist
Admin Configuration:
- ✅ Custom Express Shipping appears in carrier settings
- ✅ All form fields render correctly
- ✅ Settings save and persist properly
- ✅ Validation works for required fields
Frontend Functionality:
- ✅ Shipping method appears during checkout
- ✅ Rates calculate correctly
- ✅ Method title and description display properly
- ✅ Integration with cart totals works
Edge Cases:
- ✅ Method respects enabled/disabled status
- ✅ Handles empty carts gracefully
- ✅ Works with different product types
- ✅ Responds correctly to weight/price thresholds
Generated vs Manual Package Structure
Both methods create the same final structure:
packages
└── Webkul
└── CustomExpressShipping
└── src
├── Carriers
│ └── CustomExpressShipping.php # Rate calculation logic
├── Config
│ ├── carriers.php # Shipping method definition
│ └── system.php # Admin configuration
└── Providers
└── CustomExpressShippingServiceProvider.php # Registration
Choosing Your Approach
Use Package Generator When:
- Quick prototyping or testing
- Following standard Bagisto patterns
- Building simple shipping methods
- Learning Bagisto basics
Use Manual Setup When:
- Need complete control over code
- Building complex shipping logic
- Want to understand every component
- Customizing beyond standard patterns
Your Next Steps
Congratulations! You've successfully created a custom shipping method for Bagisto. Your express shipping method now integrates seamlessly with the checkout process and provides administrators with full configuration control.
Key Achievements:
- ✅ Built a complete shipping method from scratch
- ✅ Implemented basic rate calculation logic
- ✅ Created admin configuration interface
- ✅ Integrated with Bagisto's shipping system
Continue Learning
Now that you have a working shipping method, dive deeper into specific components:
📖 Understanding Carrier Configuration → Learn about carrier configuration properties, validation, and advanced options.
📖 Understanding Carrier Class → Learn how to implement the business logic and rate calculation methods for your shipping method.
📖 Understanding System Configuration → Master the admin interface creation with field types, validation, and multi-channel support.
Production Considerations
Before deploying to production:
- Test with various cart configurations
- Verify multi-channel and multi-locale settings
- Set up monitoring for rate calculation errors
- Document configuration options for administrators
Your shipping method is now complete! You can extend it further by adding features like tracking integration, delivery time estimates, or API integrations with shipping carriers.