skip to content

In PHP 8.5, what happens when include versus require cannot open the file, and which should load a bootstrap file?

level: juniorimportance: must knowfreq 78%

answer

  1. one warns, one stops
  2. include returns false and continues
  3. Failed opening required ... is an Error
  4. E_COMPILE_ERROR only before PHP 8.0
  5. parse errors throw ParseError either way

basics

~20 s

When the file cannot be opened, include emits warnings, returns false and the script continues; require emits a warning and then throws an Error, which stops the script unless caught. Anything the program cannot run without should use require.

solid answer

~40 s

Both constructs load and execute another PHP file; they differ only when the file **cannot be opened**. `include` raises an `E_WARNING` ("Failed to open stream"), a second `E_WARNING` ("Failed opening '...' for inclusion"), evaluates to `false` and lets execution continue. `require` raises the same first warning and then, in PHP 8.5, throws an `Error` with the message `Failed opening required '...'`; uncaught, that ends the script as a fatal error. Before PHP 8.0 it was an `E_COMPILE_ERROR` that could not be caught. So bootstrap files, configuration and function libraries use `require` (or `require_once`), and `include` is for genuinely optional pieces such as an optional template partial. Neither softens a broken file: a syntax error in the included code throws `ParseError` in both cases.

code

php · 13 lines
php
<?php
declare(strict_types=1);

$banner = include __DIR__ . '/partials/banner.php'; // missing: 2 warnings
var_dump($banner);                                   // bool(false)

try {
    require __DIR__ . '/config/app.php';             // missing
} catch (\Exception $e) {
    echo 'never reached: Error is not an Exception';
} catch (\Error $e) {
    echo $e->getMessage(), PHP_EOL; // Failed opening required '.../config/app.php' ...
}

go deeper

for a junior

Recall the one-line difference: a missing file makes include warn and continue, and makes require stop the script.

for a middle

Describe the exact failure in PHP 8: two warnings and false for include, a warning plus a thrown Error for require, and that parse errors throw ParseError in both.

for a senior

Use require for everything the application cannot run without, so failures surface at the load point, and catch Error or Throwable only where a loader can really degrade gracefully.

for a principal

Treat remaining include and require calls as a small, audited set of entry points, with class loading left to the autoloader and paths anchored to DIR.

## Two constructs, one difference `include` and `require` are **language constructs**, not functions, so parentheses around the path are optional: `require 'config.php';` and `require('config.php');` are the same. Both read the target file, compile it and run it at that point of the program. The manual states it directly: `require` is identical to `include` except for what happens **on failure** to open the file. | Situation | `include` | `require` | |---|---|---| | File opened and compiled | runs it, evaluates to its return value (or `1`) | same | | File cannot be opened | two `E_WARNING`s, evaluates to `false`, script continues | one `E_WARNING`, then throws `Error` | | Syntax error inside the file | throws `ParseError` | throws `ParseError` | | Exception thrown by the file's code | propagates | propagates | ## What the failure looks like in PHP 8.5 For a missing file, `include 'partials/banner.php';` produces: 1. `Warning: include(partials/banner.php): Failed to open stream: No such file or directory` 2. `Warning: include(): Failed opening 'partials/banner.php' for inclusion (include_path='...')`, with the current `include_path` inside the parentheses and then the next statement runs. The expression's value is `false`. For `require 'config.php';` the first warning is the same, and then PHP throws: `Error: Failed opening required 'config.php' (include_path='...')` The `include_path` in the message is whatever the current setting is; it helps when diagnosing path problems. ## The PHP 8.0 change Before PHP 8.0, a failed `require` raised an `E_COMPILE_ERROR`: a hard fatal error with no way to intercept it. Since PHP 8.0 it throws an `Error` object instead. Two consequences: - It **can be caught** with `catch (\Error $e)` or `catch (\Throwable $e)`, which a front controller or a plugin loader might do to show a friendly page or skip a broken plugin. - It **cannot** be caught with `catch (\Exception $e)`, because `Error` does not extend `Exception`. Code that wraps `require` in `catch (Exception $e)` still dies with "Uncaught Error". Note that the manual's `include` page still speaks of an `E_ERROR` for `require`; the `require` page and php-src 8.5 agree that it is an `Error` exception. ## Choosing between them - **`require`** for anything the program cannot run without: the bootstrap, the Composer autoloader file, configuration, a file of helper functions. Failing loudly at the load point is easier to diagnose than an undefined-function error many lines later. - **`include`** for optional content where a missing file is an acceptable outcome, for example an optional local override or a template fragment. Check the return value if the difference matters. - **`require_once` / `include_once`** when the same file might be reached twice and running it twice would redeclare functions or classes. In modern codebases most class files are loaded by an autoloader, so explicit `require` calls shrink to a handful: the autoloader itself, configuration and entry-point bootstrapping. ## A worked decision Consider a front controller with three loads: 1. `require __DIR__ . '/../vendor/autoload.php';` must exist, or nothing else can work, so `require` is right and a failure should stop the request. 2. `$config = require __DIR__ . '/../config/app.php';` is equally essential, and uses the file's return value. 3. `include __DIR__ . '/../config/local.php';` is an optional developer override that is absent in production; `include` plus a check of its result expresses that. Writing the optional file with `require` would break production; writing the essential ones with `include` would let the request continue into confusing secondary errors. ## Related constructs and settings - `include_once` and `require_once` behave like `include` and `require` on failure, and additionally skip a file already loaded in the current request. - The ini settings `auto_prepend_file` and `auto_append_file` include a file before or after every script, with `require` semantics, which some legacy hosts use for bootstrapping. - `get_included_files()` lists every file loaded so far, which helps confirm what a failing page actually pulled in. - Include paths also accept stream wrappers, but including remote URLs is disabled by the system-level `allow_url_include` setting, which defaults to off. ## What neither construct protects against `include` is sometimes described as "the safe one", which is wrong in three ways: - A **syntax error** in the included file throws `ParseError` from both constructs. - An **exception or `Error`** raised while the included code runs propagates normally from both. - `include` returning `false` is easy to ignore, so a missing file can turn into confusing undefined-variable warnings later. Paths deserve the same care with both constructs: a relative path is resolved against the include path and the current working directory, so production code builds paths from `__DIR__`.

  • In PHP 8.5, why does wrapping require in try/catch (Exception $e) not stop the fatal error?
    A failed `require` throws `Error`, and `Error` implements `Throwable` without extending `Exception`. A `catch (Exception $e)` block therefore never matches, and the script ends with "Uncaught Error: Failed opening required". Catch `\Error` or `\Throwable` if interception is really wanted.
  • In PHP, does include make a syntax error in the included file non-fatal?
    No. The warning-versus-Error difference applies only to opening the file. Once it is opened, both constructs compile it the same way, and a syntax error throws `ParseError`, which is fatal if uncaught. Exceptions thrown by the included code also propagate normally.
  • In PHP, is require('file.php') a function call?
    No. `include`, `require` and their `_once` forms are language constructs, so the parentheses are just a grouped expression around the path. That matters when combining them with operators: `include('a.php') == true` is parsed as `include (('a.php') == true)`, so write `(include 'a.php') == true`.

saying these in an interview costs you the question

  • A failed require in PHP 8 is an uncatchable E_COMPILE_ERROR
  • include turns every problem in the included file into a warning
  • catch (Exception $e) around require catches a missing file
  • include and require are functions, so the parentheses are mandatory
  • include is the safer choice for configuration because the site keeps running