Skip to content
intermediate Phase 91 · Multi-store

Configuration Scopes

Configuration scopes - global, website, store, store view scope inheritance

45m
0 problems
Topic Progress 0%

Scope Hierarchy

Configuration Scope Levels

  Default (app/etc/config.php)
    │
    ├── Website
    │     ├── Store
    │     │     ├── Store View (en_US)
    │     │     └── Store View (fr_FR)
    │     └── Store
    │           └── Store View (de_DE)
    └── Website
          └── Store
                └── Store View (en_GB)

Scope Constants

namespace Magento\Framework\App\Config;

interface ScopeInterface
{
    const SCOPE_DEFAULT = 'default';
    const SCOPE_WEBSITES = 'websites';
    const SCOPE_STORES = 'stores';
    const SCOPE_STORE = 'store';
}

Scope Resolver

namespace Vendor\Config\Scope;

class ScopeResolver
{
    private StoreManagerInterface $storeManager;

    public function resolve(int $storeId): array
    {
        $store = $this->storeManager->getStore($storeId);
        $website = $store->getWebsite();

        return [
            'default' => null,
            'website' => $website->getId(),
            'store' => $store->getId(),
            'store_view' => $storeId,
        ];
    }
}

Scope Configuration

Reading Config by Scope

namespace Vendor\Config\Reader;

class ScopedConfigReader
{
    private ConfigInterface $config;

    public function getValue(
        string $path,
        string $scope,
        int $scopeId
    ): mixed {
        return $this->config->getValue($path, $scope, $scopeId);
    }

    public function getWebsiteValue(string $path, int $websiteId): mixed
    {
        return $this->config->getValue(
            $path,
            ScopeInterface::SCOPE_WEBSITES,
            $websiteId
        );
    }

    public function getStoreValue(string $path, int $storeId): mixed
    {
        return $this->config->getValue(
            $path,
            ScopeInterface::SCOPE_STORES,
            $storeId
        );
    }
}

Scope-Aware Service

namespace Vendor\Config\Service;

class ScopeAwareService
{
    private ConfigInterface $config;
    private ScopeResolverInterface $scopeResolver;

    public function getConfigValue(
        string $path,
        int $storeId
    ): mixed {
        // Try store view scope first
        $value = $this->config->getValue(
            $path,
            ScopeInterface::SCOPE_STORES,
            $storeId
        );

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

        // Fall back to website scope
        $scopes = $this->scopeResolver->resolve($storeId);
        $value = $this->config->getValue(
            $path,
            ScopeInterface::SCOPE_WEBSITES,
            $scopes['website']
        );

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

        // Fall back to default
        return $this->config->getValue(
            $path,
            ScopeInterface::SCOPE_DEFAULT
        );
    }
}

Scope Inheritance

Config Value Resolution

namespace Vendor\Config\Inheritance;

class ConfigValueResolver
{
    private ConfigInterface $config;

    public function resolve(
        string $path,
        int $storeId
    ): ResolvedValue {
        $storeValue = $this->config->getValue(
            $path,
            ScopeInterface::SCOPE_STORES,
            $storeId
        );

        $websiteId = $this->getWebsiteId($storeId);
        $websiteValue = $this->config->getValue(
            $path,
            ScopeInterface::SCOPE_WEBSITES,
            $websiteId
        );

        $defaultValue = $this->config->getValue(
            $path,
            ScopeInterface::SCOPE_DEFAULT
        );

        return new ResolvedValue([
            'value' => $storeValue ?? $websiteValue ?? $defaultValue,
            'scope' => $storeValue !== null ? 'store' : (
                $websiteValue !== null ? 'website' : 'default'
            ),
        ]);
    }
}

Scope Override Check

namespace Vendor\Config\Override;

class ScopeOverrideChecker
{
    public function hasOverride(
        string $path,
        int $storeId
    ): bool {
        $storeValue = $this->config->getValue(
            $path,
            ScopeInterface::SCOPE_STORES,
            $storeId
        );

        return $storeValue !== null;
    }

    public function getOverrides(int $websiteId): array
    {
        $overrides = [];
        $allPaths = $this->config->getAllPaths();

        foreach ($allPaths as $path) {
            $websiteValue = $this->config->getValue(
                $path,
                ScopeInterface::SCOPE_WEBSITES,
                $websiteId
            );

            if ($websiteValue !== null) {
                $overrides[$path] = $websiteValue;
            }
        }

        return $overrides;
    }
}

Scope in Admin

Admin Scope Selector

<!-- system.xml scope attributes -->
<field id="field_name" translate="label" type="text" sortOrder="10"
       showInDefault="1" showInWebsite="1" showInStore="1">
    <label>Field Label</label>
</field>

Scope-Aware Save

namespace Vendor\Config\Admin\Save;

class ScopedConfigSaver
{
    private ConfigInterface $config;

    public function save(
        string $path,
        mixed $value,
        string $scope,
        int $scopeId
    ): void {
        $this->config->setValue(
            $path,
            $value,
            $scope,
            $scopeId
        );
        $this->config->save();
    }
}

Scope Display in Admin

namespace Vendor\Config\Admin\Display;

class ScopeAwareRenderer
{
    public function renderValue(
        string $path,
        int $storeId
    ): array {
        $storeValue = $this->config->getValue(
            $path,
            ScopeInterface::SCOPE_STORES,
            $storeId
        );

        $websiteValue = $this->config->getValue(
            $path,
            ScopeInterface::SCOPE_WEBSITES,
            $this->getWebsiteId($storeId)
        );

        $defaultValue = $this->config->getValue(
            $path,
            ScopeInterface::SCOPE_DEFAULT
        );

        return [
            'current' => $storeValue ?? $websiteValue ?? $defaultValue,
            'inherited' => $storeValue === null,
            'scope' => $storeValue !== null ? 'Store' : (
                $websiteValue !== null ? 'Website' : 'Default'
            ),
        ];
    }
}

Quiz

1. What is scope inheritance?

Question 1 options

2. How do you read store-specific config?

Question 2 options

3. What does showInStore='1' mean in system.xml?

Question 3 options

Flashcards

Question

What are the scope levels?

Answer

Default → Website → Store → Store View

Question

How does scope inheritance work?

Answer

More specific scope overrides broader scope

Question

How to read store config?

Answer

getValue(path, SCOPE_STORES, storeId)

Question

What is showInStore?

Answer

system.xml attribute allowing store view scope override

Revision Notes

Key Takeaways

  • 1. Scope hierarchy: Default → Website → Store → Store View
  • 2. More specific scopes override broader ones
  • 3. showInStore/Website/Default controls admin field visibility
  • 4. Config values resolve by checking most specific scope first
  • 5. Scope-aware services read config at correct level

Interview Tips

  • Explain scope hierarchy and inheritance order
  • Discuss when to use each scope level
  • Describe how to read config at different scopes
  • Talk about scope-aware design patterns

Cheat Sheet

Scopes:
  Default → global fallback
  Website → payment/shipping
  Store → catalog
  Store View → language/display

Inheritance:
  Store View → Website → Default
  First non-null value wins

Reading:
  getValue($path, $scope, $scopeId)
  $scope = 'default'/'websites'/'stores'