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?
2. What does a Store View control?
3. How do you share a product catalog across stores?
Flashcards
Question
What is a Website in Magento?
Click to reveal answer
Answer
Top-level entity grouping stores with shared payment/shipping config
Question
What is a Store View?
Click to reveal answer
Answer
Language/display variant of a store
Question
How to share products across stores?
Click to reveal answer
Answer
Assign to same store group
Question
What is store code in URL?
Click to reveal answer
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