Skip to content
beginner Phase 14 · Application Structure

Magento Bootstrap Process

Magento bootstrap process - index.php, ObjectManager initialization, area code setup, configuration loading

45m
0 problems
Topic Progress 0%

The Bootstrap Process

Overview

HTTP Request → pub/index.php
    ↓
1. Error handling setup
2. Autoloader registration
3. ObjectManager creation
4. Area code initialization
5. Configuration loading
6. Application ready

Step 1: pub/index.php

<?php
// pub/index.php

use Magento\Framework\App\Bootstrap;

// 1. Error handling
require __DIR__ . '/../app/autoload.php';

// 2. Create ObjectManager via Bootstrap
$bootstrap = Bootstrap::create(
    BP, // Base path (project root)
    [
        'mode' => 'developer', // or 'production'
    ]
);

// 3. Run application
$bootstrap->run(
    new Magento\Framework\App\Http(
        $bootstrap->getObjectManager()
    )
);

Step 2: Autoloader

// app/autoload.php
require BP . '/vendor/autoload.php';

// Composer autoloader registers:
// - PSR-4 autoloading for all modules
// - Classmap for generated classes
// - Custom autoloaders for Magento framework

Step 3: ObjectManager Creation

// Magento\Framework\App\Bootstrap::create()
// 1. Load app/etc/env.php (environment config)
// 2. Load app/etc/config.php (module list)
// 3. Create ObjectManager with configuration
// 4. Register compiled configuration if available

// ObjectManager is the DI container that:
// - Resolves all dependencies
// - Manages shared/non-shared instances
// - Handles preferences (interface → implementation)
// - Generates factories, proxies on-demand

Step 4: Area Code

// Area code determines which context we're in
// Set by the entry point:

// Frontend: area code = 'frontend'
// Admin: area code = 'adminhtml'
// REST API: area code = 'api'
// Cron: area code = 'crontab'

$bootstrap = Bootstrap::create(BP, []);
$bootstrap->run($app);

// Inside Bootstrap::run(), area code is set:
// $this->state->setAreaCode('frontend');

// Area code affects:
// - Which di.xml files are loaded
// - Which plugins are active
// - Which observers are registered
// - Which layout handles are used

Step 5: Configuration Loading

1. app/etc/env.php (DB, cache, crypt)
2. app/etc/config.php (module list)
3. All module etc/module.xml (dependencies)
4. All module etc/di.xml (dependency injection)
5. etc/frontend/di.xml (area-specific DI)
6. Compiled config (var/di/global.php if exists)
7. ObjectManager resolves all dependencies

The entire configuration is loaded and merged before any application code runs.

ObjectManager Deep Dive

What ObjectManager Does

// ObjectManager is Magento's DI container
objectManager = Bootstrap::getObjectManager();

// Create any class with dependency resolution
$product = $objectManager->create(
    \Magento\Catalog\Model\Product::class,
    ['data' => ['sku' => 'test']]
);

// Get shared instance (singleton)
$repository = $objectManager->get(
    \Magento\Catalog\Api\ProductRepositoryInterface::class
);

// Shared vs create:
// get() → returns same instance every time (shared)
// create() → returns new instance every time

Compiled Configuration

# When you run setup:di:compile
bin/magento setup:di:compile

# Magento generates:
# 1. Factories for all injectable classes
# 2. Proxies for lazy loading
# 3. Interceptors for plugin system
# 4. Compiled DI config (var/di/global.php)

# Next request uses compiled config (faster)
# Development mode: no compilation (slower but dynamic)

ObjectManager Internals

// Simplified ObjectManager resolution:
1. Check compiled config (if available)
2. Check di.xml preferences (interface → implementation)
3. Resolve constructor arguments:
   a. Type-hinted class/interface
   b. Default values from di.xml <arguments>
   c. Scalar values from di.xml
4. Create instance (shared or new)
5. Apply plugins (interceptors)
6. Return instance

// Cache: ObjectManager caches resolved definitions
// So the resolution process happens once per class

Why ObjectManager is Controversial

// BAD: Direct ObjectManager usage (anti-pattern)
$product = ObjectManager::getInstance()->get(Product::class);
// Hidden dependency, hard to test, not explicit

// GOOD: Constructor injection (preferred)
class ProductProcessor
{
    public function __construct(
        private ProductRepositoryInterface $productRepo // Explicit
    ) {}
}

ObjectManager exists to bootstrap the application. After bootstrap, use constructor injection. The ObjectManager is only used directly in very specific cases (factories, proxies).

Quiz

1. What is the first file executed in a Magento web request?

Question 1 options

2. What does the area code determine?

Question 2 options

3. What does bin/magento setup:di:compile generate?

Question 3 options

Flashcards

Question

What is the web entry point?

Answer

pub/index.php

Question

What does ObjectManager do?

Answer

DI container — resolves dependencies, manages shared instances

Question

What is an area code?

Answer

Context identifier (frontend, adminhtml, api, crontab) that determines active config

Question

What does setup:di:compile generate?

Answer

Factories, proxies, interceptors, compiled DI config

Question

Shared vs create()?

Answer

get() = shared instance (singleton), create() = new instance each time

Revision Notes

Key Takeaways

  • 1. Bootstrap: pub/index.php → autoload → ObjectManager → area code → config → ready
  • 2. ObjectManager resolves all dependencies via constructor injection
  • 3. Area code determines which DI config, plugins, and observers are active
  • 4. setup:di:compile generates factories, proxies, interceptors for production
  • 5. Always use constructor injection, not direct ObjectManager usage

Interview Tips

  • Walk through the bootstrap process step by step
  • Explain why ObjectManager is controversial (anti-pattern when used directly)
  • Discuss how area code affects which modules and plugins are loaded

Cheat Sheet

Bootstrap Process:
  1. pub/index.php (entry point)
  2. autoload.php (Composer autoloader)
  3. Bootstrap::create() → ObjectManager
  4. Area code set (frontend/adminhtml/api/crontab)
  5. Configuration loaded (env.php, config.php, di.xml)
  6. Application runs

ObjectManager:
  get()     → shared instance (singleton)
  create()  → new instance each time
  resolve() → compile dependency tree

setup:di:compile → factories + proxies + interceptors + compiled config