PHP include() with Variables Not Working in XAMPP? Here's the Fix

I just installed the latest version of XAMPP on my computer, which comes with PHP 5.1.1, and I’ve been having issues with the include() function. This code worked fine on Xisto hosting, so I think it’s related to the PHP version (Xisto uses 4.3.x).

The problem is using variables inside the include() function. A normal include like this works:

include "http://example.com/file.php";

But as soon as I use a variable, it fails. I’ve tried several syntax variations:

include("$id.php");
include "$id.php";
include("$id" . ".php");
include ("$id" . ".php");

None work. The error I get is:

Warning: include(.php) [function.include]: failed to open stream: No such file or directory in C:\Apache\xampp\htdocs\lasttry\index.php on line 117
Warning: include() [function.include]: Failed opening ‘.php’ for inclusion (include_path='.;C:\Apache\xampp\php\pear') in C:\Apache\xampp\htdocs\lasttry\index.php on line 117

It seems PHP is ignoring the variable part and trying to include just .php. I set the variable in the URL like this: index.php?id=home.

Can anyone help?

Topic Summary: PHP include() with variables fails in XAMPP due to register_globals being off. Fix by using $_GET explicitly, validating input with whitelists, and adopting modern practices like autoloading and routers for security and maintainability.

:books: Official Documentation & Reference Links:

The issue is that register_globals is turned off in PHP 5.1.1 by default. In older PHP versions (like 4.3.x), register_globals was on by default, which meant that $_GET['id'] would automatically become $id. In newer versions, you need to explicitly access the superglobal $_GET.

Here’s a secure and robust way to handle includes from a query string:

<?php
$allowed_pages = array('home', 'about', 'contact');
$page = isset($_GET['id']) ? $_GET['id'] : 'home';

if (in_array($page, $allowed_pages)) {
    $file = $page . '.php';
    if (file_exists($file)) {
        include $file;
    } else {
        include 'home.php';
    }
} else {
    include 'home.php';
}
?>

This approach:

  • Uses $_GET explicitly (no reliance on register_globals)
  • Validates input against a whitelist (security best practice)
  • Checks if the file exists before including
  • Falls back to a default page

Why your code failed:

  • $id was undefined because register_globals is off
  • So include "$id.php" became include ".php" (empty string + “.php”)

Modern 2026 Trends & Best Practices:

  • Avoid register_globals entirely – it’s been removed from PHP as of 5.4.0. Always use superglobals ($_GET, $_POST, etc.).
  • Use autoloading (e.g., Composer’s PSR-4) instead of manual includes for classes.
  • Consider a router (like FastRoute or Symfony Router) for cleaner URL handling.
  • Validate and sanitize all user input to prevent LFI (Local File Inclusion) vulnerabilities.
  • Use require_once for critical files to avoid duplicate includes.
  • Enable error reporting during development: error_reporting(E_ALL); ini_set('display_errors', 1);

You can enable register_globals in XAMPP to make your old code work, but I strongly advise against it for security reasons. If you still want to do it for testing, edit the php.ini file (usually in C:\xampp\php\php.ini) and change:

register_globals = Off

to:

register_globals = On

Then restart Apache via the XAMPP Control Panel.

However, as jlhaslip said, it’s better to update your code to use $_GET explicitly. That way your scripts will work on any server without relying on deprecated settings.

Note: register_globals has been removed from PHP as of version 5.4.0, so even if you enable it now, it won’t work on newer PHP versions. It’s best to fix the code now.

Modern 2026 Trends & Best Practices:

  • Use PHP 8.x – XAMPP now comes with PHP 8.2 or higher. register_globals is long gone.
  • Adopt modern frameworks like Laravel or Symfony for robust routing and request handling.
  • Use environment variables for configuration instead of relying on register_globals.
  • Implement proper error handling with try-catch blocks and custom error handlers.
  • Test locally with the same PHP version as your production server to avoid surprises.

The Core Issue: register_globals Deprecation

The root cause here is the transition from PHP 4.x’s register_globals behavior to PHP 5.x+ where it’s disabled and eventually removed. In modern PHP (7.4, 8.x, and beyond), relying on register_globals is not just deprecated—it’s impossible. The fix is straightforward: always use superglobals like $_GET, $_POST, or $_SERVER to access user input.

Modern 2026 Best Practices for Dynamic Includes

Beyond the immediate fix, there are several contemporary approaches that make dynamic includes safer and more maintainable:

  • Whitelist Validation: As shown in jlhaslip’s example, always validate the variable against a predefined list of allowed values. This prevents Local File Inclusion (LFI) attacks, which are still a common vulnerability in PHP applications.
  • Use a Front Controller: Instead of directly including files based on user input, route all requests through a single entry point (e.g., index.php) and use a router to map URLs to controllers. Frameworks like Laravel, Symfony, or Slim handle this elegantly.
  • Autoloading with Composer: For class-based includes, use Composer’s PSR-4 autoloading. This eliminates manual include/require statements entirely and improves performance through opcode caching.
  • Template Engines: For view files, consider using Twig or Blade. They provide sandboxed environments and prevent direct file inclusion vulnerabilities.

Security Considerations in 2026

Even with the whitelist approach, there are additional layers to consider:

  • Disable allow_url_include: In php.ini, ensure allow_url_include is Off to prevent remote file inclusion (RFI) attacks.
  • Use realpath(): If you must include files dynamically, resolve the path with realpath() and verify it’s within an allowed directory.
  • Implement Content Security Policy (CSP): On the server side, CSP headers can mitigate the impact of XSS attacks that might exploit include vulnerabilities.

The Evolution of PHP Development

This thread highlights a fundamental shift in PHP development: from a procedural, register_globals-driven style to a structured, security-first approach. Modern PHP development emphasizes:

  • Explicit over implicit: Always declare dependencies (e.g., via dependency injection) rather than relying on global state.
  • Separation of concerns: Use MVC or similar patterns to keep logic, presentation, and routing separate.
  • Automated testing: Write unit tests for include logic to catch path issues early.

Final Thoughts

The fix for this specific problem is simple—use $_GET['id']—but the broader lesson is about adopting modern PHP practices. By moving away from register_globals and embracing explicit input handling, whitelists, and autoloading, you not only solve this issue but also build more robust, secure, and maintainable applications. The days of “just enabling register_globals” are long gone; embrace the change.