Skip to content
intermediate Phase 91 · Multi-store

Websites and Stores

Websites and stores - website/store/store view hierarchy, multi-store setup

45m
0 problems
Topic Progress 0%

Store Hierarchy

Website → Store → Store View

  Website (base_url)
    │
    ├── Store (product catalog)
    │     ├── Store View (en_US)
    │     └── Store View (fr_FR)
    │
    └── Store (product catalog)
          ├── Store View (de_DE)
          └── Store View (en_GB)

Entity Relationships

Entity Purpose Scope
Website Payment/shipping config Group of stores
Store Product catalog Group of views
Store View Language/translation Content display

Store Manager

namespace Vendor\MultiStore\Manager;

class StoreManager
{
    private StoreManagerInterface $storeManager;

    public function getAllStores(): array
    {
        return $this->storeManager->getStores();
    }

    public function getStoresByWebsite(int $websiteId): array
    {
        $website = $this->storeManager->getWebsite($websiteId);
        return $website->getStores();
    }

    public function getDefaultStore(): StoreInterface
    {
        return $this->storeManager->getStore(1);
    }

    public function getStoreByUrl(string $url): ?StoreInterface
    {
        foreach ($this->storeManager->getStores() as $store) {
            if (strpos($url, $store->getBaseUrl()) === 0) {
                return $store;
            }
        }
        return null;
    }
}

Multi-Store Setup

Store Configuration

namespace Vendor\MultiStore\Setup;

class StoreCreator
{
    private StoreFactoryInterface $storeFactory;
    private StoreManagerInterface $storeManager;
    private GroupFactoryInterface $groupFactory;
    private WebsiteFactoryInterface $websiteFactory;

    public function createStore(array $data): StoreInterface
    {
        // Create website
        $website = $this->websiteFactory->create();
        $website->setName($data['website_name']);
        $website->setCode($data['website_code']);
        $this->storeManager->saveWebsite($website);

        // Create store group
        $group = $this->groupFactory->create();
        $group->setName($data['store_name']);
        $group->setCode($data['store_code']);
        $group->setWebsite($website);
        $this->storeManager->saveStoreGroup($group);

        // Create store views
        foreach ($data['views'] as $viewData) {
            $store = $this->storeFactory->create();
            $store->setName($viewData['name']);
            $store->setCode($viewData['code']);
            $store->setGroupId($group->getId());
            $store->setIsActive($viewData['active'] ?? true);
            $this->storeManager->saveStore($store);
        }

        return $store;
    }
}

Store Code in URL

namespace Vendor\MultiStore\Url;

class StoreCodeResolver
{
    public function resolveFromUrl(string $url): ?string
    {
        $path = parse_url($url, PHP_URL_PATH);

        // Check if store code is in URL
        $parts = explode('/', trim($path, '/'));
        if (!empty($parts[0])) {
            $storeCode = $parts[0];
            if ($this->isValidStoreCode($storeCode)) {
                return $storeCode;
            }
        }

        return null;
    }
}

Store View Localization

Localization Configuration

namespace Vendor\MultiStore\Localization;

class LocalizationManager
{
    public function getStoreLocale(int $storeId): string
    {
        $store = $this->storeManager->getStore($storeId);
        return $store->getConfig('general/locale/code');
    }

    public function getStoreCurrency(int $storeId): string
    {
        $store = $this->storeManager->getStore($storeId);
        return $store->getConfig('currency/options/default');
    }

    public function getStoreTimezone(int $storeId): string
    {
        $store = $this->storeManager->getStore($storeId);
        return $store->getConfig('general/locale/timezone');
    }
}

Store-Specific Content

namespace Vendor\MultiStore\Content;

class StoreContentResolver
{
    public function resolve(int $storeId, string $contentKey): ?string
    {
        // Check store view scope first
        $value = $this->config->getValue(
            $contentKey,
            ScopeInterface::SCOPE_STORES,
            $storeId
        );

        if ($value !== null) {
            return $value;
        }

        // Fall back to website scope
        $store = $this->storeManager->getStore($storeId);
        $value = $this->config->getValue(
            $contentKey,
            ScopeInterface::SCOPE_WEBSITES,
            $store->getWebsiteId()
        );

        return $value;
    }
}

Multi-Store Design Patterns

Store Resolver Pattern

namespace Vendor\MultiStore\Resolver;

interface StoreResolverInterface
{
    public function resolve(Request $request): int;
}

class UrlStoreResolver implements StoreResolverInterface
{
    public function resolve(Request $request): int
    {
        $storeCode = $this->extractStoreCode($request->getPathInfo());

        if ($storeCode) {
            $store = $this->storeManager->getStore($storeCode);
            return $store->getId();
        }

        return $this->getDefaultStoreId();
    }
}

class DomainStoreResolver implements StoreResolverInterface
{
    public function resolve(Request $request): int
    {
        $host = $request->getServer('HTTP_HOST');

        foreach ($this->domainMap as $domain => $storeId) {
            if ($host === $domain) {
                return $storeId;
            }
        }

        return $this->getDefaultStoreId();
    }
}

Store-Specific Product Pricing

namespace Vendor\MultiStore\Pricing;

class StorePriceResolver
{
    public function getStorePrice(
        ProductInterface $product,
        int $storeId
    ): float {
        $price = $product->getPrice();

        // Check store-specific price override
        $override = $this->config->getValue(
            'catalog/price/' . $product->getId(),
            ScopeInterface::SCOPE_STORES,
            $storeId
        );

        if ($override !== null) {
            return (float) $override;
        }

        return $price;
    }
}

Quiz

1. What is the hierarchy of Magento store entities?

Question 1 options

2. What does a Store View control?

Question 2 options

3. How do you share a product catalog across stores?

Question 3 options

Flashcards

Question

What is a Website in Magento?

Answer

Top-level entity grouping stores with shared payment/shipping config

Question

What is a Store View?

Answer

Language/display variant of a store

Question

How to share products across stores?

Answer

Assign to same store group

Question

What is store code in URL?

Answer

Path prefix identifying the active store view

Revision Notes

Key Takeaways

  • 1. Website → Store → Store View hierarchy
  • 2. Websites share payment/shipping configuration
  • 3. Stores share product catalog within a group
  • 4. Store Views handle language and display differences
  • 5. Store code in URL activates specific store view

Interview Tips

  • Explain the website/store/store view hierarchy
  • Discuss when to use multiple websites vs store views
  • Describe store code URL resolution
  • Talk about sharing catalogs across stores

Cheat Sheet

Hierarchy:
  Website → Store → Store View

Website:
  Payment/shipping config
  Domain

Store:
  Product catalog
  Root category

Store View:
  Language
  Currency
  Display settings