关于 magento-multi-store
这项 Magento 配置技能讲解如何在单个安装中管理多个网站、商店和本地化视图,涵盖作用域配置、路由、商品分配及 Adobe Commerce B2B 共享目录。
主要功能
- 01Website、Store 与 Store View 层级
- 02按商店代码配置 Nginx 路由
- 03全局、网站和视图级设置
- 04网站商品分配与定价
- 05Adobe Commerce B2B 共享目录
适用场景
- 01在单个 Magento 安装中运营不同国家的店面
- 02为各网站设置货币和支付方式
- 03基于共享目录创建本地化视图
- 04管理 B2B 企业专属商品可见性与价格
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ finsilabs/ awesome-ecommerce-skills --skill magento-multi-store安装后在 Claude Code 中输入/magento-multi-store确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
tile.jsonevals/cli-website-provisioning-script/criteria.jsontask.mdevals/nginx-multi-store-routing-config/criteria.jsontask.mdevals/php-scoped-config-and-product-assignment/criteria.jsontask.md详细介绍
Magento 多店铺设置
概述
Magento 的多店铺架构分为三个层级:Website → Store → Store View。Website 将拥有共享客户群和订单流程的多个店铺归为一组。Website 下的 Store 拥有自己的根类别和 URL 结构。Store 下的 Store View 通常代表不同语言或地区设置。配置值可以设为全局、Website 或 Store View 范围;较低层级的设置会覆盖较高层级的设置。Adobe Commerce(B2B)还提供 Shared Catalogs,用于按公司控制产品和价格的可见性。
何时使用此技能
- 需要通过单个 Magento 安装运行多个品牌或面向不同国家/地区的店面时
- 需要为每个 Website 设置不同的基础货币、税务配置或支付方式时
- 需要在 B2C 店铺旁创建具有不同产品可见性的 B2B 门户时
- 需要在同一产品目录下为多种语言创建本地化 Store View 时
- 需要为每个 Website 配置独立的结账流程、配送方式或支付网关时
- 需要管理共享产品目录,同时覆盖特定 Website 的定价和可见性时
核心说明
-
创建 Website → Store → Store View 层级
注意: Magento 核心版本不包含
bin/magento store:website:create、store:group:create或store:store:createCLI 命令。请通过 Admin → Stores → All Stores 或以编程方式使用 PHP(如下所示)创建 Website、Store 和 Store View。一些第三方模块会添加对应的 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(); -
配置 nginx 以支持多 Website 路由
# /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; } } -
设置范围配置值
配置可以设为全局、Website 或 Store View 范围:
# 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() ); } } -
管理特定 Website 的产品分配和定价
可以将产品分配给特定 Website,同时共享全局目录:
<?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 } }启用 Website 范围的定价:
bin/magento config:set catalog/price/scope 1 # 0 = Global, 1 = Website bin/magento indexer:reindex catalog_product_price -
配置 Adobe Commerce B2B Shared Catalogs
Shared Catalogs(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
示例
自动化多 Website 部署配置
<?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),仅在需要独立客户群、订单和支付方式时使用 Website 路由(MAGE_RUN_TYPE=website) - 上线前启用 Website 范围的定价——之后从全局范围切换到 Website 范围需要完整重建价格索引,并可能破坏现有目录规则
- 在 nginx/Apache 层设置
MAGE_RUN_CODE和MAGE_RUN_TYPE,不要在index.php中设置——这样可将路由配置保留在基础设施层,并便于复制 - 分别测试每个 Website 的结账流程——支付网关、税类和配送方式都可以按 Website 配置;一个 Website 的结账流程正常,并不意味着其他 Website 也正常
- 每次执行
config:set后清理配置缓存——范围配置更改会被缓存;自动化预配置脚本执行后,请运行bin/magento cache:clean config - 在高流量环境中为每个 Website 使用独立的 Redis 数据库——某个 Website 的缓慢重新索引可能耗尽共享缓存存储资源并影响所有 Website
- 记录 Website/Store/Store View ID 的对应关系——ID 会因环境而异;所有配置脚本中都应使用代码(
uk_en),而不是数字 ID
常见问题
| 问题 | 解决方案 |
|---|---|
| 新网站显示全局价格,忽略网站配置 | 启用网站范围的定价:先运行 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