Be careful when using symbolic links, because require will search the real path of the file and not the path relative to the symbolic link.
Imagine your script A.php resides on directory /a and you create a symbolic link for it on directory /b/c.
So for the code
<?php
echo realpath("../");
?>
you might expect the directory /b, but actually you get the root directory /.
If you need to include the file /b/B.php inside your A.php, you can't use the following
<?php
require "../B.php";
?>
because it will search the root directory, not the /b directory.
Regards.
require()
Het require() statement vervangt zichzelf met de gespecificeerde file, bijna gelijk als de C preprocessor's #include werkt.
Als "URL fopen wrappers" zijn enabled in PHP (dit zijn ze in de default distributie) dan kun je met require() ook een URL gebruiken in plaats van een lokaal bestand. Zie Remote files en fopen() voor meer informatie.
Het is belangrijk om te weten dat wanneer er een bestand wordt geinclude()ed of gerequire()ed, de parser uit PHP komt en naar HTML mode gaat voordat het bestand wordt toegevoegd, en weer start met de PHP mode aan het einde van het bestand. Om deze reden moet alle code in het bestand dat als PHP code moet worden geïnterpreteerd moet worden omvat met geldige PHP start en end tags.
require() is eigenlijk geen functie in PHP; maar het is een taal constructie. Er gelden andere dingen voor constructies dan voor functies. Bijvoorbeeld is het niet mogelijk om require() een return waarde mee te geven. Als je toch probeert een return waarde te lezen uit een require() aanroep, krijg je een parse error.
In tegenstelling tot include() leest require() altijd het bestand in, zelfs als de regel waarop de require call staat nooit wordt uitgevoerd.. Als je een bestand conditioneel wilt laden, gebruik dan de include() functie. Een conditioneel statement heeft geen invloed op een require(). Als een regel waarop de require() staat niet wordt uitgevoerd, dan zal de code in de required file ook niet worden uitgevoerd.
Gelijksoortig hebben loop structuren geen effect op het gedrag van require(). Hoewel de code in de required file nog steeds in de loop staat, wordt het require() statement zelf maar ëën keer uitgevoerd.
Al dit betekent dat je niet kunt verwachten dat require() binnen een loop structuur per iteratie een ander bestand kan invoegen. Om zoiets te doen, kun je het include() statement gebruiken.
require ('header.inc');
Als een bestand is gerequire()ed, dan zal de code de inhoud van de variabele scope overnemen zoals deze was op het punt van de require(). Alle variabelen die beschikbaar waren in de aanroepende file, zullen ook beschikbaar zijn de in aangeroepen file. Als de require() optreed in een functie in de aanroepende file, dan zal de code die zich in het bestand dat ge-required wordt zich gedragen alsof deze in de functie waarin require() wordt aangeroepen.
Als de require()ed file wordt opgeroepen over HTTP met gebruikmakend van de fopen wrappers, en als de target server dit bestand kan interpreteren als PHP code, dan mogen er variabelen worden meegegeven aan de require()ed file met gebruik maken als een HTTP GET regel (zie voorbeeld). Dit is niet precies hetzelfde als require()ing een bestand en het laten overnemen van de variabele scope van de aanroepende file. In dit geval wordt het script uitgevoerd op de remote server en het resultaat van het script zla opgenomen worden in het lokale script.
/* Dit voorbeeld gaat er van uit dat someserver is geconfigureerd om
* .php bestanden uit te voeren, maar .txt file niet. Ook betekent
* 'werkt' hier dat de variabelen $vareen en $vartwee beschikbaar
* zijn binnen de require()ed file. */
/* Werkt niet; file.txt werd niet geparsed door someserver. */
require ("http://someserver/file.txt?varone=1&vartwo=2");
/* Werkt niet; er wordt gekeken naar het bestand 'file.php?varone=1&vartwo=2'
* op het huidige bestandssysteem. */
require ("file.php?varone=1&vartwo=2");
/* Werkt. */
require ("http://someserver/file.php?varone=1&vartwo=2");
$varone = 1;
$vartwo = 2;
require ("file.txt"); /* Werkt. */
require ("file.php"); /* Werkt. */
In PHP 3 is het mogelijk een return waarde terug te geven vanuit een require()ed bestand, zo lang dat statement optreed binnen de globale scope van het require()ed bestand. Het mag niet optreden binnen een blok (d.w.z. binnen accolades ({}). In PHP 4, is deze mogelijkheid echter niet meer aanwezig. Als je dit toch wilt, zie dan de include() functie.
Zie ook include(), require_once(), include_once(), readfile(), en virtual().
require
16-Dec-2008 02:23
23-Nov-2008 09:37
In response to some dot user at notarealdomain dot com:
This is because require executes the code "as if" it was code written inside of the function, inheriting everything including the scope. But here there is something even more interesting:
<requiredfile.php>:
<?php
$this->a.=" is visible also under a require\n";
$b="While the variable b is a local variable of the function\n";
function FunctionUnderRequire() {
echo "But the functions declared inside of a require called from a class function, just as when defined from inside any other function, are always global\n";
}
?>
<mainfile.php>:
<?php
error_reporting(E_ALL|E_STRICT);
class UserClass {
protected $a;
public function UserFunction() {
$this->a='The class variable a';
require 'requiredfile.php';
echo $this->a; // "The class variable a is visible also under a require\n"
echo $this->b; // Notice: Undefined property: UserClass::$b
echo $b; // "While the variable b is a local variable of the function\n"
$this->FunctionUnderRequire(); //Fatal error!
FunctionUnderRequire(); // "But the functions..."
}
}
$UserClass=new UserClass;
$UserClass->UserFunction();
?>
I'm wondering if there is a method for declaring class public/private/protected functions from inside a require/include...
14-May-2008 06:15
Two functions to help:
<?php
function add_include_path ($path)
{
foreach (func_get_args() AS $path)
{
if (!file_exists($path) OR (file_exists($path) && filetype($path) !== 'dir'))
{
trigger_error("Include path '{$path}' not exists", E_USER_WARNING);
continue;
}
$paths = explode(PATH_SEPARATOR, get_include_path());
if (array_search($path, $paths) === false)
array_push($paths, $path);
set_include_path(implode(PATH_SEPARATOR, $paths));
}
}
function remove_include_path ($path)
{
foreach (func_get_args() AS $path)
{
$paths = explode(PATH_SEPARATOR, get_include_path());
if (($k = array_search($path, $paths)) !== false)
unset($paths[$k]);
else
continue;
if (!count($paths))
{
trigger_error("Include path '{$path}' can not be removed because it is the only", E_USER_NOTICE);
continue;
}
set_include_path(implode(PATH_SEPARATOR, $paths));
}
}
?>
16-Oct-2007 04:21
re the comment by moazzamk at gmail dot com
As the manual states require and require_once as of PHP 4.02 no longer call the file if the line of code it is on should not be executed.
20-Sep-2007 08:27
If you want to verify that a file can be included or required, the simplest solution I've found is just to check that the file exists.
<?php
if(file_exists($pageContentInc)){
require_once $pageContentInc;
}else{
$pageContentInc = "common/content_404.inc";
require_once $pageContentInc;
}
?>
Does it really need to be any harder than that?
07-Sep-2007 02:24
I love php. But when file can't be included, 'require' or 'require_once' throw fatal error and halt the script, which is almost never desirable on a mission-critical production server. I think it may be better to use something like the following.
<?php
if (@include 'plan_A.php') {
// Plan A;
} elseif (@include 'plan_B.php') {
// Plan B;
} else {
// Hope never happens. If does, then Email the webmaster;
// Call 911, Medic, Fire, Police, the president;
// Change hard drive, server, hosting service;
}
?>
Or handle trouble first is you wish
<?php
if (!@include 'plan_A.php') {
// Someone has kidnapped/corrupted Plan_A.php;
// Email the webmaster;
// Change hard drive, server, hosting service;
} else {
// Plan A;
}
?>
17-Jul-2007 03:51
require and include read the included files even if they are not executed in the code. You can use eval() to avoid this.
eval('require filename;');
I don't know if it's faster to have the files included the regular way or the eval way though (in other words, I haven't tested their efficiency). It will be great if someone can test which is better.
11-Jul-2007 02:58
Discovered a bit of weird behavior yesterday involving require() (using PHP 5.2.3). If you use require() inside a function, the "globals" in the file will be local to the function. An example of this:
test.php:
<?php
function TestFunc()
{
require('test2.php');
echo "<pre>" . print_r($GLOBALS, true) . "</pre>";
}
?>
test2.php:
<?php
$MyTestGlobal = Array();
?>
This happens because require is a statement that _inlines_ the target code - not a function that gets called.
To fix this, use the $GLOBALS superglobal:
test2.php:
<?php
$GLOBALS["MyTestGlobal"] = Array();
?>
20-Jun-2007 12:06
Remember, when using require that it is a statement, not a function. It's not necessary to write:
<?php
require('somefile.php');
?>
The following:
<?php
require 'somefile.php';
?>
Is preferred, it will prevent your peers from giving you a hard time and a trivial conversation about what require really is.
A note that drove me nuts for 2 days!
Be carfull if you have a newline or blank space befor your php tags in the included/required file it will read as html and outputed.
If your running your output through javascript string evaluations which would be sensitive to newlines/white spaces be carfull that the first chars in the file are the php tages eg <?php
17-Oct-2006 08:06
// Looks like I might have a fix for some on the
// relative path issue.
if (!function_exists('bugFixRequirePath'))
{
function bugFixRequirePath($newPath)
{
$stringPath = dirname(__FILE__);
if (strstr($stringPath,":")) $stringExplode = "\\";
else $stringExplode = "/";
$paths = explode($stringExplode,$stringPath);
$newPaths = explode("/",$newPath);
if (count($newPaths) > 0)
{
for($i=0;$i<count($newPaths);$i++)
{
if ($newPaths[$i] == "..") array_pop($paths);
}
for($i=0;$i<count($newPaths);$i++)
{
if ($newPaths[$i] == "..") unset($newPaths[$i]);
}
reset($newPaths);
$stringNewPath = implode($stringExplode,$paths).
$stringExplode.implode($stringExplode,$newPaths);
return $stringNewPath;
}
}
}
require_once(bugFixRequirePath("../config.php"));
14-Jul-2006 12:42
If you are experiencing a bug related to using relative paths with include or require, it may be related to a grandparent directory that is executable but not readable. It will cause __FILE__ to return a relative path instead of the full path which it is supposed to show. This manifests itself in interesting ways that can be seemingly unrelated. For instance, I discovered it using the Smarty {debug} command which failed to find its template due to this issue. Please see the following for more details:
http://bugs.php.net/bug.php?id=34552
http://shiftmanager.net/~kurt/test/
31-May-2006 03:35
I have found a problem when I try to access a php file via require($class_directory)
// # $class_directory contain a long full path and dot into the last folder.
// # $class_directory = "/var/.../app/system/plugintoto_1.0/class_plugintoto_1.0.php";
// dot ('.') and minus ('-') are not accepted in require !
11-May-2006 01:41
When using symbolic links with PHP, specify a dotslash './page.php' path to ensure that PHP is looking in the right directory with nested requires:
E.g. when the required actual page1.php contains other require statements to, say page2.php, PHP will search the path that the symbolic link points to, instead of the path where the symbolic link lives. To let PHP find the other page2.php in the path of the symbolic link, a require('./page2.php'); statement will solve the puzzle.
25-Feb-2006 05:34
I have learnt to manipulate this code into an effecitve and easy to use form. I use it with require_once, but it could be used for require.
require_once($_SERVER['DOCUMENT_ROOT'].'/includes/top.php');
This mainly jumps back to the servers document root and then begins to enter the directories defined until it finds the file. In this case it would go back to the root of the server, or whatever your document root is, and then enter includes. there it would search for the top.php file. Simple to use, yet effective...espcially for people like me who re-use code or move files to different directories. I don't have to fix the includes, because they all work the same way.
24-Feb-2006 11:24
WARNING: Be absolutely sure that your include paths are relative or directory based and not http!!!
require("http://www.mydomain.com/somefile.php"); //WRONG!!
require("usr/mydomain/somefile.php"); //CORRECT!!
If you are intending to access local files and you accidentally use an http address, the request will probably work. However, this creates a wierd situation that can cause all sorts of bugs in your scripts and slow your code down.
The problem is that the include spawns off another php request, and is essentially requesting the file in the same a way a remote viewer would. So rather than including the intended php code, instead you get the processed output from that single file executed in its own private scope.
It's a simple mistake, but it can be an awful problem to debug.
Walker
22-Jan-2006 08:08
re: danielm at unb dot br...
$_SERVER['DOCUMENT_ROOT'] is very useful, but it is not available with all web servers. Apache has it; IIS doesn't.
I use the following to make my PHP applications work in more situations:
<?php
if (!defined("BASE_PATH")) define('BASE_PATH', isset($_SERVER['DOCUMENT_ROOT']) ? $_SERVER['DOCUMENT_ROOT'] : substr($_SERVER['PATH_TRANSLATED'],0, -1*strlen($_SERVER['SCRIPT_NAME'])));
?>
...but even that gets tripped up by symlinks to different mount points, etc. You could substitute realpath($_SERVER['PATH_TRANSLATED']), but that function has been reported not to work on some (Windows) servers. One could use the PATH_TRANSLATED for both servers, but I figure if Apache is going to tell me exactly what I want to know, I should listen.
06-Jul-2005 06:54
Something which may not be immediately obvious is that if you use double quotes on the filename, you can use variables to specify the filename, allowing you to do something like this:
<?php
$query = "SELECT filename FROM updates WHERE version>$current ORDER BY version";
$updateresult = mysql_query($query) or exit($query.'<br />'.mysql_error());
while ($updaterow = mysql_fetch_row($updateresult)) {
require "$updaterow[0]";
}
?>
Drop this in a script on a server and you can push updates to your clients. Obviously, make sure you only run scripts you want to.
06-May-2005 05:42
This will sound elementary, but for C++ native programmers, be sure NOT to put a '#' in front of your include statements! The parser will not give you an error, but also will not include the file, making for a tedious debugging process.
In short, USE:
<?php
include "yourfile.php";
?>
and DON'T use:
<?php
#include "yourfile.php";
?>
07-Apr-2005 08:58
If you use relativ paths in a php script (file A) that can be required by another php script (file B), be aware that the relativ paths in file A will be relativ to the directory, where file B is stored.
You can use the following syntax in file A, to be sure that the paths are relativ to the directory of file A:
<?
require(dirname(__FILE__)."/path/relative/file_to_include.php");
?>
Greetings,
Richard
Note when calling any require or include function, that the call will block if the script given as the parameter is excecuting.
Because of this one should be careful when using blocking functions like sleep() in a script which is included by another.
22-Nov-2004 07:50
if you want to include files with an absolut path reference, you can use:
require ($_SERVER["DOCUMENT_ROOT"]."/path/to/file.php");
this way you can organize your files in subdirectories trees.
