shipping-method-development について
Bagisto の開発者向けに、カスタム配送方法の実装を案内するスキルです。キャリアクラスや料金設定、計算方法を扱い、チェックアウトへの選択肢追加や独自料金ルールの作成に役立ちます。
主な機能
- 01キャリアと管理設定の構成
- 02料金計算クラスの実装
- 03固定・商品単位・重量別の料金
- 04プロバイダーとパッケージの登録
- 05組み込み配送方法の例
活用シーン
- 01チェックアウトに配送方法を追加
- 02重量や注文額の条件で料金を算出
- 03販売チャネルごとに送料を設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ bagisto/ agent-skills --skill shipping-method-developmentインストール後、Claude Code で/shipping-method-developmentを入力して読み込まれたか確認します。
詳細
配送方法の開発
概要
Bagisto でカスタム配送方法を作成すると、ビジネスのニーズに合わせて配送オプションを調整できます。壊れやすい商品の特別な取り扱いや、速達オプション、地域固有の配送ルールなどが必要な場合、カスタム配送方法を利用すれば、EC ストアに必要な柔軟性を実現できます。
このチュートリアルでは、あらゆる種類の配送ソリューションを構築するために必要な基本概念をすべて紹介する、カスタム速達配送方法を作成します。
適用するタイミング
次の場合に、このスキルを有効にしてください:
- 新しい配送方法を作成するとき
- 配送業者(FedEx、UPS、DHL、USPS など)を連携するとき
- チェックアウトに配送オプションを追加するとき
- 既存の配送設定を変更するとき
- 配送方法の管理者向け設定を作成するとき
- 料金計算ロジックを実装するとき
Bagisto の配送アーキテクチャ
Bagisto の配送システムは、設定とビジネスロジックを分離する、柔軟な配送業者ベースのアーキテクチャで構築されています。
主なコンポーネント
| コンポーネント | 目的 | 場所 |
|---|---|---|
| 配送業者の設定 | 配送方法のプロパティを定義します | Config/carriers.php |
| 配送業者クラス | 料金計算ロジックを含みます | Carriers/ClassName.php |
| システム設定 | 管理者インターフェースのフォームを定義します | Config/system.php |
| サービスプロバイダー | 配送方法を登録します | Providers/ServiceProvider.php |
| 配送ファサード | 料金を収集して管理します | Webkul\Shipping\Shipping |
主な機能
- 柔軟な料金計算:単位ごと、注文ごと、重量ベース、またはカスタム料金に対応します。
- 設定管理:管理者が使いやすい設定インターフェースを提供します。
- マルチチャネル対応:販売チャネルごとに異なる料金と設定を適用できます。
- ローカライズ対応:翻訳を全面的にサポートします。
- 拡張可能なアーキテクチャ:サードパーティ API と簡単に連携できます。
手順ガイド
ステップ 1:パッケージのディレクトリー構造を作成する
mkdir -p packages/Webkul/CustomExpressShipping/src/{Carriers,Config,Providers}
ステップ 2:配送業者の設定を作成する
ファイル: 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',
'active' => true,
'default_rate' => '19.99',
'type' => 'per_order',
'class' => 'Webkul\CustomExpressShipping\Carriers\CustomExpressShipping',
],
];
設定プロパティの説明
| プロパティ | 型 | 目的 | 説明 |
|---|---|---|---|
code | 文字列 | 一意の識別子 | 配列キーおよび配送業者クラスの $code プロパティと一致させる必要があります。 |
title | 文字列 | デフォルトの表示名 | チェックアウト時に顧客に表示されます(管理画面で上書きできます)。 |
description | 文字列 | 配送方法の説明 | 配送サービスの簡単な説明です。 |
active | ブール値 | デフォルトの状態 | 配送方法をデフォルトで有効にするかどうかを指定します。 |
default_rate | 文字列/浮動小数点数 | 基本配送料 | 計算前の基本配送料です。 |
type | 文字列 | 料金モデル | per_order(定額料金)または per_unit(商品ごと)を指定します。 |
class | 文字列 | 配送業者クラスの名前空間 | 配送業者クラスへの完全なパスです。 |
注: 配列キー(
custom_express_shipping)は、配送業者クラスのcodeプロパティおよびシステム設定のキーのパスと一致させ、全体で一貫性を保つ必要があります。
ステップ 3:配送業者クラスを作成する
ファイル: packages/Webkul/CustomExpressShipping/src/Carriers/CustomExpressShipping.php
<?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.
*
* @var string
*/
protected $code = 'custom_express_shipping';
/**
* Shipping method code.
*
* @var string
*/
protected $method = 'custom_express_shipping_custom_express_shipping';
/**
* Calculate shipping rate for the current cart.
*
* @return \Webkul\Checkout\Models\CartShippingRate|false
*/
public function calculate()
{
if (! $this->isAvailable()) {
return false;
}
return $this->getRate();
}
/**
* Get shipping rate.
*
* @return \Webkul\Checkout\Models\CartShippingRate
*/
public function getRate(): CartShippingRate
{
$cart = Cart::getCart();
$cartShippingRate = new CartShippingRate;
$cartShippingRate->carrier = $this->getCode();
$cartShippingRate->carrier_title = $this->getConfigData('title');
$cartShippingRate->method = $this->getMethod();
$cartShippingRate->method_title = $this->getConfigData('title');
$cartShippingRate->method_description = $this->getConfigData('description');
$cartShippingRate->price = 0;
$cartShippingRate->base_price = 0;
$baseRate = (float) $this->getConfigData('default_rate');
if ($this->getConfigData('type') == 'per_unit') {
foreach ($cart->items as $item) {
if ($item->getTypeInstance()->isStockable()) {
$cartShippingRate->price += core()->convertPrice($baseRate) * $item->quantity;
$cartShippingRate->base_price += $baseRate * $item->quantity;
}
}
} else {
$cartShippingRate->price = core()->convertPrice($baseRate);
$cartShippingRate->base_price = $baseRate;
}
return $cartShippingRate;
}
}
ステップ 4:システム設定を作成する
ファイル: 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,
],
],
],
];
システム設定フィールドのプロパティ
| プロパティ | 用途 | 説明 |
|---|---|---|
name | フィールド識別子 | 設定値の保存と取得に使用します。 |
title | フィールドラベル | 管理フォームに表示されるラベルです。 |
type | 入力タイプ | text、textarea、boolean、select、password などです。 |
default_value | デフォルト設定 | 初回設定時の初期値です。 |
channel_based | マルチストア対応 | 販売チャネルごとに異なる値を設定できます。 |
locale_based | 多言語対応 | 言語ごとに翻訳可能なコンテンツを設定できます。 |
validation | フィールドのバリデーション | required、numeric、email などのルールです。 |
手順 5:サービスプロバイダーを作成する
ファイル: packages/Webkul/CustomExpressShipping/src/Providers/CustomExpressShippingServiceProvider.php
<?php
namespace Webkul\CustomExpressShipping\Providers;
use Illuminate\Support\ServiceProvider;
class CustomExpressShippingServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register(): void
{
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/carriers.php',
'carriers'
);
$this->mergeConfigFrom(
dirname(__DIR__) . '/Config/system.php',
'core'
);
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot(): void
{
//
}
}
手順 6:パッケージを登録する
- composer.json に追加する(Bagisto のルートディレクトリ内):
{
"autoload": {
"psr-4": {
"Webkul\\CustomExpressShipping\\": "packages/Webkul/CustomExpressShipping/src"
}
}
}
- オートローダーを更新する:
composer dump-autoload
bootstrap/providers.phpでサービスプロバイダーを登録する:
<?php
return [
App\Providers\AppServiceProvider::class,
// ... other providers ...
Webkul\CustomExpressShipping\Providers\CustomExpressShippingServiceProvider::class,
];
- キャッシュをクリアする:
php artisan optimize:clear
基底キャリアクラスのリファレンス
場所: packages/Webkul/Shipping/src/Carriers/AbstractShipping.php
すべての配送方法は Webkul\Shipping\Carriers\AbstractShipping を継承します。
<?php
namespace Webkul\Shipping\Carriers;
use Webkul\Shipping\Exceptions\CarrierCodeException;
abstract class AbstractShipping
{
/**
* Shipping method carrier code.
*
* @var string
*/
protected $code;
/**
* Shipping method code.
*
* @var string
*/
protected $method;
abstract public function calculate();
/**
* Checks if shipping method is available.
*
* @return array
*/
public function isAvailable()
{
return $this->getConfigData('active');
}
/**
* Returns shipping method carrier code.
*
* @return string
*/
public function getCode()
{
if (empty($this->code)) {
throw new CarrierCodeException('Carrier code should be initialized.');
}
return $this->code;
}
/**
* Return shipping method code.
*
* @return string
*/
public function getMethod()
{
if (empty($this->method)) {
$code = $this->getCode();
return $code . '_' . $code;
}
return $this->method;
}
/**
* Returns shipping method title.
*
* @return array
*/
public function getTitle()
{
return $this->getConfigData('title');
}
/**
* Returns shipping method description.
*
* @return array
*/
public function getDescription()
{
return $this->getConfigData('description');
}
/**
* Retrieve information from shipping configuration.
*
* @param string $field
* @return mixed
*/
public function getConfigData($field)
{
return core()->getConfigData('sales.carriers.' . $this->getCode() . '.' . $field);
}
}
CartShippingRate モデル
場所: packages/Webkul/Checkout/src/Models/CartShippingRate.php
<?php
namespace Webkul\Checkout\Models;
use Illuminate\Database\Eloquent\Model;
use Webkul\Checkout\Contracts\CartShippingRate as CartShippingRateContract;
class CartShippingRate extends Model implements CartShippingRateContract
{
protected $fillable = [
'carrier',
'carrier_title',
'method',
'method_title',
'method_description',
'price',
'base_price',
'discount_amount',
'base_discount_amount',
'tax_percent',
'tax_amount',
'base_tax_amount',
'price_incl_tax',
'base_price_incl_tax',
'applied_tax_rate',
];
}
実装する主要メソッド
| メソッド | 用途 | 必須 |
|---|---|---|
calculate() | 配送料を計算して返します | はい(抽象メソッド) |
getRate() | CartShippingRate オブジェクトを構築します | いいえ(インライン実装可能) |
isAvailable() | 独自の利用可否判定を行うためにオーバーライドします | いいえ(デフォルトを使用) |
組み込みの配送方法
- FlatRate:
packages/Webkul/Shipping/src/Carriers/FlatRate.php - Free:
packages/Webkul/Shipping/src/Carriers/Free.php
料金設定の例
固定料金の配送
public function calculate()
{
if (! $this->isAvailable()) {
return false;
}
$cartShippingRate = new CartShippingRate;
$cartShippingRate->carrier = $this->getCode();
$cartShippingRate->carrier_title = $this->getConfigData('title');
$cartShippingRate->method = $this->getMethod();
$cartShippingRate->method_title = $this->getConfigData('title');
$cartShippingRate->method_description = $this->getConfigData('description');
$cartShippingRate->price = 15.99;
$cartShippingRate->base_price = 15.99;
return $cartShippingRate;
}
重量に基づく料金設定
public function calculate()
{
if (! $this->isAvailable()) {
return false;
}
$cart = Cart::getCart();
$baseRate = 5.00;
$perKg = 2.50;
$price = $baseRate + ($cart->weight * $perKg);
$cartShippingRate = new CartShippingRate;
$cartShippingRate->carrier = $this->getCode();
$cartShippingRate->carrier_title = $this->getConfigData('title');
$cartShippingRate->method = $this->getMethod();
$cartShippingRate->method_title = $this->getConfigData('title');
$cartShippingRate->price = core()->convertPrice($price);
$cartShippingRate->base_price = $price;
return $cartShippingRate;
}
一定額以上で送料無料
public function calculate()
{
if (! $this->isAvailable()) {
return false;
}
$cart = Cart::getCart();
$threshold = (float) $this->getConfigData('free_shipping_threshold');
$price = $cart->sub_total >= $threshold ? 0 : (float) $this->getConfigData('default_rate');
$cartShippingRate = new CartShippingRate;
$cartShippingRate->carrier = $this->getCode();
$cartShippingRate->carrier_title = $this->getConfigData('title');
$cartShippingRate->method = $this->getMethod();
$cartShippingRate->method_title = $this->getConfigData('title');
$cartShippingRate->price = core()->convertPrice($price);
$cartShippingRate->base_price = $price;
return $cartShippingRate;
}
Shipping ファサード
場所: packages/Webkul/Shipping/src/Shipping.php
Shipping ファサードは、料金の収集と処理を管理します。
class Shipping
{
public function collectRates()
{
// Iterates through all carriers and calls calculate()
// Returns grouped shipping methods with rates
}
public function getGroupedAllShippingRates()
{
// Returns rates grouped by carrier
}
public function getShippingMethods()
{
// Returns available shipping methods
}
}
パッケージ構成
packages
└── Webkul
└── CustomExpressShipping
└── src
├── Carriers
│ └── CustomExpressShipping.php # Rate calculation logic
├── Config
│ ├── carriers.php # Shipping method definition
│ └── system.php # Admin configuration
└── Providers
└── CustomExpressShippingServiceProvider.php # Registration
テスト
配送方法はチェックアウトのフローを通じてテストできます。次の項目をテストしてください。
- 有効にしたときに、チェックアウトに配送方法が表示される
- 料金が正しく計算される
- 管理画面の設定が正しく保存される
- 配送方法が有効/無効の状態に従う
主要ファイルのリファレンス
| ファイル | 用途 |
|---|---|
packages/Webkul/Shipping/src/Carriers/AbstractShipping.php | 基底抽象クラス |
packages/Webkul/Shipping/src/Carriers/FlatRate.php | 定額配送の例 |
packages/Webkul/Shipping/src/Carriers/Free.php | 送料無料の例 |
packages/Webkul/Shipping/src/Config/carriers.php | デフォルトのキャリア設定 |
packages/Webkul/Shipping/src/Shipping.php | Shipping ファサード |
packages/Webkul/Checkout/src/Models/CartShippingRate.php | 配送料モデル |
packages/Webkul/Admin/src/Config/system.php | 管理画面の設定(キャリアセクション) |
よくある落とし穴
- サービスプロバイダーで設定をマージし忘れる
$codeプロパティと設定配列のキーが一致していないbootstrap/providers.phpでサービスプロバイダーを登録していない- パッケージの追加後に
composer dump-autoloadを実行し忘れる - 設定を変更した後にキャッシュをクリアし忘れる
- 複数通貨に対応するための
core()->convertPrice()を使用していない - 商品ごとの計算で
isStockable()を確認していない - 適切な句読点を用いた PHPDoc の規約に従っていない