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

codeigniter4 / CodeIgniter4 / 16544964448

26 Jul 2025 11:32PM UTC coverage: 84.185% (-0.003%) from 84.188%
16544964448

Pull #9631

github

web-flow
Merge a601c2c31 into d1ee6966b
Pull Request #9631: feat: env directory path

4 of 6 new or added lines in 3 files covered. (66.67%)

20882 of 24805 relevant lines covered (84.18%)

193.05 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::loadCommonFunctions();
×
148
        static::loadAutoloader();
×
149
        static::setExceptionHandler();
×
150
        static::initializeKint();
×
151
        static::autoloadHelpers();
×
152
    }
153

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

164
        static::loadAutoloader();
×
165
    }
166

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

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

185
            define('ENVIRONMENT', $env);
×
186
        }
187
    }
188

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

194
            return;
×
195
        }
196

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

201
            exit(EXIT_ERROR);
×
202
        }
203
    }
204

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

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

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

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

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

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

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

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

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

259
        // Require system/Common.php
260
        require_once SYSTEMPATH . 'Common.php';
×
261
    }
262

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

277
        require_once SYSTEMPATH . 'Autoloader/Autoloader.php';
×
278
        require_once SYSTEMPATH . 'Config/BaseService.php';
×
279
        require_once SYSTEMPATH . 'Config/Services.php';
×
280
        require_once APPPATH . 'Config/Services.php';
×
281

282
        // Initialize and register the loader with the SPL autoloader stack.
283
        Services::autoloader()->initialize(new Autoload(), new Modules())->register();
×
284
    }
285

286
    protected static function autoloadHelpers(): void
287
    {
288
        service('autoloader')->loadHelpers();
×
289
    }
290

291
    protected static function setExceptionHandler(): void
292
    {
293
        service('exceptions')->initialize();
×
294
    }
295

296
    protected static function checkMissingExtensions(): void
297
    {
298
        if (is_file(COMPOSER_PATH)) {
×
299
            return;
×
300
        }
301

302
        // Run this check for manual installations
303
        $missingExtensions = [];
×
304

305
        foreach ([
×
306
            'intl',
×
307
            'json',
×
308
            'mbstring',
×
309
        ] as $extension) {
×
310
            if (! extension_loaded($extension)) {
×
311
                $missingExtensions[] = $extension;
×
312
            }
313
        }
314

315
        if ($missingExtensions === []) {
×
316
            return;
×
317
        }
318

319
        $message = sprintf(
×
320
            'The framework needs the following extension(s) installed and loaded: %s.',
×
321
            implode(', ', $missingExtensions),
×
322
        );
×
323

324
        header('HTTP/1.1 503 Service Unavailable.', true, 503);
×
325
        echo $message;
×
326

327
        exit(EXIT_ERROR);
×
328
    }
329

330
    protected static function initializeKint(): void
331
    {
332
        service('autoloader')->initializeKint(CI_DEBUG);
×
333
    }
334

335
    protected static function loadConfigCache(): FactoriesCache
336
    {
337
        $factoriesCache = new FactoriesCache();
×
338
        $factoriesCache->load('config');
×
339

340
        return $factoriesCache;
×
341
    }
342

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

355
        return $app;
×
356
    }
357

358
    /**
359
     * Now that everything is set up, it's time to actually fire
360
     * up the engines and make this app do its thang.
361
     */
362
    protected static function runCodeIgniter(CodeIgniter $app): void
363
    {
364
        $app->run();
×
365
    }
366

367
    protected static function saveConfigCache(FactoriesCache $factoriesCache): void
368
    {
369
        $factoriesCache->save('config');
×
370
    }
371

372
    protected static function initializeConsole(): Console
373
    {
374
        $console = new Console();
×
375

376
        // Show basic information before we do anything else.
377
        if (is_int($suppress = array_search('--no-header', $_SERVER['argv'], true))) {
×
378
            unset($_SERVER['argv'][$suppress]);
×
379
            $suppress = true;
×
380
        }
381

382
        $console->showHeader($suppress);
×
383

384
        return $console;
×
385
    }
386

387
    protected static function runCommand(Console $console): int
388
    {
389
        $exit = $console->run();
×
390

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

© 2026 Coveralls, Inc