Critical Flow

1. Store Resolution Flow

Store resolution occurs during application bootstrap to determine which store view to use for the current request. This affects all scoped configuration, URLs, and content.

[1] HTTP Request arrives at index.php
|
[2] Bootstrap -> Application::launch()
|
[3] StoreManager::getStore() called
|
[4] StoreResolver::getCurrentStoreId()
|
+--> StorePathInfoValidator::getValidStoreCode() // Check URL path
| e.g., /french/products -> "french"
|
+--> Request::getParam('___store') // Check GET param
| e.g., ?___store=french
|
+--> StoreCookieManager::getStoreCodeFromCookie()
| // Check 'store' cookie
|
[5] Validate store is active and in allowed list
|
[6] StoreRepository::getActiveStoreByCode() or getActiveStoreById()
|
[7] Return StoreInterface instance

Store Resolution Priority

1. URL Path contains store code?
Use store from URL (e.g., /french/catalog/product)
2. GET parameter ___store present?
Use store from parameter, set cookie
3. Store cookie exists?
Use store from cookie
4. Fallback
Use default store from MAGE_RUN_CODE or website default
Critical Flow

2. Scope Configuration Resolution

When ScopeConfigInterface::getValue() is called, configuration values are resolved with proper fallback from store -> website -> default scope.

[1] ScopeConfig::getValue('path/to/config', ScopeInterface::SCOPE_STORE, $storeCode)
|
[2] ScopePool::getScope('stores', $storeCode)
|
[3] Check store-level value in core_config_data
| scope='stores', scope_id=[store_id]
|
+--> Found? Return value
|
[4] Check website-level value
| scope='websites', scope_id=[website_id]
|
+--> Found? Return value
|
[5] Check default-level value
| scope='default', scope_id=0
|
+--> Found? Return value
|
[6] Return null (no value at any scope)
Caching

Configuration data is heavily cached. The entire core_config_data table is loaded into memory and cached by scope. Use bin/magento cache:flush config after programmatic config changes.

Important Flow

3. Store Switching Flow

When a customer switches stores (e.g., via store switcher dropdown), several steps ensure proper redirection and state management.

  1. Customer clicks store switcher link
    Link format: /stores/store/redirect/?___store=french&___from_store=default
  2. Redirect controller validates store codes
    Ensures both source and target stores exist and are active
  3. StoreCookieManager::setStoreCookie($store)
    Persists selected store in cookie for future requests
  4. URL Rewrite lookup for target store
    Attempts to find equivalent URL in target store
  5. Redirect to target store URL
    Maintains URL path if possible, or redirects to home
// Store switch link generation $urlBuilder->getUrl('stores/store/redirect', [ '___store' => $targetStoreCode, '___from_store' => $currentStoreCode, '_query' => ['uenc' => $encodedUrl] ]);
Important Flow

4. Multi-Store URL Generation

URL generation must account for store-specific base URLs, URL rewrites, and store codes in path.

[1] UrlInterface::getUrl($routePath, $routeParams)
|
[2] StoreUrlRouteParamsResolver plugin intercepts
|
+--> Extract '_scope' from params (target store)
+--> Extract '_scope_to_url' (whether to add store code)
|
[3] Store::getBaseUrl($type) // LINK, MEDIA, STATIC, WEB
|
[4] Check configuration 'web/url/use_store'
|
+--> true: Add store code to path: /french/catalog/product
+--> false: No store code: /catalog/product
|
[5] Apply HTTPS if required (isCurrentlySecure())
|
[6] Return complete URL
URL Configuration Per Store

Each store can have a different base URL configured in web/unsecure/base_url and web/secure/base_url. This enables subdomain-based multi-store setups (e.g., uk.example.com, de.example.com).

Important Flow

5. Store Repository Caching Flow

The StoreRepository implements in-memory caching to avoid repeated database queries.

[1] StoreRepository::get($code)
|
[2] Check $this->entities[$code] (in-memory cache)
|
+--> Hit? Return cached StoreInterface
|
[3] Miss: StoreFactory::create()->load($code, 'code')
|
[4] Validate store exists
|
+--> Not found? Throw NoSuchEntityException
|
[5] Cache in $this->entities[$code]
|
[6] Return StoreInterface

Cache Invalidation

// Reinitialize all store data (clears all caches) $storeManager->reinitStores(); // This internally calls: $this->cache->clean( Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, [StoreResolver::CACHE_TAG, Store::CACHE_TAG] ); $this->scopeConfig->clean(); $this->storeRepository->clean(); $this->websiteRepository->clean(); $this->groupRepository->clean();
Standard Flow

6. Single Store Mode Detection

Single store mode simplifies the admin UI when only one store view exists.

[1] StoreManager::isSingleStoreMode()
|
[2] Check isSingleStoreModeEnabled()
| Config: general/single_store_mode/enabled
|
+--> Disabled? Return false
|
[3] Check hasSingleStore()
|
+--> count($this->getStores(true)) < 3
| // Admin store (0) + Default (1) = 2 stores minimum
|
[4] Return true if both conditions met
Admin Store (ID: 0)

Magento always has an "admin" store with ID 0. This is why hasSingleStore() checks for < 3 stores: admin (0) + one real store = 2 is still "single store".