mcpField
M
magento-multi-store

magento-multi-store

github.com/finsilabs開発6078 回インストール5 日前に更新
リポジトリ

magento-multi-store について

単一のMagento環境で複数のWebsite、Store、ローカライズ済みStore Viewを運用するための設定スキルです。スコープ別設定、ルーティング、商品割り当て、Adobe Commerce B2B Shared Catalogsを解説します。

主な機能

  1. 01Website、Store、Store Viewの階層
  2. 02ストアコードによるNginxルーティング
  3. 03グローバル、Website、View単位の設定
  4. 04Website別の商品割り当てと価格
  5. 05Adobe Commerce B2B Shared Catalogs

活用シーン

  1. 01単一のMagento環境で国別ストアを運営
  2. 02Websiteごとの通貨や決済手段の設定
  3. 03共通カタログを使ったローカライズ済みビューの作成
  4. 04B2B企業ごとの商品表示と価格の管理

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/finsilabs/awesome-ecommerce-skills --skill magento-multi-store

インストール後、Claude Code で/magento-multi-storeを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

tile.json
evals/cli-website-provisioning-script/
criteria.json
task.md
evals/nginx-multi-store-routing-config/
criteria.json
task.md
evals/php-scoped-config-and-product-assignment/
criteria.json
task.md

詳細

Magento マルチストアのセットアップ

概要

Magento のマルチストアアーキテクチャは、Web サイト → ストア → ストアビューの 3 つの階層で構成されています。Web サイトは、顧客基盤と注文フローを共有するストアをまとめます。Web サイト配下のストアは、それぞれ独自のルートカテゴリと URL 構造を持ちます。ストア配下のストアビューは、通常、言語やロケールを表します。設定値はグローバル、Web サイト、ストアビューのスコープで設定でき、下位スコープの値が上位スコープの値を上書きします。Adobe Commerce(B2B)では、会社ごとに商品や価格の表示を制御できる共有カタログが追加されます。

このスキルを使用する場面

  • 1 つの Magento インストール環境から複数のブランドや国別のストアフロントを運営する場合
  • Web サイトごとに基本通貨、税設定、支払い方法を変更する場合
  • 商品の表示設定が異なる B2B ポータルを B2C ストアと併設する場合
  • 同じ商品カタログの下に、複数の言語向けのローカライズ済みストアビューを作成する場合
  • Web サイトごとに異なるチェックアウトフロー、配送方法、決済ゲートウェイを設定する場合
  • Web サイトごとの価格設定や表示設定を適用しながら、商品カタログを共有する場合

主な手順

  1. Web サイト → ストア → ストアビューの階層を作成する

    注: Magento コアには、bin/magento store:website:create、store:group:create、store:store:create CLI コマンドは含まれていません。Web サイト、ストア、ストアビューは、管理画面 → ストア → すべてのストアから、または PHP でプログラムから作成します(以下を参照)。サードパーティ製モジュールによって同等の CLI コマンドが追加される場合がありますが、コアには含まれていません。

    PHP でプログラムから作成する方法(主な方法):

    <?php
    // Create website via DataObject
    use Magento\Store\Model\Website;
    use Magento\Store\Model\Group;
    use Magento\Store\Model\Store;
    
    $website = $objectManager->create(Website::class);
    $website->setCode('uk_site')
            ->setName('UK Website')
            ->setDefaultGroupId(0) // Set after creating group
            ->save();
    
    $storeGroup = $objectManager->create(Group::class);
    $storeGroup->setWebsiteId($website->getId())
               ->setName('UK Store')
               ->setRootCategoryId(3) // Your UK root category ID
               ->save();
    
    $storeView = $objectManager->create(Store::class);
    $storeView->setWebsiteId($website->getId())
              ->setGroupId($storeGroup->getId())
              ->setCode('uk_en')
              ->setName('UK English')
              ->setIsActive(1)
              ->save();
    
  2. マルチ Web サイトルーティング用に nginx を設定する

    # /etc/nginx/sites-available/magento-multi-store.conf
    
    # Map host to Magento store code (MAGE_RUN_CODE + MAGE_RUN_TYPE)
    map $http_host $MAGE_RUN_CODE {
        hostnames;
        default         "";
        www.mystore.com "";         # Default (global config)
        uk.mystore.com  uk_en;     # UK store view
        de.mystore.com  de_de;     # German store view
        b2b.mystore.com b2b_en;   # B2B website
    }
    
    map $http_host $MAGE_RUN_TYPE {
        hostnames;
        default         "";
        www.mystore.com "";
        uk.mystore.com  "store";   # Route to store view
        de.mystore.com  "store";
        b2b.mystore.com "website"; # Route to website (different customer base)
    }
    
    server {
        listen 443 ssl http2;
        server_name ~^(.+\.)?mystore\.com$;
    
        root /var/www/magento/pub;
        index index.php;
    
        location ~ \.php$ {
            fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
            fastcgi_param MAGE_RUN_CODE $MAGE_RUN_CODE;
            fastcgi_param MAGE_RUN_TYPE $MAGE_RUN_TYPE;
            include fastcgi_params;
        }
    }
    
  3. スコープ付き設定値を指定する

    設定は、グローバル、Web サイト、ストアビューの各スコープで指定できます。

    # Set base URL per website
    bin/magento config:set --scope=websites --scope-code=uk_site web/secure/base_url "https://uk.mystore.com/"
    bin/magento config:set --scope=websites --scope-code=uk_site web/unsecure/base_url "https://uk.mystore.com/"
    
    # Set currency per website
    bin/magento config:set --scope=websites --scope-code=uk_site currency/options/base GBP
    bin/magento config:set --scope=websites --scope-code=uk_site currency/options/default GBP
    bin/magento config:set --scope=websites --scope-code=uk_site currency/options/allow "GBP,EUR"
    
    # Set locale per store view
    bin/magento config:set --scope=stores --scope-code=de_de general/locale/code de_DE
    bin/magento config:set --scope=stores --scope-code=de_de general/locale/timezone "Europe/Berlin"
    
    # Disable a payment method for specific website
    bin/magento config:set --scope=websites --scope-code=uk_site payment/checkmo/active 0
    

    PHP でプログラムから設定する場合:

    <?php
    use Magento\Framework\App\Config\Storage\WriterInterface;
    use Magento\Store\Model\ScopeInterface;
    
    class ScopeConfigManager
    {
        public function __construct(
            private readonly WriterInterface $configWriter,
            private readonly \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList
        ) {}
    
        public function setScopedValue(
            string $path,
            mixed $value,
            string $scope,
            int $scopeId
        ): void {
            $this->configWriter->save($path, $value, $scope, $scopeId);
            // Flush config cache after write
            $this->cacheTypeList->cleanType('config');
        }
    
        public function setWebsiteShippingOrigin(string $websiteCode, array $originData): void {
            $website = \Magento\Framework\App\ObjectManager::getInstance()
                ->create(\Magento\Store\Model\Website::class)
                ->load($websiteCode, 'code');
    
            $this->setScopedValue(
                'shipping/origin/country_id',
                $originData['country'],
                ScopeInterface::SCOPE_WEBSITES,
                (int)$website->getId()
            );
        }
    }
    
  4. Web サイト固有の商品割り当てと価格を管理する

    グローバルカタログを共有しながら、商品を特定の Web サイトに割り当てることができます。

    <?php
    // Assign a product to specific websites
    use Magento\Catalog\Model\ResourceModel\Product as ProductResource;
    
    class ProductWebsiteAssignment
    {
        public function __construct(
            private readonly ProductResource $productResource,
            private readonly \Magento\Store\Model\StoreManagerInterface $storeManager
        ) {}
    
        public function assignProductToWebsite(int $productId, string $websiteCode): void {
            $website = $this->storeManager->getWebsite($websiteCode);
            $this->productResource->websiteToProducts([
                ['product_id' => $productId, 'website_id' => $website->getId()],
            ]);
        }
    
        public function setWebsitePrice(int $productId, string $websiteCode, float $price): void {
            // Use tier prices with website scope for website-specific pricing
            $tierPriceResource = \Magento\Framework\App\ObjectManager::getInstance()
                ->create(\Magento\Catalog\Model\ResourceModel\Product\Attribute\Backend\Tierprice::class);
            // Or use price scope: Admin → Config → Catalog → Price → Catalog Price Scope = Website
        }
    }
    

    Web サイトスコープの価格設定を有効にします。

    bin/magento config:set catalog/price/scope 1  # 0 = Global, 1 = Website
    bin/magento indexer:reindex catalog_product_price
    
  5. Adobe Commerce の B2B 共有カタログを設定する

    共有カタログ(B2B 機能)を使用すると、会社ごとに商品や価格の表示を設定できます。

    <?php
    // Assign a company to a custom shared catalog
    use Magento\SharedCatalog\Api\SharedCatalogManagementInterface;
    use Magento\SharedCatalog\Api\Data\SharedCatalogInterface;
    
    class SharedCatalogManager
    {
        public function __construct(
            private readonly SharedCatalogManagementInterface $sharedCatalogManagement,
            private readonly \Magento\SharedCatalog\Api\SharedCatalogRepositoryInterface $catalogRepository,
            private readonly \Magento\Company\Api\CompanyRepositoryInterface $companyRepository
        ) {}
    
        public function assignCompanyToCatalog(int $companyId, int $sharedCatalogId): void {
            $sharedCatalog = $this->catalogRepository->get($sharedCatalogId);
            $company = $this->companyRepository->get($companyId);
            $company->getExtensionAttributes()->getQuoteConfig()?->setCustomerGroupId(
                $sharedCatalog->getCustomerGroupId()
            );
            $this->companyRepository->save($company);
        }
    }
    
    # CLI: Assign products to a shared catalog (by SKU list from CSV)
    bin/magento company:catalog:assign --catalog-id=2 --products-file=products.csv
    
    # Set catalog-specific pricing via import
    bin/magento import:start --entity=shared_catalog_product_price --behavior=add_update --import-file=prices.csv
    

例

マルチ Web サイトのデプロイ設定を自動化する
<?php
// Console command to provision a new website from config array
namespace MyVendor\MultiStore\Console\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class ProvisionWebsiteCommand extends Command
{
    protected function configure(): void
    {
        $this->setName('mystore:website:provision')
             ->setDescription('Provision a new website from config');
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $websites = [
            [
                'code' => 'au_site',
                'name' => 'Australia',
                'domain' => 'au.mystore.com',
                'currency' => 'AUD',
                'locale' => 'en_AU',
                'timezone' => 'Australia/Sydney',
                'root_category_id' => 5,
            ],
        ];

        foreach ($websites as $config) {
            $output->writeln("Creating website: {$config['code']}");
            // Execute creation commands...
            $this->createWebsite($config, $output);
        }

        return Command::SUCCESS;
    }

    private function createWebsite(array $config, OutputInterface $output): void
    {
        // Implementation: create Website → Group → StoreView → set config
    }
}
カスタムモジュールでスコープ付き設定を読み取る
<?php
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;

class StoreAwareConfig
{
    public function __construct(
        private readonly ScopeConfigInterface $scopeConfig
    ) {}

    public function getWebsiteConfig(string $path, ?string $websiteCode = null): mixed
    {
        return $this->scopeConfig->getValue(
            $path,
            ScopeInterface::SCOPE_WEBSITE,
            $websiteCode // null = current website
        );
    }

    public function getStoreConfig(string $path, ?string $storeCode = null): mixed
    {
        return $this->scopeConfig->getValue(
            $path,
            ScopeInterface::SCOPE_STORE,
            $storeCode // null = current store view
        );
    }

    // Usage
    public function getShippingOriginCountry(): string
    {
        return (string)$this->getStoreConfig('shipping/origin/country_id');
    }
}

ベストプラクティス

  • 言語違いのバリエーションにはストアコードルーティング(MAGE_RUN_TYPE=store)を使用し、顧客基盤、注文、支払い方法を分ける必要がある場合にのみ Web サイトルーティング(MAGE_RUN_TYPE=website)を使用します
  • 本番稼働前に Web サイトスコープの価格設定を有効にします — グローバルスコープから Web サイトスコープへの切り替えには、価格インデックスの全件再構築が必要となり、既存のカタログルールに影響する可能性があります
  • MAGE_RUN_CODE と MAGE_RUN_TYPE は index.php ではなく nginx/Apache のレベルで設定します — これにより、ルーティング設定をインフラストラクチャ層に保ち、複製を容易にできます
  • 各 Web サイトのチェックアウトを個別にテストします — 決済ゲートウェイ、税クラス、配送方法はすべて Web サイトごとに設定できます。ある Web サイトでチェックアウトが動作しても、他の Web サイトで動作するとは限りません
  • config:set を実行するたびに設定キャッシュをフラッシュします — スコープ付き設定の変更はキャッシュされます。自動プロビジョニングスクリプトの実行後に bin/magento cache:clean config を実行してください
  • 高トラフィック環境では、Web サイトごとに Redis データベースを分けます — ある Web サイトでの再インデックスに時間がかかると、共有キャッシュストレージが飽和し、すべての Web サイトに影響する可能性があります
  • Web サイト、ストア、ストアビューの ID 対応表を記録します — ID は環境間で変わるため、すべての設定スクリプトで数値 ID ではなくコード(uk_en)を使用してください

よくある落とし穴

問題解決策
新しいウェブサイトに、ウェブサイトの設定を無視してグローバル価格が表示されるウェブサイト単位の価格設定を有効にします:bin/magento config:set catalog/price/scope 1 を実行し、その後 catalog_product_price を再インデックスします
nginx の MAGE_RUN_CODE が PHP に渡されないfastcgi_param MAGE_RUN_CODE が location ~ \.php$ ブロック内にあり、外にないことを確認します。よくある配置ミスです
あるウェブサイトの顧客が別のウェブサイトにもログインできるMAGE_RUN_TYPE=website のウェブサイトは、デフォルトで顧客プールを共有します。ウェブサイトごとに顧客アカウントの共有範囲を設定するには、Admin → Config → Customer → Account Sharing で有効にします
商品が誤ったウェブサイトに表示されるAdmin → Catalog で商品の「Product in Websites」属性を確認します。商品を表示する各ウェブサイトに、商品を明示的に割り当てる必要があります
スコープ付き設定が反映されない設定値はキャッシュされます。変更後は必ず bin/magento cache:clean config を実行してください。また、スコープコードのスペルが完全に一致していることも確認します
B2B の共有カタログで商品が絞り込まれない顧客を、適切なカタログが設定された会社に割り当てる必要があります。ゲスト顧客と会社に所属していない顧客には、公開共有カタログのみが表示されます

関連スキル

  • @magento-module-development
  • @magento-graphql
  • @magento-indexing-caching
  • @international-ecommerce
  • @b2b-commerce

コメント