Delivery Methods
Delivery widgets provide a flexible way to customize the checkout form fields for different delivery methods in sCommerce. Each delivery method can have its own Blade template that renders the necessary form fields.
Overview
Starting from version 1.x, sCommerce supports customizable delivery widgets through Blade templates. This allows you to:
- Customize checkout forms for each delivery method
- Create project-specific delivery implementations
- Integrate third-party delivery service widgets (Nova Poshta, UPS, etc.)
- Maintain consistent styling across delivery methods
Template Resolution
Templates are resolved in the following priority order:
-
Project views (highest priority)
views/delivery/{delivery-name}.blade.php -
Vendor default (lowest priority)
core/vendor/seiger/scommerce/views/delivery/{delivery-name}.blade.php
This allows you to override any delivery template by simply copying it to your project's views directory.
Available Variables
All delivery widget templates receive the following variables:
$delivery
Array containing delivery method information:
$delivery['name']- Unique delivery identifier (e.g., 'courier', 'pickup')$delivery['title']- Localized delivery method title$delivery['description']- Localized delivery method description
$checkout
Array with current checkout data:
$checkout['user']- User information$checkout['user']['address']- Address data (city, street, building, room, etc.)$checkout['cart']- Shopping cart data- Other checkout-related information
$settings
Array with delivery method settings configured in admin panel:
- Custom settings vary by delivery method
- Example for courier:
$settings['cities'],$settings['info'] - Example for pickup:
$settings['locations']
Creating Custom Delivery Widget
Step 1: Create Delivery Class
Create a new delivery method class that extends BaseDeliveryMethod:
<?php namespace App\Delivery;
use Seiger\sCommerce\Delivery\BaseDeliveryMethod;
class CustomDelivery extends BaseDeliveryMethod
{
public function getName(): string
{
return 'custom';
}
public function getType(): string
{
return "<b>Custom Delivery</b> (custom)";
}
public function getValidationRules(): array
{
return [
'delivery.custom.address' => 'required|string|max:255',
'delivery.custom.phone' => 'required|string',
];
}
public function calculateCost(array $order): float
{
return 50.00; // Fixed cost or custom calculation
}
public function defineFields(): array
{
return [
// Admin panel settings fields
];
}
public function prepareSettings(array $data): string
{
return json_encode($data, JSON_UNESCAPED_UNICODE);
}
}
Step 2: Create Widget Template
Create a Blade template for your delivery widget:
File: views/delivery/custom.blade.php
{{--
Custom Delivery Widget
Available variables: $delivery, $checkout, $settings
--}}
<label class="form-label">
<input
type="text"
name="delivery[{{$delivery['name']}}][address]"
value="{{old('delivery.'.$delivery['name'].'.address', '')}}"
placeholder="Enter delivery address"
required
/>
<span>Delivery Address</span>
</label>
<label class="form-label">
<input
type="tel"
name="delivery[{{$delivery['name']}}][phone]"
placeholder="Phone number"
required
/>
<span>Contact Phone</span>
</label>
Step 3: Register Delivery Method
The delivery method will be automatically registered when added to the database with the correct class name.
Examples
Courier Delivery
Default template location: core/vendor/seiger/scommerce/views/delivery/courier.blade.php
Features:
- City input with quick city selection
- Street, building, apartment fields
- Receiver selection (self or other person)
To customize, copy to: views/delivery/courier.blade.php
Pickup Delivery
Default template location: core/vendor/seiger/scommerce/views/delivery/pickup.blade.php
Features:
- Radio buttons for pickup location selection
- Displays all configured pickup addresses
To customize, copy to: views/delivery/pickup.blade.php
Field Naming Convention
Always use the following naming pattern for input fields:
name="delivery[{{$delivery['name']}}][field_name]"
This ensures proper data structure for:
- Validation processing
- Order data storage
- Multi-delivery support
Using Widgets in Checkout
In your checkout view, simply output the widget:
@foreach($deliveries as $delivery)
<div data-delivery="{{$delivery['name']}}">
{{-- Info message from settings --}}
@if(isset($delivery['info']) && trim($delivery['info']))
<div class="message-info">
{!! nl2br(e($delivery['info'])) !!}
</div>
@endif
{{-- Delivery widget --}}
{!! $delivery['widget'] !!}
</div>
@endforeach
The $delivery['widget'] contains the pre-rendered HTML from the delivery method's template.
Advanced Usage
Adding JavaScript
Use @push('scripts') directive to add JavaScript for your widget:
<div id="delivery-{{$delivery['name']}}">
{{-- Your form fields --}}
</div>
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', function() {
// Your JavaScript code
console.log('Delivery widget initialized');
});
</script>
@endpush
Conditional Fields with Alpine.js
<div x-data="{ showAdvanced: false }">
<label>
<input type="checkbox" x-model="showAdvanced">
Show advanced options
</label>
<div x-show="showAdvanced" x-transition>
{{-- Additional fields --}}
</div>
</div>
API Integration
For third-party delivery services:
<div id="delivery-api-widget-{{$delivery['name']}}"></div>
@push('scripts')
<script src="https://api.delivery-service.com/widget.js"></script>
<script>
DeliveryServiceWidget.init({
container: '#delivery-api-widget-{{$delivery['name']}}',
apiKey: '{{$settings['api_key'] ?? ''}}',
onSelect: function(data) {
// Handle delivery selection
}
});
</script>
@endpush
Best Practices
- Always validate input - Define validation rules in
getValidationRules() - Use translation keys - Make widgets multilingual with
__('key') - Preserve user data - Use
old()helper for form repopulation - Handle errors gracefully - Check if settings exist before using them
- Keep widgets focused - One widget = one delivery method
- Document your code - Add comments explaining complex logic
- Test across browsers - Ensure compatibility with target browsers
Troubleshooting
Widget not displaying
- Check if template file exists in one of the search paths
- Verify delivery method class implements
DeliveryMethodInterface - Check Laravel logs for rendering errors:
storage/logs/scommerce.log
Validation errors
- Ensure field names match validation rules
- Check
getValidationRules()method in delivery class - Verify all required fields are present in the widget
Styling issues
- Check if your project's CSS classes match the widget's HTML
- Consider creating a custom template in
views/delivery/ - Use browser developer tools to inspect applied styles
Migration from Hardcoded Forms
If you have existing hardcoded delivery forms in checkout.blade.php:
- Create widget template:
views/delivery/{name}.blade.php - Copy form HTML from checkout to the widget template
- Replace hardcoded values with template variables
- Update input names to use
delivery[{{$delivery['name']}}][field]format - Test checkout process thoroughly
- Remove old hardcoded form from checkout.blade.php