mcpField
S
shipping-method-development

shipping-method-development

github.com/bagisto開発13270 回インストール2 週間前に更新
リポジトリ

shipping-method-development について

Bagisto の開発者向けに、カスタム配送方法の実装を案内するスキルです。キャリアクラスや料金設定、計算方法を扱い、チェックアウトへの選択肢追加や独自料金ルールの作成に役立ちます。

主な機能

  1. 01キャリアと管理設定の構成
  2. 02料金計算クラスの実装
  3. 03固定・商品単位・重量別の料金
  4. 04プロバイダーとパッケージの登録
  5. 05組み込み配送方法の例

活用シーン

  1. 01チェックアウトに配送方法を追加
  2. 02重量や注文額の条件で料金を算出
  3. 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:パッケージを登録する
  1. composer.json に追加する(Bagisto のルートディレクトリ内):
{
    "autoload": {
        "psr-4": {
            "Webkul\\CustomExpressShipping\\": "packages/Webkul/CustomExpressShipping/src"
        }
    }
}
  1. オートローダーを更新する:
composer dump-autoload
  1. bootstrap/providers.php でサービスプロバイダーを登録する:
<?php

return [
    App\Providers\AppServiceProvider::class,

    // ... other providers ...

    Webkul\CustomExpressShipping\Providers\CustomExpressShippingServiceProvider::class,
];
  1. キャッシュをクリアする:
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.phpShipping ファサード
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 の規約に従っていない

コメント