Tutorials Logic, IN info@tutorialslogic.com

PHP include and require: Reliable Paths and File Boundaries

PHP File Loading

PHP include and require evaluate another file in the caller context. Require is appropriate for essential code, include for a truly optional fragment, and the once variants prevent repeated evaluation within one request.

Reliable loading anchors paths with __DIR__, validates returned configuration, keeps code outside writable public storage, maps every dynamic choice through an allowlist, and replaces hidden load-order dependencies with explicit bootstrap and autoload boundaries.

Loading Choices

Construct Missing file Duplicate protection
include Warning; execution continues No
require Error; execution stops No
include_once Warning; execution continues Yes
require_once Error; execution stops Yes

Reliable Paths

Load a Required Bootstrap

Load a Required Bootstrap
<?php
require_once __DIR__ . '/bootstrap.php';

__DIR__ points to the directory containing the current file, regardless of where the command started.

Returned Configuration

A required file can return a value. This pattern keeps configuration data explicit and avoids creating globals as a side effect.

Read a Configuration Array

Read a Configuration Array
<?php
// config/app.php returns ['name' => 'Tutorials Logic'];
$config = require __DIR__ . '/config/app.php';
echo $config['name'];
Output
Tutorials Logic

Include Scope

An included file inherits the variable scope of the line where it is included. Loading a template inside a function exposes that function local scope. Pass named data intentionally instead of depending on unrelated ambient variables.

  • Use require for files the application cannot operate without.
  • Use once variants for class or bootstrap files that must not be redeclared.
  • Do not build include paths directly from user input.
  • Use Composer autoloading for classes instead of manual require chains.

Safe Inclusion

Use require for essential bootstrap and configuration code whose absence makes the request invalid. Use a controlled optional include only when the application can genuinely continue. Build paths from __DIR__ and fixed application directories, never directly from query parameters or form values.

Prefer autoloading for classes and explicit functions for reusable behavior. Included files inherit variables from the calling scope and can modify it, which makes template data easy to collide. Pass a clearly named data array to views and keep executable setup out of content files.

Loading Constructs

`include` and `require` are language constructs that evaluate another PHP file in the current execution. Use `require` when the application cannot continue without the file; a missing required file stops execution. Use `include` only when a missing optional fragment has a deliberate fallback.

A failed include raises warnings and returns false, while a successful included file returns one unless it explicitly returns another value. A required file failure is fatal. Do not suppress either outcome with the error-control operator; handle optionality before loading and let required boot failures remain visible.

The `_once` variants skip a file that PHP has already included during the request. They prevent duplicate declarations, but they do not create dependency injection, control ordering, or make side-effect-heavy files safe. Prefer one clear bootstrap and native autoloading for classes.

Because these are constructs, parentheses are unnecessary and can produce confusing expression precedence. Write `require $path;` as a statement, or parenthesize the entire include expression when intentionally examining its return value.

  • Require files essential to a valid process.
  • Include only genuinely optional fragments with fallback behavior.
  • Use once variants to prevent repeated evaluation, not to design dependencies.
  • Never hide loading errors with suppression.

Path Resolution

A bare filename can be searched through `include_path`, the calling script directory, and the current working directory. The working directory may differ between a web request, CLI command, test runner, and queue worker, which makes bare relative paths fragile.

Anchor project files to the file that owns the relationship: `__DIR__ . "/config/routes.php"`. `__DIR__` is resolved for the source file containing it, including inside an included file, so the path remains stable when the process starts elsewhere.

An explicitly absolute path or a path beginning with dot or dot-dot bypasses include-path searching. Build paths from trusted roots and normalize ownership at configuration boundaries. Do not assume a URL path beginning with slash means the same thing as a filesystem path.

Check deployment case exactly. A path that works on a case-insensitive development filesystem may fail on a case-sensitive host. Test packaged artifacts from a clean directory and ensure every required source file is present before switching traffic.

  • Anchor owned files with __DIR__.
  • Avoid process-dependent bare paths.
  • Keep filesystem and URL path rules separate.
  • Verify exact case and packaged file presence.

Return Configuration Data

Return Configuration Data
<?php
// config/app.php returns an array.
$config = require __DIR__ . "/config/app.php";

if (!is_array($config)) {
    throw new RuntimeException("Invalid application configuration");
}

The path is stable and the caller validates the included file contract immediately.

Included Scope

Included code inherits the variable scope at the line where inclusion occurs. A file included inside a function can read that function local state, while functions and classes declared by the file still enter their normal declaration scope.

Implicit variable sharing makes templates difficult to inspect. Pass one explicit data array or extract named values at a narrow rendering boundary, document required keys, and escape each value for its output context.

An included file may explicitly `return` a value, ending evaluation of that file and giving the value to the include expression. Returning a configuration array is clearer than populating unrelated global variables. Validate the returned type at the caller.

Output from an included file is sent like output from the caller. Capture it only through a carefully balanced output buffer when string rendering is the actual contract. Ensure exceptions clean the buffer so later responses are not corrupted.

  • Treat inherited variables as an explicit interface.
  • Prefer returned data over global mutation.
  • Validate included-file return types.
  • Balance output buffers on success and failure.

Loading Security

Never concatenate a request value directly into an include or require path. Traversal sequences, stream wrappers, absolute paths, and unexpected extensions can turn a page selector into local or remote code execution.

Map a small external identifier to a fixed application-owned path. Reject every unknown key. Checking only a suffix or removing dot-dot text is not a sufficient policy because path interpretation and encoding have many edge cases.

Keep source and configuration outside the public document root where deployment permits it, and disable remote URL inclusion. A file that must be downloaded is data: fetch it through an HTTP client, validate it, and never evaluate the response as PHP.

File permissions should allow the runtime account to read required code but not rewrite deployed source. Separate writable uploads, caches, and logs from executable directories, and prevent uploaded files from being selected by any loader.

  • Allowlist identifiers to fixed owned files.
  • Do not evaluate downloaded or uploaded content.
  • Separate writable data from executable source.
  • Deploy code read-only to the runtime where possible.

Bootstrap Design

A front controller can require one bootstrap that loads environment-safe configuration, registers error handling and autoloading, creates services, and dispatches the request. Keep the order explicit because early output or failure changes later headers and diagnostics.

Class files should declare classes rather than run application work when loaded. Native `spl_autoload_register` can map approved namespace prefixes to source roots without adding Composer to a small project. Return immediately for unknown prefixes and never search request-controlled paths.

Functions, constants, and procedural compatibility files may still need one deliberate require. Group them by real ownership and avoid a directory-wide loop that executes every PHP file merely because it exists.

Do not use include order as a hidden service container. Pass constructed dependencies to objects and functions. This makes tests independent of which unrelated file happened to run first.

  • Keep one ordered application bootstrap.
  • Autoload classes through approved namespace prefixes.
  • Require procedural definitions deliberately.
  • Pass runtime dependencies instead of relying on load order.

Failure Diagnosis

A missing-file message includes the requested path and attempted search context. Log the stable application path, current working directory when relevant, deployment release identifier, and previous warning without exposing full server paths to users.

A duplicate class or function declaration usually means a file ran twice, two files own the same symbol, or a loader map is inconsistent. `_once` can mask one symptom, but ownership and autoload mappings still need correction.

Headers-already-sent errors often come from whitespace, a byte-order mark, or HTML output in an included file. Pure PHP source files should omit the closing PHP tag so accidental trailing output cannot escape.

When an included configuration returns one instead of expected data, it probably omitted an explicit return. Validate immediately and report the specific contract instead of letting an integer travel into unrelated code.

  • Log loading context without exposing paths in responses.
  • Repair duplicate symbol ownership at the source.
  • Keep pure source files free from accidental output.
  • Validate configuration results at the include boundary.

Loading Tests

Run entry points from different working directories to prove paths are anchored. Test web, CLI, worker, and scheduled command bootstraps when the application supports them, including a clean production-like release directory.

Test missing optional files, missing required files in a subprocess, invalid return values, duplicate loading, and unknown dynamic identifiers. Required-failure tests belong in isolated processes because fatal termination should not end the whole suite.

Audit every include expression for user-controlled path fragments and enabled URL wrappers. Static analysis can locate dynamic includes, but a reviewer must verify that each variable originates from an application-owned mapping.

Measure boot time only after correctness. Opcode caching and autoload maps usually matter more than replacing readable requires. Remove obsolete bootstrap files when no entry point references them so dead startup behavior does not survive unnoticed.

  • Exercise bootstraps from multiple working directories.
  • Isolate fatal loading tests in subprocesses.
  • Trace every dynamic path to a trusted mapping.
  • Remove unreferenced bootstrap and compatibility files.
Before you move on

Mastery Check

5 checks
  • Choose fatal or optional loading deliberately.
  • Anchor owned paths independently of the working directory.
  • Validate scope, output, and returned-value contracts.
  • Never build executable paths from request values.
  • Test clean web, CLI, worker, and release bootstraps.

Try this next

Organize a Small Project

0 of 2 completed

  1. Create config/app.php that returns an array and load it with require.
  2. Run a script from another working directory, observe the failure, then fix the path with __DIR__.
Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.