require, require_once, include, include_once in PHP

Содержание
Introduction
The four constructs
What happens when the file is missing
_once dedupes by resolved path
Included code sees your scope
Relative paths resolve against CWD, not the file
Remote includes are off for a reason
Opcache can serve yesterday's file
Checklist: include safely
How this evolved across PHP versions
Examples on this site

Introduction

Four statements, two axes: require vs include is about severity when the file is missing; the _once suffix is about loading the same file twice. The differences look trivial until a rename on a Friday evening takes down the whole site — which is exactly what happened to us (see the last section).

The four constructs

require — file is mandatory. Missing file: warning plus a thrown Error (fatal if uncaught). Use for code the page cannot live without.

include — file is optional. Missing file: warning, expression evaluates to false, execution continues. Use for optional blocks (banners, widgets).

require_once / include_once — same as above, but a file already loaded during this request is skipped. Use everywhere a file may be reached through several paths (shared headers, class files).

What happens when the file is missing

Tested on PHP 8.1:

$ php -r '$r = @include "/nonexistent/x.php"; var_dump($r);'

bool(false) — and the script keeps running

$ php -r 'try { require "/nonexistent/x.php"; } catch (Throwable $e)
{ echo get_class($e); }'

Warning, then caught: Error — catch it and the script also survives

So on modern PHP a failed require is catchable — but only if you wrap it. An unwrapped require_once of a renamed module (our case) still kills the request exactly like the old fatal did.

Изображение баннера

_once dedupes by resolved path

require_once tracks files by their resolved real path, not by the spelling you used. Tested: three spellings of one file — ../f.php, an absolute path with /./ inside, and a path with /sub/../ — executed the file exactly once. Consequences: symlinked copies of one file load once too (usually what you want), while the same code reached through two genuinely different files still loads twice. Never rely on _once to deduplicate by content — only by path.

Included code sees your scope

An included file runs in the scope of the line that includes it: a require inside a function sees that function locals, and any variables the file sets leak back out. Convention that saves nerves: included files either declare functions/classes only, or document the exact variables they read and write (our footer fragments, for example, contract on $metrika).

Relative paths resolve against CWD, not the file

require "lib/util.php" looks in include_path and the current working directory — not the directory of the file containing the statement. A page that works in the browser (CWD = docroot) can break under cron or CLI with a different CWD. Robust forms, in order of preference: __DIR__ . '/lib/util.php' (anchored to the including file), or an absolute path built from a known root such as $_SERVER['DOCUMENT_ROOT'].

Remote includes are off for a reason

require "https://…/lib.php" executes third-party code inside your process with your permissions — a hijacked or lagging URL becomes code execution or a hung request. PHP ships allow_url_include=Off since 5.2 exactly because of that history. Leave it off; fetch remote data with HTTP clients and treat it as data, never as code.

Opcache can serve yesterday file

With opcache enabled and timestamp validation off (common production tuning), PHP keeps executing the cached bytecode after you replace the file: renames look half-applied, deleted files keep running. After every deploy that adds, renames, or deletes PHP files, invalidate explicitly (opcache_reset() or a web-server reload), otherwise you debug ghosts.

Checklist: include safely

1. Absolute paths from __DIR__ or a known root — never bare relative paths.
2. _once for anything reachable twice; plain require only when exactly-once is guaranteed by construction.
3. Optional modules: is_file() guard + baked-in default, so a missing file degrades instead of fataling.
4. Keep allow_url_include=Off.
5. Reset opcache (or confirm timestamp validation) on deploy.

How this evolved across PHP versions

PHP 4/5: a failed require ended in an uncatchable fatal (E_COMPILE_ERROR) — the whole request died, no recovery possible.

PHP 5.2: allow_url_include default switched to Off after years of remote-include exploits.

PHP 5.3: __DIR__ arrived, giving every file a reliable anchor for absolute includes (previously only verbose dirname(__FILE__)).

PHP 7.0: engine errors became catchable Error throwables — a failed require can now be caught with try/catch (verified above on 8.1), while include keeps its warn-and-continue contract. Uncaught, both still stop the page — which is why the guard pattern matters on every version.

PHP 7.4+ / 8.x: include semantics unchanged; opcache preloading and stricter engine typing raised the stakes of stale or misspelled paths rather than changing the statements themselves.

Examples on this site

require on a missing file fatals the page — the rename incident, guard pattern, fallback chain.

Call function from another file — everyday require_once with absolute paths.

PHP errors: case studies — more failure modes and fixes.

Article author: Arthur Isaev

Похожие статьи
Development with PHP
require, require_once, include, include_once
require_once on a missing file fatals the page

Поиск по сайту

Подпишитесь на Telegram канал @aofeed чтобы следить за выходом новых статей и обновлением старых

Перейти на канал

@aofeed

Задать вопрос в Телеграм-группе

@aofeedchat

Контакты и сотрудничество:
Рекомендую наш хостинг beget.ru
Пишите на info@urn.su если Вы:
1. Хотите написать статью для нашего сайта или перевести статью на свой родной язык.
2. Хотите разместить на сайте рекламу, подходящую по тематике.
3. Реклама на моём сайте имеет максимальный уровень цензуры. Если Вы увидели рекламный блок недопустимый для просмотра детьми школьного возраста, вызывающий шок или вводящий в заблуждение - пожалуйста свяжитесь с нами по электронной почте
4. Нашли на сайте ошибку, неточности, баг и т.д. ... .......
5. Статьи можно расшарить в соцсетях, нажав на иконку сети: