文字

include

(PHP 4, PHP 5)

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 " ;
}



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

?>

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

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

Warning

Windows 版本的 PHP 在 4.3.0 版之前不支持通过此函数访问远程文件,即使已经启用 allow_url_fopen.

Example #3 通过 HTTP 进行的 include

<?php



// 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') == 'OK'), i.e. include('')
if (include( 'vars.php' ) ==  'OK' ) {
    echo 
'OK' ;
}

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

Example #5 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 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。

用户评论:

[#1] error17191 at gmail dot com [2015-10-01 09:39:59]

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

[#2] Jero Minh [2015-04-01 10:55:40]

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

[#3] Rash [2015-01-17 17:55:03]

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.

[#4] Ray.Paseur often uses Gmail [2014-09-30 23:05:29]

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);

[#5] Jochen mauch at mail dot de [2014-09-18 10:34:22]

Typically I use PHP to build myself a rudimentary CMS, i.e. one not as powerful and GUI-ish to use as full-blown systems like e.g. Joomla or Typo3 for the sake of not having to dive exhaustingly into how to use these systems, or, in less words: for the sake of simplicity. Thus I wrote a function to include snippets based on an optional parameter specifying the snippets directory and two shorthands for frequently used snippets:

<?php

function includeSnippetHere($name$snippetDir 'snippets/') { include $snippetDir.$name; }

function abbrSSL() { includeSnippetHere('abbrSSL.htm'); }
function 
KonqOnly() { includeSnippetHere('KonqOnly.htm'); }
?>

[#6] abanarn at gmail dot com [2014-07-11 14:56:26]

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,

[#7] phpbypass at digitallyhazardous dot com [2014-03-02 21:13:17]

You can use include in echo short tags.  To avoid include echoing '1' when you don't need it, simply add an empty string and a demiter to the beginning of the statement.

Example :  <?php='';include('foobar.php')?>

[#8] casey at seangroup dot com [2013-09-22 21:35:56]

Include function,utilizing extract and compact to post variables to and return from an include file (great for configurations, ex: DB connection info, or whatever else you can imagine). 

<?php
# include function allowing variables to be posted to and returned from the target script
    
function inc$__path$__return='.', array $__post=array() ) {
    
# post var's to the local scope
        
if ( count$__post ) )
            
extract($__postEXTR_SKIP);
    
# include the file and store the result
        
if ( $__result = include $__path ) {
        
# return requested variables from the included file
            
if ( is_array($__return) )
                
$result compact($__return);
        
# Return ALL variables defined from within the included file
        # NOTE: $__post keys are NOT included!
            
else if ( $__return == '.' )
                
$result compactarray_diffarray_keys(get_defined_vars()),
                    array(
'GLOBALS''__path''__return''__post''__result')
                    + 
array_keys($__post) ) );
        
# Is $__return a variable from the file?
            
else if ( $__return && isset($$__return) )
                
$result = array( $__return => $$__return );
            else
                
$result = array();
        
# unshift the include result into $result
            
array_unshift($result$__result);
            return 
$result;
        }
        return array(
$__result);
    }
?>


-------------------------------------------
www.show-ip.org

[#9] ethantsien at gmail dot com [2013-09-11 12:08:25]

"Files are included based on the file path given or, if none is given, the include_path specified. If the file isn't found in the include_path, include will finally check in the calling script's own directory and the current working directory before failing. "

i strace some php code, i think the first step is searching the current working directory , then include path, the final is the calling script's own directory

[#10] brett dot jr dot alton at gmail dot com [2012-08-09 16:34:32]

You need to test to see if include() is equal to 1 to see if it's successful. For some reason it tests success instead of failure.

So to test if the include failed, you need to test like this:

<?php
if ((include 'inc/db.php') !== 1)
{
    die(
'Include failed.');
}
?>


The docs say to test against 'OK', which is incorrect, as the return value is int(1);

[#11] Anon [2012-02-26 18:31:16]

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.

[#12] sPlayer [2011-03-02 09:09:59]

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));
?>

[#13] joe dot naylor at gmail dot com [2010-10-22 14:11:57]

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.

[#14] emanueledelgrande ad email dot it [2010-07-09 14:23:59]

About the problem to include a script in the global scope, after many tests with different solutions, I reached my point. I post it in the hope it may be useful.

At first I built my "globalScopeSimulator" class, but an include called inside a class is not the best solution: if it contains some user code, the user will access to the $this reserved variable and even to all the private members... Critical issue!

That's why I turned back into a function solution.

Another advantage is that I didn't have to make use of the deprecable "global" keyword, since I *imported* the global scope inside the function, with the extract() function.
Using the EXTR_REFS flag this trick does not waste memory, since the extracted variables are not a copy, but a reference to the global ones.

<?php
function global_include($script_path) {
    
// check if the file to include exists:
    
if (isset($script_path) && is_file($script_path)) {
        
// extract variables from the global scope:
        
extract($GLOBALSEXTR_REFS);
        
ob_start();
        include(
$script_path);
        return 
ob_get_clean();
    } else {
        
ob_clean();
        
trigger_error('The script to parse in the global scope was not found');
    }
}
?>


Hope it helps... :)
Cheers and happy coding!

[#15] this dot person at joaocunha dot eti dot br [2009-12-23 05:20:02]

AVOID ZERO BYTE ORDER MARK!

I was having problems with include/require (once or not). I created an include-opening.php which had the initial structure of the page, and then included this page in all other pages. The result was looking "crashed", so I did compare including or just pasting the html code into the page. The hardcoded version displayed ok, even with the source code being exactly the same.

So I opened the include file with notepad++ and set the encoding to UTF-8 (no BOM) and voila, everything is working great now.

[#16] daevid at daevid dot com [2009-11-20 16:54:03]

Well now, I am confused because these pages all show them as functions:
Include(), require(), require_once(), include_once()

Yet ALL of the examples show the PEAR way:
http://pear.php.net/manual/en/standards.including.php

"Note: include_once and require_once are statements, not functions. Parentheses should not surround the subject filename." 

include_once "a.php";

To change all require_once('foo.php'); to require_once 'foo.php' execute this:

cd /var/www/

find . -name '*.php' -print | xargs egrep -l \
'require_once\s*(\(.*\));'\ | xargs sed -i.sedorig -e \
's/require_once\s*(\(.*\));/require_once \1;/'

(thanks to Robert Hajime Lanning for that)

Then to remove all the ".php.sedorig" backup files execute this:

find . -name "*.php.sedorig" -type f -exec rm -rf {} \;

[#17] Chris Bell [2009-11-12 17:12:20]

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.

[#18] Anonymous [2009-11-11 11:35:05]

I was having problems when HTTP headers were being sent before I was ready.  I discovered that this happened only when I was including a file at the top of my script.  Since my included file only contained PHP with no whitespace outside the tags, this behavior seemed incorrect.

The editor I was using was saving the files in UTF8 format, sometimes including the redundant Byte Order Mark at the beginning of the file.  Any Unicode-aware editor would implicitly hide the presence of the BOM from the user, making it hard to notice the problem.  However, by using a hex editor I was able to see and remove the three bytes, restoring normal behavior.

Moral:  Prevent your editor from adding an invisible Unicode Byte Order Mark to the beginning of your source code!

[#19] hyponiq at gmail dot com [2009-11-02 02:12:28]

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 {
    

    
$directories = array(
        
'Includes'
    
);
    
    if (
defined('__DIR__')) {
        
$currentDirectory __DIR__;
    }
    else {
        
$currentDirectory dirname(__FILE__);
    }
    
    
$currentDirectory rtrim($currentDirectoryDIRECTORY_SEPARATOR);
    
$currentDirectory $currentDirectory DIRECTORY_SEPARATOR;
    
    foreach (
$directories as $directory) {
        
$currentDirectory str_replace(
            
DIRECTORY_SEPARATOR $directory DIRECTORY_SEPARATOR,
            
DIRECTORY_SEPARATOR,
            
$currentDirectory
        
);
    }
    
    
$currentDirectory rtrim($currentDirectoryDIRECTORY_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';
?>

[#20] johan [2008-12-10 05:47:36]

If you wish to abstract away include calls inside functions, or programmatically juggle files to include using functions, just remember:

1. Declare any variables as global if you want those variables "included" in the global scope (ie. if they are used outside the file).

2. Functions are naturally global, so files that only contain functions (libs, sets of api's what have you) can be included anywhere. 

eg.

<?php
function nav($i){
  include 
"nav$i.php";
}

nav(1); 

// same as...
include "nav1.php";
// ...as long as variables are global
?>


So don't feel you can only include/require at the beginning of files, or outside/before functions. You can totally program any sophisticated include behavior.

[#21] snowyurik at gmail dot com [2008-11-05 22:49:17]

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.

[#22] Wade. [2008-10-22 20:20:46]

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.

[#23] AntonioCS at gmail dot com [2008-09-26 10:39:57]

Include and Require will call the __autoload function if the file that is being called extends some other class

Example Code:
File teste.php
<?php
class teste extends motherclass {
    public function 
__construct() {
        
parent::__construct();    
    }       
}
?>


File example.php

<?php 
require("teste.php");

if (
class_exists("motherclass"))
echo 
"It exists";

?>


You will be given the output:

It exists

I think the __autoload function should be called when I instantiate the teste class not when I include/require the file.

[#24] example at user dot com [2008-09-21 21:33:12]

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');"

[#25] thedanevans at gmail dot com [2008-09-20 23:02:31]

Linking to CSS/JavaScript resources through an included file has bugged me for a long time because if I have a directory structure like:
/www
    index.php
    /sub_dir
        index.php
    /includes
        header.php
    /style
        main.css

where both index.php files include header.php and the header.php file includes something like:

<link rel="stylesheet" type="text/css" href="style/main.css">

This will be included for /index.php but not for /sub_dir/index.php. I read through a few different ways to use relative includes but those are generally meant for the php include function not the HTML <link>. I didn't really love the idea of a new function that I would pass both the filename and a '../' string into which it could use in the href. I also didn't want to just use /style/main.css because in development it is not hosted in my root directory. Although I could change my configuration or my include_path I really just wanted to find a way for PHP to figure out the relative path for me. I finally found a solution that met my needs and here it is:

<?php
    $include_dist 
substr_count(dirname(__FILE__), DIRECTORY_SEPARATOR);
    
$calling_dist substr_count(dirname($_SERVER['SCRIPT_FILENAME']), DIRECTORY_SEPARATOR);
?>

<link rel="stylesheet" type="text/css" href="<?=str_repeat('../', $calling_dist - $include_dist + 1)?>style/main.css">

In this case I added one to the difference to account for the fact that the include is one directory away from the base. This also means that str_repeat won't be passed a negative value, which would cause an error. dirname(__FILE__) gets the directory of the file being included while dirname($_SERVER['SCRIPT_FILENAME']) gets the directory of the file including it. The script simply finds the difference in how far off the base directory the two are and prints the appropriate number of '../' before the URL.

NOTE: dirname(__FILE__) can be replaced by __DIR__ in PHP greater than or equal to 5.3.0

[#26] rich dot lovely at klikzltd dot co dot uk [2008-07-17 13:20:42]

I needed a way of include()ing a php page from a MySQL database.  It took some work, but 
eventually I came up with this:

<?php
function include_text($text){
    while(
substr_count($text'<?php') > 0){             //loop while there's code in $text
        
list($html$text) = explode('<?php'$text2); //split at first open php tag 
        
echo $html;                                      //echo text before tag
        
list($code$text) = explode('?>
', $text, 2);    //split at closing tag
        eval($code);                                     //exec code (between tags)
    }
    echo $text;                                          //echo whatever is left
}
?>

It doesn't work exactly the same as include(), as newlines after the '?>' tag are echoed, rather 
than being discarded, but that's an exercise left to the reader to fix if they so desire, and
also globals defined within the included text are not available outside the function. 

Not sure whether it would work with something like:

<?php if($x){ ?>
<p>Some HTML Output</p>
...
...
<?php }
else{ 
?>

<p>Other HTML Output</p>
...
...
<?php ?>

I rarely use that, but it's easy to re-write code to avoid it using HereDoc syntax, so the example above becomes:

<?php if($x){ echo <<<EOT
<p>Some HTML Output</p>
...
...
EOT;
}
else{ echo <<<
EOT 
<p>Other HTML Output</p>
...
...
EOT;
?>


Which would work with include_text()

It also won't work as-is with either asp-style or short tags.

[#27] ricardo dot ferro at gmail dot com [2008-05-14 11:14:32]

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_SEPARATORget_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_SEPARATORget_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));
    }
}

?>

[#28] Rick Garcia [2008-05-08 09:38:02]

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.

[#29] uramihsayibok, gmail, com [2008-02-24 17:28:38]

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*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:ar,en-US;q=0.8,en;q=0.6
Cache-Control:max-age=0
Cookie:cwrot=1
Host:gtes.cwahi.net
Proxy-Connection:keep-alive
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.69 Safari/537.36
Response Headersview source
Connection:keep-alive
Content-Encoding:gzip
Content-Type:application/xml
Date:Fri, 04 Oct 2013 06:33:45 GMT
Server:nginx/1.3.0
Transfer-Encoding:chunked
Vary:Host
X-Powered-By:PHP/5.2.11

[#6] bimal at sanjaal dot com [2011-06-04 11:46:39]

If your code is running on multiple servers with different environments (locations from where your scripts run) the following idea may be useful to you:

a. Do not give absolute path to include files on your server.
b. Dynamically calculate the full path (absolute path)

Hints:
Use a combination of dirname(__FILE__) and subsequent calls to itself until you reach to the home of your '/index.php'. Then, attach this variable (that contains the path) to your included files.

One of my typical example is:

<?php
define
('__ROOT__'dirname(dirname(__FILE__)));
require_once(
__ROOT__.'/config.php');
?>


instead of:
<?php require_once('/var/www/public_html/config.php'); ?>

After this, if you copy paste your codes to another servers, it will still run, without requiring any further re-configurations.

[EDIT BY danbrown AT php DOT net: Contains a typofix (missing ')') provided by 'JoeB' on 09-JUN-2011.]

[#7] spark at limao dot com dot br [2011-04-14 07:31:53]

if you use require_once on a file A pointing to file B, and require_once in the file B pointing to file A, in some configurations you will get stuck

also wouldn't it be nice to manage that to prevent getting stuck AND use the good old Java import?

<?php
       
function import($path=""){
               if(
$path == ""){ //no parameter returns the file import info tree;
                       
$report $_SESSION['imports'];
                       foreach(
$report as &$item$item array_flip($item);
                       return 
$report;
               }

               
$current str_replace("\\","/",getcwd())."/";
               
$path $current.str_replace(".","/",$path);
               if(
substr($path,-1) != "*"$path .= ".class.php";

               
$imports = &$_SESSION['imports'];
               if(!
is_array($imports)) $imports = array();

               
$control = &$imports[$_SERVER['SCRIPT_FILENAME']];
               if(!
is_array($control)) $control = array();

               foreach(
glob($path) as $file){
                       
$file str_replace($current,"",$file);
                       if(
is_dir($file)) import($file.".*");
                       if(
substr($file,-10) != ".class.php") continue;
                       if(
$control[$file]) continue;
                       
$control[$file] = count($control);
                       require_once(
$file);
               }
       }
?>


just remember to start the session and to enable the glob function

now you can use
<?php
    import
("package.ClassName");
    
import("another.package.*"); //this will import everything in the folder
?>

[#8] info at erpplaza dot com [2010-10-05 00:10:23]

Include all files from a particular directory

<?php
foreach (glob("classes
 
 //require ('/www/includes/example.com/code/conf/sql_servers.inc');
 //require ('../../includes/example.com/code/conf/sql_servers.inc');
 //require_once ('/www/includes/example.com/code/conf/sql_servers.inc');
 //require_once ('../../includes/example.com/code/conf/sql_servers.inc');
 
 
$end_time microtime(true);
 
 
$handle fopen("/tmp/results""ab+");
 
fwrite($handle, ($end_time $start_time) . "\n");
 
fclose($handle);
?>


The test:
  I ran ab on the test.php script with a different require*() uncommented each time:
  ab -n 1000 -c 10 www.example.com/test.php

RESULTS:
--------
The average time it took to run test.php once:
require('absolute_path'):      0.000830569960420
require('relative_path'):      0.000829198306664
require_once('absolute_path'): 0.000832904849136
require_once('relative_path'): 0.000824960252097

The average was computed by eliminating the 100 slowest and 100 fastest times, so a total of 800 (1000 - 200) times were used to compute the average time.  This was done to eliminate any unusual spikes or dips.

The question of how many stat() system calls were made can be answered as follows:
- If you run httpd -X and then do an strace -p <pid_of_httpd>, you can view the system calls that take place to process the request.
- The most important thing to note is if you run test.php continuously (as the ab test does above), the stat() calls only happen for the first request:

  first call to test.php (above):
  -------------------------------
  lstat64 ("/www", {st_mode=S_IFDIR|0755, st_size=...
  lstat64 ("/www/includes", {st_mode=S_IFDIR|0755,...
  lstat64 ("/www/includes/example.com", {st_mode=S...
  lstat64 ("/www/includes/example.com/code", {st_m...
  lstat64 ("/www/includes/example.com/code/conf", ...
  lstat64 ("/www/includes/example.com/code/conf/sql_servers.inc", {st_mode...
  open ("/www/includes/example.com/code/conf/sql_servers.inc", O_RDONLY) = 17
  
  subsequent calls to test.php:
  -----------------------------
  open ("/www/includes/example.com/code/conf/sql_servers.inc", O_RDONLY) = 17

- The lack of stat() system calls in the subsequent calls to test.php only happens when test.php is called continusly.  If you wait a certain period of time (about 1 minute or so), the stat() calls will happen again.
- This indicates that either the OS (Ubuntu Linux in my case), or Apache is "caching" or knows the results of the previous stat() calls, so it doesn't bother repeating them.
- When using absolute_path there are fewer stat() system calls.
- When using relative_path there are more stat() system calls because it has to start stat()ing from the current directory back up to / and then to the include/ directory.

CONCLUSIONS:
------------
- Try to use absolute_path when calling require*().
- The time difference between require_once() vs. require() is so tiny, it's almost always insignificant in terms of performance.  The one exception is if you have a very large application that has hundreds of require*() calls.
- When using APC opcode caching, the speed difference between the two is completely irrelevant.
- Use an opcode cache, like APC!

Konstantin Rozinov
krozinov [at] gmail

[#12] cnorthcote at underground dot co dot uk [2008-03-14 03:20:57]

Bear in mind that require_once doesn't have a return value (neither does require; since they both halt execution on failure), so this won't work:

<?php

require_once("path/to/myfile.php") or die("Couldn't load myfile");

?>


because you will get a very unhelpful error:

PHP Fatal error:  require_once() : Failed opening required '1' (include_path='.;C:\\php5\\pear') in C:\path\to\code.php on line 1

This was mentioned on the php-general mailing list in about 2003 but is a gotcha I have seen a few people come across. If you want to check to see if a file was included, use @include() instead.

[#13] amcewen at look dot ca [2008-02-11 07:00:10]

Perhaps it would be clearer to say that require_once() includes AND evaluates the resulting code once.  More specifically, if there is code in the script file other than function declarations, this code will only be executed once via require_once().

[#14] manuel schaffner [2007-06-14 14:02:16]

The path for nested require_once() is always evaluated relative to the called / first file containing require_once(). To make it more flexible, maintain the include_path (php.ini) or use set_include_path() - then the file will be looked up in all these locations.

[#15] jazfresh at hotmail.com [2007-03-07 23:22:43]

Check how many files you are including with get_required_files(). If it's a significant number (> 100), it may be worth "compiling" the main PHP file. By "compiling", I mean write a script that reads a PHP file and replaces any "include/require_once" references with either:
- the file that it's requiring
- a blank line if that file has been included before

This function can be recursive, thus building up a large PHP file with no require_once references at all. The speedup can be dramatic. On one of our pages that included 115 classes, the page was sped up by 60%.

[#16] sneskid at hotmail dot com [2007-01-19 12:00:45]

<?php
function & rel($r, &$f) {return file_exists( ( $f = ( dirname($r).'/'.$f ) ) );}
function & 
relf($r$f) {return rel($r,$f) ? file_get_contents($f) : null;}
function & 
reli($r$f) {return rel($r,$f) ? include($f) : null;}
function & 
relr($r$f) {return rel($r,$f) ? require($f) : null;}
function & 
relio($r$f) {return rel($r,$f) ? include_once($f) : null;}
function & 
relro($r$f) {return rel($r,$f) ? require_once($f) : null;}
?>


I found it useful to have a function that can load a file relative to the calling script and return null if the file did not exist, without raising errors.

<?php

echo relf(__FILE__'some.file');
?>


It was easy to modify and just as useful for require/include.

<?php

relro(__FILE__'stats.php');
?>


If you work with a deep php file structure and a barrage of includes/requires/file-loads this works well.

[#17] rejjn at mail dot nu [2006-09-01 02:28:58]

The following only applies to case insensitive systems like Windows.

Even though the documentation sais that "the path is normalized" that doesn't seem to be true in all cases. 

If you are using the magic __autoload() function (or if the framework you're using is using it) and it includes the requested class file with complete path or if you override the include path in mid execution, you may have some very strange behavior. The most subtle problem is that the *_once functions seem to differentiate between c:\.... and C:\....

So to avoid any strange problems and painfull debugging make sure ALL paths you use within the system have the same case everywhere, and that they correspond with the actual case of the filesystem. That includes include paths set in webserver config/php.ini, auto load config, runtime include path settings or anywhere else.

[#18] antoine dot pouch at mcgill dot ca [2006-03-10 07:13:45]

require_once (and include_once for that matters) is slow. 
Furthermore, if you plan on using unit tests and mock objects (i.e. including mock classes before the real ones are included in the class you want to test), it will not work as require() loads a file and not a class.

To bypass that, and gain speed, I use :

<?php
class_exists
('myClass') || require('path/to/myClass.class.php');
?>


I tried to time 100 require_once on the same file and it took the script 0.0026 seconds to run, whereas with my method it took only 0.00054 seconds. 4 times faster ! OK, my method of testing is quite empirical and YMMV but the bonus is the ability to use mock objects in your unit tests.

[#19] martijn(dot)lowrider(at)gmail(dot)com [2006-02-24 11:00:58]

How to use Require_Once with error reporting to include a MySQL Connection file:

-------------------------------------------------------------------
$MySQLConnectFile = './inc/MySQL.Class.php';

if ( is_dir ( './inc/' ) )
{
$IncIsDir == TRUE;
}

if ( file_exists ( $MySQLConnectFile ) )
{
$MySQLFileExists == TRUE;
}

if ( $IncIsDir && $MySQLFileExists )
{
require_once ( $MySQLConnectFile )
}
else
{
echo '<b>Error:</b> <i>Could not read the MySQL Connection File. Please try again later.';
exit();
}

----------------------------------------------------------------------

[#20] miqrogroove [2005-05-01 11:10:02]

require_once() is NOT independent of require().  Therefore, the following code will work as expected:

echo.php
<?php
echo "Hello";
?>


test.php
<?php
require('echo.php');
require_once(
'echo.php');
?>


test.php outputs: "Hello".

Enjoy,
-- Miqro

[#21] ulderico at maber dot com dot br [2005-03-22 05:38:04]

With both of your functions guys, Pure-PHP and jtaal at eljakim dot nl, you'll not have any variables available GLOBALly if they're supposed to be globals...

That's why my import handles better those situation. OK, SOME MAY DISPUTE that using include_once and require_once may slow down an application. But what's the use to do IN PHP what the interpreter *should* do better for you. Thusly these workarounds shall, some time in the future, DIE.

Thus It's better to well design your application to keep some order using few INCLUDES and REQUIRES in it rather than insert MANY AND SEVERAL *_once around.

[#22] Pure-PHP [2005-03-17 14:19:07]

require_once can slower your app, if you include to many files.

You cann use this wrapper class, it is faster than include_once 

http://www.pure-php.de/node/19

require_once("includeWrapper.class.php")

includeWrapper::require_once("Class1.class.php");
includeWrapper::require_once("Class1.class.php");
includeWrapper::require_once("Class2.class.php")

[#23] jtaal at eljakim dot nl [2005-03-10 05:00:35]

When you feel the need for a require_once_wildcard function, here's the solution:

<?php // /var/www/app/system/include.inc.php

function require_once_wildcard($wildcard$__FILE__) {
  
preg_match("/^(.+)\/[^\/]+$/"$__FILE__$matches);
  
$ls = `ls $matches[1]/$wildcard`;
  
$ls explode("\n"$ls);
  
array_pop($ls); // remove empty line ls always prints
  
foreach ($ls as $inc) {
    require_once(
$inc);
  }
}

?>


The $__FILE__ variable should be filled with the special PHP construct __FILE__:
<?php // /var/www/app/classes.inc.php

require_once('system/include.inc.php');
require_once_wildcard("classes  $arg_n )
{
    echo 
"Example function.\n" ;
    return 
$retval ;
}
?>

任何有效的 PHP 代码都有可能出现在函数内部,甚至包括其它函数和类定义。

函数名和 PHP 中的其它标识符命名规则相同。有效的函数名以字母或下划线打头,后面跟字母,数字或下划线。可以用正则表达式表示为:[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*

Tip

请参见用户空间命名指南。

函数无需在调用之前被定义,除非是下面两个例子中函数是有条件被定义时。

当一个函数是有条件被定义时,必须在调用函数之前定义。

Example #2 有条件的函数

<?php

$makefoo 
true ;



bar ();

if (
$makefoo ) {
  function 
foo ()
  {
    echo 
"I don't exist until program execution reaches me.\n" ;
  }
}



if ( $makefoo foo ();

function 
bar ()
{
  echo 
"I exist immediately upon program start.\n" ;
}

?>

Example #3 函数中的函数

<?php
function  foo ()
{
  function 
bar ()
  {
    echo 
"I don't exist until foo() is called.\n" ;
  }
}



foo ();



bar ();

?>

PHP 中的所有函数和类都具有全局作用域,可以定义在一个函数之内而在之外调用,反之亦然。

PHP 不支持函数重载,也不可能取消定义或者重定义已声明的函数。

Note: 函数名是大小写无关的,不过在调用函数的时候,使用其在定义时相同的形式是个好习惯。

PHP 的函数支持可变数量的参数和默认参数。参见 func_num_args() func_get_arg() func_get_args()

在 PHP 中可以调用递归函数。

Example #4 递归函数

<?php
function  recursion ( $a )
{
    if (
$a  20 ) {
        echo 
" $a \n" ;
        
recursion ( $a  1 );
    }
}
?>

Note: 但是要避免递归函数/方法调用超过 100-200 层,因为可能会使堆栈崩溃从而使当前脚本终止。 无限递归可视为编程错误。

用户评论:

[#1] Muneeb Aslam [2015-11-23 15:09:12]

following is a function that can be used to convert numeric date to alphabetic date, e-g from 2015-11-16 to 16 Nov, 2015.

1. Function takes 3 parameters, numeric date, locale and length of month
2. Function currently supports EN and ES month names.
3. Function can be calles as  <?php convertDate("2015-11-16","en","full"); ?>

<?php

    
function convertDate($date,$locale,$length){
        
        
$monthNames = array(
                
"en" => array(
                    
"full" => array(1=>'January','February','March','April','May',
                    
'June','July','August','September','October','November','December'),
                    
                    
"short" => array(1=>'Jan','Feb','Mar','Apr','May','Jun',
                    
'Jul','Aug','Sep','Oct','Nov','Dec')
                ),
                
"es" => array(
                    
"full" => array(1=>'Enero','Febrero','Marzo','Abril','Mayo',
                    
'Junio','Julio','Agosto','Septiembre','Octubre','Noviembre','Deciembre'),
                    
                    
"short" => array(1=>'Ene','Feb','Mar','Abr','May','Jun',
                    
'Jul','Ago','Sep','Oct','Nov','Dec')
                ),
            );
            
            
$exploded explode("-",$date);
            
$year $exploded[0];
            
$month $exploded[1];
            
$day $exploded[2];
            
            
$month $monthNames[$locale][$length][$month];
            
$date $day " " $month ", " $year;
            return 
$date;
    }

?>

[#2] ohcc at 163 dot com [2015-11-07 15:52:14]

As of PHP 7.0, you can restrain type of return value of user defined functions.

Syntax is : function FunctionName ($arg1, $arg2, ...)  : TYPE { ... }

TYPE is a string representing the type of return value, TYPE can be a class name or a php variable type, such as array/string/bool/int/float. 

When TYPE is one of the following value, it also stands for a classname

str/boolean/integer/real/double/resource/object/scalar

However,in my opion, boolean/bool, integer/int ... should have the same meaning, but at least in PHP7, they stand for different meanings respectively. This may be fixed in later versions of PHP.

<?php
    
function wxc ($var) : string {
        return 
$var;
    }
?>


this function must return a string, if it return something else when called, a "Fatal error: Uncaught TypeError" error will be triggered.

code above is supported only in PHP 7+

[#3] N Atanackovic [2015-03-16 17:31:16]

You can also call function from itself.  For example, I want to reach the deepest value in multidimensional array and I call function from inside the very same function. In this example function behave as some meta-loop.
    
<?php 

$arr1
=array('a'=>array('e'=>array('f'=>array('g'=>'h''n' )),'b','c'));
$arr2=array('a'=>array('e'=>array('f'=>array('g'=>array('l'=>array('m'=>'w','q')), 'n' )),'b','c'));

function 
Deep($array){
    foreach(
$array as $key){
        if(
is_array($key)){
             return 
Deep($key);//calling the function inside the function
}else {
echo 
$key;
        }
    }
}

echo 
Deep($arr1); //outputs: hn
echo Deep($arr2); //outputs: wq

?>

[#4] php at xenhideout dot nl [2014-09-15 17:59:28]

Please be advised that the code block defining the function, within the function_exists() call, has to be executed for the function to get defined, whereas this is not the case for regular, unenclosed functions.

Meaning, if you write code like this:

<?php

do_function
();

if (!
function_exists('my_undefined')) {
    function 
my_undefined() {
    }
}

function 
do_function() {
    
my_undefined();
}
?>


..Then my_undefined will not be defined before the code in do_function calls it. Some people put their function sections below the regular executing code of the script. Making any of it 'pluggable' can then cause problems.

[#5] aydinantmen [at] hotmail [dot] com [2014-04-23 17:17:23]

I want to use multidimentional arrays in a callback function what accepts second parameter.

Solution:

<?php

$arr1 
= array("a" => "b""c""d's""e" => array("f's""g" => array("h's""i" => "j's")));
$arr2 mdarr_parameter($arr1);
$arr3 mdarr_parameter($arr2true);

function 
mdarr_parameter($needle$job=false) {
    if (
is_array($needle)) {
        foreach(
$needle as $name => $value) {
            
$needle[$name] = mdarr_parameter($value$job);
        }
    } else {
        
// Now you do anything you want...
        
if ($job === true) {
            
$needle stripslashes($needle);
        } else {
            
$needle addslashes($needle);
        }
    }
    return 
$needle;
}

print_r($arr2);
print_r($arr3);



?>

上一篇: 下一篇: