• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

codeigniter4 / CodeIgniter4 / 20604399136

30 Dec 2025 07:35PM UTC coverage: 85.499% (+1.0%) from 84.522%
20604399136

Pull #9860

github

web-flow
Merge 12167db76 into 455068a22
Pull Request #9860: feat: allow overriding namespaced views via `app/Views` directory

9 of 9 new or added lines in 1 file covered. (100.0%)

87 existing lines in 2 files now uncovered.

21810 of 25509 relevant lines covered (85.5%)

204.06 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/system/Boot.php
1
<?php
2

3
declare(strict_types=1);
4

5
/**
6
 * This file is part of CodeIgniter 4 framework.
7
 *
8
 * (c) CodeIgniter Foundation <admin@codeigniter.com>
9
 *
10
 * For the full copyright and license information, please view
11
 * the LICENSE file that was distributed with this source code.
12
 */
13

14
namespace CodeIgniter;
15

16
use CodeIgniter\Cache\FactoriesCache;
17
use CodeIgniter\CLI\Console;
18
use CodeIgniter\Config\DotEnv;
19
use Config\App;
20
use Config\Autoload;
21
use Config\Modules;
22
use Config\Optimize;
23
use Config\Paths;
24
use Config\Services;
25

26
/**
27
 * Bootstrap for the application
28
 *
29
 * @codeCoverageIgnore
30
 */
31
class Boot
32
{
33
    /**
34
     * Used by `public/index.php`
35
     *
36
     * Context
37
     *   web:     Invoked by HTTP request
38
     *   php-cli: Invoked by CLI via `php public/index.php`
39
     *
40
     * @return int Exit code.
41
     */
42
    public static function bootWeb(Paths $paths): int
43
    {
44
        static::definePathConstants($paths);
×
45
        if (! defined('APP_NAMESPACE')) {
×
46
            static::loadConstants();
×
47
        }
48
        static::checkMissingExtensions();
×
49

50
        static::loadDotEnv($paths);
×
51
        static::defineEnvironment();
×
52
        static::loadEnvironmentBootstrap($paths);
×
53

54
        static::loadCommonFunctions();
×
55
        static::loadAutoloader();
×
56
        static::setExceptionHandler();
×
57
        static::initializeKint();
×
58

59
        $configCacheEnabled = class_exists(Optimize::class)
×
60
            && (new Optimize())->configCacheEnabled;
×
61
        if ($configCacheEnabled) {
×
62
            $factoriesCache = static::loadConfigCache();
×
63
        }
64

65
        static::autoloadHelpers();
×
66

67
        $app = static::initializeCodeIgniter();
×
68
        static::runCodeIgniter($app);
×
69

70
        if ($configCacheEnabled) {
×
71
            static::saveConfigCache($factoriesCache);
×
72
        }
73

74
        // Exits the application, setting the exit code for CLI-based
75
        // applications that might be watching.
76
        return EXIT_SUCCESS;
×
77
    }
78

79
    /**
80
     * Used by command line scripts other than
81
     * * `spark`
82
     * * `php-cli`
83
     * * `phpunit`
84
     *
85
     * @used-by `system/util_bootstrap.php`
86
     */
87
    public static function bootConsole(Paths $paths): void
88
    {
89
        static::definePathConstants($paths);
×
90
        static::loadConstants();
×
91
        static::checkMissingExtensions();
×
92

93
        static::loadDotEnv($paths);
×
94
        static::loadEnvironmentBootstrap($paths);
×
95

96
        static::loadCommonFunctions();
×
97
        static::loadAutoloader();
×
98
        static::setExceptionHandler();
×
99
        static::initializeKint();
×
100
        static::autoloadHelpers();
×
101

102
        // We need to force the request to be a CLIRequest since we're in console
103
        Services::createRequest(new App(), true);
×
104
        service('routes')->loadRoutes();
×
105
    }
106

107
    /**
108
     * Used by `spark`
109
     *
110
     * @return int Exit code.
111
     */
112
    public static function bootSpark(Paths $paths): int
113
    {
114
        static::definePathConstants($paths);
×
115
        if (! defined('APP_NAMESPACE')) {
×
116
            static::loadConstants();
×
117
        }
118
        static::checkMissingExtensions();
×
119

120
        static::loadDotEnv($paths);
×
121
        static::defineEnvironment();
×
122
        static::loadEnvironmentBootstrap($paths);
×
123

124
        static::loadCommonFunctions();
×
125
        static::loadAutoloader();
×
126
        static::setExceptionHandler();
×
127
        static::initializeKint();
×
128
        static::autoloadHelpers();
×
129

130
        static::initializeCodeIgniter();
×
131
        $console = static::initializeConsole();
×
132

133
        return static::runCommand($console);
×
134
    }
135

136
    /**
137
     * Used by `system/Test/bootstrap.php`
138
     */
139
    public static function bootTest(Paths $paths): void
140
    {
141
        static::loadConstants();
×
142
        static::checkMissingExtensions();
×
143

144
        static::loadDotEnv($paths);
×
145
        static::loadEnvironmentBootstrap($paths, false);
×
146

147
        static::loadCommonFunctionsMock();
×
148
        static::loadCommonFunctions();
×
149

150
        static::loadAutoloader();
×
151
        static::setExceptionHandler();
×
UNCOV
152
        static::initializeKint();
×
UNCOV
153
        static::autoloadHelpers();
×
154
    }
155

156
    /**
157
     * Used by `preload.php`
158
     */
159
    public static function preload(Paths $paths): void
160
    {
161
        static::definePathConstants($paths);
×
162
        static::loadConstants();
×
UNCOV
163
        static::defineEnvironment();
×
164
        static::loadEnvironmentBootstrap($paths, false);
×
165

UNCOV
166
        static::loadAutoloader();
×
167
    }
168

169
    /**
170
     * Load environment settings from .env files into $_SERVER and $_ENV
171
     */
172
    protected static function loadDotEnv(Paths $paths): void
173
    {
174
        require_once $paths->systemDirectory . '/Config/DotEnv.php';
×
UNCOV
175
        $envDirectory = $paths->envDirectory ?? $paths->appDirectory . '/../';
×
UNCOV
176
        (new DotEnv($envDirectory))->load();
×
177
    }
178

179
    protected static function defineEnvironment(): void
180
    {
181
        if (! defined('ENVIRONMENT')) {
×
182
            // @phpstan-ignore-next-line
183
            $env = $_ENV['CI_ENVIRONMENT'] ?? $_SERVER['CI_ENVIRONMENT']
×
UNCOV
184
                ?? getenv('CI_ENVIRONMENT')
×
185
                ?: 'production';
×
186

UNCOV
187
            define('ENVIRONMENT', $env);
×
188
        }
189
    }
190

191
    protected static function loadEnvironmentBootstrap(Paths $paths, bool $exit = true): void
192
    {
UNCOV
193
        if (is_file($paths->appDirectory . '/Config/Boot/' . ENVIRONMENT . '.php')) {
×
194
            require_once $paths->appDirectory . '/Config/Boot/' . ENVIRONMENT . '.php';
×
195

UNCOV
196
            return;
×
197
        }
198

199
        if ($exit) {
×
UNCOV
200
            header('HTTP/1.1 503 Service Unavailable.', true, 503);
×
201
            echo 'The application environment is not set correctly.';
×
202

UNCOV
203
            exit(EXIT_ERROR);
×
204
        }
205
    }
206

207
    /**
208
     * The path constants provide convenient access to the folders throughout
209
     * the application. We have to set them up here, so they are available in
210
     * the config files that are loaded.
211
     */
212
    protected static function definePathConstants(Paths $paths): void
213
    {
214
        // The path to the application directory.
UNCOV
215
        if (! defined('APPPATH')) {
×
UNCOV
216
            define('APPPATH', realpath(rtrim($paths->appDirectory, '\\/ ')) . DIRECTORY_SEPARATOR);
×
217
        }
218

219
        // The path to the project root directory. Just above APPPATH.
UNCOV
220
        if (! defined('ROOTPATH')) {
×
UNCOV
221
            define('ROOTPATH', realpath(APPPATH . '../') . DIRECTORY_SEPARATOR);
×
222
        }
223

224
        // The path to the system directory.
UNCOV
225
        if (! defined('SYSTEMPATH')) {
×
UNCOV
226
            define('SYSTEMPATH', realpath(rtrim($paths->systemDirectory, '\\/ ')) . DIRECTORY_SEPARATOR);
×
227
        }
228

229
        // The path to the writable directory.
UNCOV
230
        if (! defined('WRITEPATH')) {
×
231
            $writePath = realpath(rtrim($paths->writableDirectory, '\\/ '));
×
232

233
            if ($writePath === false) {
×
UNCOV
234
                header('HTTP/1.1 503 Service Unavailable.', true, 503);
×
UNCOV
235
                echo 'The WRITEPATH is not set correctly.';
×
236

237
                // EXIT_ERROR is not yet defined
238
                exit(1);
×
239
            }
UNCOV
240
            define('WRITEPATH', $writePath . DIRECTORY_SEPARATOR);
×
241
        }
242

243
        // The path to the tests directory
UNCOV
244
        if (! defined('TESTPATH')) {
×
UNCOV
245
            define('TESTPATH', realpath(rtrim($paths->testsDirectory, '\\/ ')) . DIRECTORY_SEPARATOR);
×
246
        }
247
    }
248

249
    protected static function loadConstants(): void
250
    {
UNCOV
251
        require_once APPPATH . 'Config/Constants.php';
×
252
    }
253

254
    protected static function loadCommonFunctions(): void
255
    {
256
        // Require app/Common.php file if exists.
UNCOV
257
        if (is_file(APPPATH . 'Common.php')) {
×
UNCOV
258
            require_once APPPATH . 'Common.php';
×
259
        }
260

261
        // Require system/Common.php
UNCOV
262
        require_once SYSTEMPATH . 'Common.php';
×
263
    }
264

265
    protected static function loadCommonFunctionsMock(): void
266
    {
UNCOV
267
        require_once SYSTEMPATH . 'Test/Mock/MockCommon.php';
×
268
    }
269

270
    /**
271
     * The autoloader allows all the pieces to work together in the framework.
272
     * We have to load it here, though, so that the config files can use the
273
     * path constants.
274
     */
275
    protected static function loadAutoloader(): void
276
    {
277
        if (! class_exists(Autoload::class, false)) {
×
278
            require_once SYSTEMPATH . 'Config/AutoloadConfig.php';
×
279
            require_once APPPATH . 'Config/Autoload.php';
×
280
            require_once SYSTEMPATH . 'Modules/Modules.php';
×
UNCOV
281
            require_once APPPATH . 'Config/Modules.php';
×
282
        }
283

UNCOV
284
        require_once SYSTEMPATH . 'Autoloader/Autoloader.php';
×
UNCOV
285
        require_once SYSTEMPATH . 'Config/BaseService.php';
×
UNCOV
286
        require_once SYSTEMPATH . 'Config/Services.php';
×
UNCOV
287
        require_once APPPATH . 'Config/Services.php';
×
288

289
        // Initialize and register the loader with the SPL autoloader stack.
UNCOV
290
        Services::autoloader()->initialize(new Autoload(), new Modules())->register();
×
291
    }
292

293
    protected static function autoloadHelpers(): void
294
    {
UNCOV
295
        service('autoloader')->loadHelpers();
×
296
    }
297

298
    protected static function setExceptionHandler(): void
299
    {
UNCOV
300
        service('exceptions')->initialize();
×
301
    }
302

303
    protected static function checkMissingExtensions(): void
304
    {
305
        if (is_file(COMPOSER_PATH)) {
×
306
            return;
×
307
        }
308

309
        // Run this check for manual installations
310
        $missingExtensions = [];
×
311

UNCOV
312
        foreach ([
×
UNCOV
313
            'intl',
×
314
            'mbstring',
×
315
        ] as $extension) {
×
UNCOV
316
            if (! extension_loaded($extension)) {
×
UNCOV
317
                $missingExtensions[] = $extension;
×
318
            }
319
        }
320

321
        if ($missingExtensions === []) {
×
UNCOV
322
            return;
×
323
        }
324

UNCOV
325
        $message = sprintf(
×
326
            'The framework needs the following extension(s) installed and loaded: %s.',
×
UNCOV
327
            implode(', ', $missingExtensions),
×
UNCOV
328
        );
×
329

UNCOV
330
        header('HTTP/1.1 503 Service Unavailable.', true, 503);
×
331
        echo $message;
×
332

UNCOV
333
        exit(EXIT_ERROR);
×
334
    }
335

336
    protected static function initializeKint(): void
337
    {
UNCOV
338
        service('autoloader')->initializeKint(CI_DEBUG);
×
339
    }
340

341
    protected static function loadConfigCache(): FactoriesCache
342
    {
UNCOV
343
        $factoriesCache = new FactoriesCache();
×
UNCOV
344
        $factoriesCache->load('config');
×
345

UNCOV
346
        return $factoriesCache;
×
347
    }
348

349
    /**
350
     * The CodeIgniter class contains the core functionality to make
351
     * the application run, and does all the dirty work to get
352
     * the pieces all working together.
353
     */
354
    protected static function initializeCodeIgniter(): CodeIgniter
355
    {
UNCOV
356
        $app = service('codeigniter');
×
UNCOV
357
        $app->initialize();
×
UNCOV
358
        $context = is_cli() ? 'php-cli' : 'web';
×
UNCOV
359
        $app->setContext($context);
×
360

UNCOV
361
        return $app;
×
362
    }
363

364
    /**
365
     * Now that everything is set up, it's time to actually fire
366
     * up the engines and make this app do its thang.
367
     */
368
    protected static function runCodeIgniter(CodeIgniter $app): void
369
    {
UNCOV
370
        $app->run();
×
371
    }
372

373
    protected static function saveConfigCache(FactoriesCache $factoriesCache): void
374
    {
UNCOV
375
        $factoriesCache->save('config');
×
376
    }
377

378
    protected static function initializeConsole(): Console
379
    {
UNCOV
380
        $console = new Console();
×
381

382
        // Show basic information before we do anything else.
383
        if (is_int($suppress = array_search('--no-header', $_SERVER['argv'], true))) {
×
UNCOV
384
            unset($_SERVER['argv'][$suppress]);
×
UNCOV
385
            $suppress = true;
×
386
        }
387

388
        $console->showHeader($suppress);
×
389

390
        return $console;
×
391
    }
392

393
    protected static function runCommand(Console $console): int
394
    {
UNCOV
395
        $exit = $console->run();
×
396

UNCOV
397
        return is_int($exit) ? $exit : EXIT_SUCCESS;
×
398
    }
399
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc