In PHP 8.5, what happens when include versus require cannot open the file, and which should load a bootstrap file?
answer
- one warns, one stops
- include returns false and continues
- Failed opening required ... is an Error
- E_COMPILE_ERROR only before PHP 8.0
- parse errors throw ParseError either way
basics
~20 sWhen 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 sBoth 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
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
Recall the one-line difference: a missing file makes include warn and continue, and makes require stop the script.
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.
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.
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