从 PHP 5.3.0 开始,您可以使用 __DIR__ 作为 dirname(__FILE__) 的替代品
(PHP 4, PHP 5, PHP 7, PHP 8)
dirname — 返回父目录的路径
给定包含文件或目录路径的字符串,此函数将返回当前目录的 levels
级父目录的路径。
注意:
dirname() 对输入字符串进行简单操作,不了解实际文件系统或路径组件(例如“
..
”)。
在 Windows 上,dirname() 假设当前设置的代码页,因此,为了让它看到包含多字节字符路径的正确目录名称,必须设置匹配的代码页。如果 path
包含当前代码页中无效的字符,dirname() 的行为将是未定义的。
在其他系统上,dirname() 假设 path
以 ASCII 兼容的编码进行编码。否则,函数的行为将是未定义的。
path
一个路径。
在 Windows 上,斜杠 (/
) 和反斜杠 (\
) 都用作目录分隔符字符。在其他环境中,它是正斜杠 (/
)。
levels
要向上移动的父目录数量。
这必须是一个大于 0 的整数。
返回父目录的路径。如果 path
中没有斜杠,则返回一个点('.
'),表示当前目录。否则,返回的字符串是 path
,其中任何尾随的 /component
都已删除。
在循环中使用此函数时要小心,因为该循环可能会到达顶层目录,从而导致无限循环。
<?php
dirname('.'); // 将返回 '.'.
dirname('/'); // 将在 Windows 上返回 `\`,在 *nix 系统上返回 '/'。
dirname('\\'); // 将在 Windows 上返回 `\`,在 *nix 系统上返回 '.'。
dirname('C:\\'); // 将在 Windows 上返回 'C:\',在 *nix 系统上返回 '.'。
?>
版本 | 描述 |
---|---|
7.0.0 | 添加了可选的 levels 参数。 |
示例 #1 dirname() 示例
<?php
echo dirname("/etc/passwd") . PHP_EOL;
echo dirname("/etc/") . PHP_EOL;
echo dirname(".") . PHP_EOL;
echo dirname("C:\\") . PHP_EOL;
echo dirname("/usr/local/lib", 2);
上面的示例将输出类似于以下内容
/etc / (or \ on Windows) . C:\ /usr
从 PHP 5.3.0 开始,您可以使用 __DIR__ 作为 dirname(__FILE__) 的替代品
由于给出的示例中的路径只有两个部分(例如“/etc/passwd”),因此不清楚 dirname 是返回父目录的单个路径元素还是返回直到父目录(包括父目录)的整个路径。从实验结果来看,似乎是后者。
例如
dirname('/usr/local/magic/bin');
返回 '/usr/local/magic' 而不是仅 'magic'
此外,不清楚 dirname 实际上返回路径的最后一个项目的父目录,无论最后一个项目是目录还是文件。(即,人们可能会认为,如果给定的路径是目录,那么 dirname 将返回整个原始路径,因为那是一个目录名称。)
此外,路径末尾存在目录分隔符并不一定表示路径的最后一个项目是目录,因此
dirname('/usr/local/magic/bin/'); #注意最后的 '/'
将返回与我上面示例相同的结果。
简而言之,这似乎更像是一个字符串操作函数,它从路径字符串中剥离最后一个非空文件或目录元素。
获取当前包含文件的目录
<?php
dirname(__FILE__);
?>
例如,如果一个名为 'database.init.php' 的脚本从文件系统的任何位置包含,并且它希望包含脚本 'database.class.php'(位于同一目录中),您可以使用
<?php
include_once(dirname(__FILE__) . '/database.class.php');
?>
请注意,如果您在 Windows 上调用 dirname(__FILE__),您可能会获得反斜杠。如果您随后尝试使用 str_replace() 或 preg_replace() 使用正斜杠在搜索模式中替换路径的一部分,则不会匹配。您可以在进行任何转换之前使用 $path = str_replace('\\', '/' ,$path) 来规范化路径
dirname 函数通常不会在末尾返回斜杠,这可能会鼓励您使用类似于以下代码创建链接
$url = dirname($_SERVER['PHP_SELF']) . '/somepage.php';
但是,如果指定的路径是根目录,则 dirname 会返回斜杠,因此在这种情况下 $url 将变为 '//somepage.php'。例如,如果您将该 URL 作为表单的 action 放置,则提交表单将尝试转到 http://somepage.php.
当我在具有路径的 URL 上编写站点时遇到了这个问题,www.somehost.com/client/somepage.php,上面的代码工作得很好,但随后我想将其放在子域上,client.somehost.com/somepage.php,在那里事情开始出现故障。
最好的解决方案是创建一个生成绝对 URL 的函数,并在整个站点中使用它,但创建一个安全的 dirname 函数(以及一个 htaccess 重写以防万一修复双斜杠)为我解决了这个问题
<?php
function safe_dirname($path)
{
$dirname = dirname($path);
return $dirname == '/' ? '' : $dirname;
}
?>
注意这一点。Dirname 可能会搞乱斜杠。
在 Windows 上,Apache
<?php
echo '$_SERVER[PHP_SELF]: ' . $_SERVER['PHP_SELF'] . '<br />';
echo 'Dirname($_SERVER[PHP_SELF]: ' . dirname($_SERVER['PHP_SELF']) . '<br>';
?>
输出
$_SERVER[PHP_SELF]: /index.php
Dirname($_SERVER[PHP_SELF]: \
像往常一样,要包含或引入文件,我们使用这个
<?php
require dirname(__FILE__) . DIRECTORY_SEPARATOR . 'my_file.php';
?>
在极少数情况下,当前文件位于根目录,dirname 会返回 C:\ 或 /,然后上面的行包含 2 个斜杠 \\ 或 //
为了处理这种情况,我们使用 rtrim 来清除斜杠。
<?php
require rtrim(dirname(__FILE__), '/\\') . DIRECTORY_SEPARATOR . 'my_file.php';
?>
此外,dirname 的另一个用途是获取虚拟目录(URL 路径),问题与上面一样,我们在连接字符串之前必须检查和处理
在 script.php 中,我需要知道包含目录的名称。例如,如果我的脚本位于 '/var/www/htdocs/website/somedir/script.php',我需要以统一的方式知道 'somedir'。
解决方法是
<?php
$containing_dir = basename(dirname(__FILE__));
?>
文件位于本地:F:\localhost\www\Shaz3e-ResponsiveFramework\S3-CMS\_source
本地主机路径:http://s3lab.com/Shaz3e-ResponsiveFramework/S3-CMS/_source/
示例 1:dirname($_SERVER['PHP_SELF']); // 输出:/Shaz3e-ResponsiveFramework/S3-CMS/_source
示例 2:"http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']); // 输出:http://s3lab.com/Shaz3e-ResponsiveFramework/S3-CMS/_source
示例 3:$_SERVER['HTTP_HOST'] . dirname($_SERVER['PHP_SELF']); // 输出:s3lab.com/Shaz3e-ResponsiveFramework/S3-CMS/_source
相同的功能,但改进了一点,将使用 REQUEST_URI,如果不可用,将使用 PHP_SELF,如果不可用,将使用 __FILE__,在这种情况下,函数必须位于同一个文件中。它应该可以工作,在 Windows 和 *NIX 上。
<?php
function my_dir(){
return end(explode('/', dirname(!empty($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : !empty($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : str_replace('\\','/',__FILE__))));
}
?>
你可以用它来获取父目录
dirname(dirname(__FILE__))
... 包含一个相对于文件路径的文件
include(dirname(__FILE__) . '/path/relative/file_to_include.php');
.. 等等。
递归 dirname 怎么样?要获取目录中 $count 级别的向上目录。
<?php
function r_dirname($path, $count=1){
if ($count > 1){
return dirname(r_dirname($path, --$count));
}else{
return dirname($path);
}
}
在某些情况下(我无法找到依赖项),如果解析的字符串为 UTF-8,basename 和 dirname 可能会返回不正确的值。
例如,dirname("glossary/задний-фокус") 将返回 "glossary",basename("glossary/задний-фокус") 将返回 "-фокус"。
快速修复是
str_replace("!$!", "", dirname(str_replace("/", "!$!/!$!", $q)))
一个简单的方法来显示包含文件的文件夹的 www 路径...
echo "http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']);
获取当前解析的 PHP 脚本的文件夹的绝对路径的最佳方法是
<?php
if (DIRECTORY_SEPARATOR=='/')
$absolute_path = dirname(__FILE__).'/';
else
$absolute_path = str_replace('\\', '/', dirname(__FILE__)).'/';
?>
这将导致一个绝对的 unix 样式路径,它在 Windows 下的 PHP5 中也可以正常工作,在那里混合 '\' 和 '/' 可能会造成问题。
[编辑:danbrown AT php DOT net:应用了作者从后续说明中提供的修复。]
dirname 可以用以下单行代码来创建自引用的 Web 脚本。
<?php
$base_url = str_replace($DOCUMENT_ROOT, "", dirname($PHP_SELF));
?>
在像这样的文件中使用这种方法
/home/mysite/public_html/wherever/whatever.php
将返回
/wherever
现在 $base_url 可用于 HTML 中引用同一目录中的其他脚本。
示例
href='<?=$base_url?>/myscript.php'
获取当前脚本的绝对路径
<?php
dirname(__FILE__)
?>
获取当前脚本的 Web 服务器相对路径...
<?php
function GetRelativePath($path)
{
$npath = str_replace('\\', '/', $path);
return str_replace(GetVar('DOCUMENT_ROOT'), '', $npath);
}
?>
稍后
<?php
GetRelativePath(dirname(__FILE__));
?>
如果有更好的方法,请提出建设性的批评!
在我的基于 MVC 的框架中,我像下面这样进行 BASE_PATH 和 BASE_URL 定义,两者在框架中都能很好地工作,没有问题。
index.php
define('BASE_PATH',realpath('.'));
define('BASE_URL', dirname($_SERVER["SCRIPT_NAME"]));
BASE_PATH 用于服务器端包含。
BASE_URL 用于客户端包含(脚本、css 文件、图像等)。
我在这里看到的多数 mkpath() 函数看起来又长又复杂。
这是我的
<?php
function mkpath($path)
{
if(@mkdir($path) or file_exists($path)) return true;
return (mkpath(dirname($path)) and mkdir($path));
}
?>
未在 Windows 上测试,但 dirname() 手册说它应该可以工作。
层次化包含树的关键问题在于 PHP 处理相对于原始文件而不是当前包含文件的包含路径。
解决方法是为所有包含路径添加前缀
<?php str_replace('//','/',dirname(__FILE__)); ?>
这将生成一个相对于当前文件的基路径,然后允许类似于 C/C++ 的包含行为。
因此,要包含父目录中的文件 1
<?php require_once( str_replace('//','/',dirname(__FILE__).'/') .'../parent.php'); ?>
要包含同一目录中的文件
<?php require_once( str_replace('//','/',dirname(__FILE__).'/') .'neighbor.php'); ?>
要包含子目录中的文件
<?php require_once( str_replace('//','/',dirname(__FILE__).'/') .'folder/sub.php'); ?>
请注意,我们引用的所有路径都不得以 / 开头,并且必须相对于当前文件,以便正确连接。
如果您想获取脚本的父父目录,可以使用以下代码
<?php
//示例脚本路径:home/content/en/script.php
$parentparentdir=basename(dirname(dirname(__FILE__)));
echo $parentparentdir; //将输出 'content'
?>
如果您只是想确定某个文件是否位于某个目录内或其下,例如,用于白名单验证,则以下函数可能对您有用
<?php
function in_dir ($file, $in_dir)
{
$dir = realpath ($file);
$in_dir = realpath ($in_dir);
if (!is_dir ($file)) {
$dir = dirname ($file);
}
do {
if ($dir === $in_dir) {
$is_in_dir = TRUE;
break;
}
} while ($dir !== ($dir = dirname ($dir)));
return (bool) @$is_in_dir;
}
?>
这个小函数获取顶层公共目录
例如,http://www.mysite.com/directory1/file.php
或 http://www.mysite.com/directory1/directory2/directory3/file.php
都将返回 "directory1" ... 这是顶层目录
<?php
function public_base_directory()
{
//获取公共目录结构,例如 "/top/second/third"
$public_directory = dirname($_SERVER['PHP_SELF']);
//将每个目录放入数组中
$directory_array = explode('/', $public_directory);
//获取目录字符串数组中最高的或顶层的
$public_base = max($directory_array);
return $public_base;
}
?>
如果您想从项目路径调用文件,可以获得最佳根路径。
确保在 www/index.php 中定义了此项
或位于 www/ 根目录内的核心文件。
<?php
/**
* @def (string) DS - 目录分隔符。
*/
define("DS","/",true);
/**
* @def (resource) BASE_PATH - 获取基路径。
*/
define('BASE_PATH',realpath(dirname(__FILE__)).DS,true);
?>
您可以随时调用任何文件,而不会遇到任何问题
<?php
include BASE_PATH.'inc/class.php';
?>
用于写入权限检查的代码
<?php
error_reporting(E_ALL);
$dir_name = '/var/www/virtual/phpintra/htdocs/php/';
do {
$b_is_writable = is_writable($dir_name);
echo sprintf("Dir[%s]Writable[%s]\n", $dir_name, $b_is_writable? 'YES':'NO');
}while (($dir_name = dirname($dir_name)) !='/');
?>
我非常感谢 Fredrich Echol 的建议 (rwf at gpcom dot net),关于如何找到基路径,但发现当初始脚本已经在根文件夹中时它会失败 -- dirname('/rootscript.php')=='/' 和 dirname('/include/includescript.php')=='/include' 具有相同的斜杠数量。这是我现在使用的变体
<?php
if (!defined("BASE_PATH")) define('BASE_PATH', dirname($_SERVER['SCRIPT_NAME'])=='/' ? './' : str_repeat("../", substr_count(dirname($_SERVER["SCRIPT_NAME"]), "/")));
?>
这显式地检查根路径 (/),如果我们在根文件夹中,则使用 './' 作为基路径。
我把这个放在任何调用另一个文件的顶部/附近。(我出于自己的方便使用了 define;它应该与变量一起工作,并且无需测试是否已经执行了它。)
请注意,在这两种情况下(根文件夹脚本和非根文件夹脚本),BASE_PATH 将包含尾部斜杠。至少在 Darwin(Mac OS X)上的 Apache 中,您可以 include(BASE_PATH.'/myfile.php'); 并且双斜杠不会导致任何问题,与 include(BASE_PATH.'myfile.php'); 产生相同的结果。
在 PHP 7 之后;
<?php
print dirname("/usr/local/lib", 2); # /usr
?>
在 PHP 7 之前;
<?php
print dirname(dirname("/usr/local/lib")); # /usr
# or
function dirname_with_levels($path, $levels = 1) {
while ($levels--) {
$path = dirname($path);
}
return $path;
}
print dirname_with_levels("/usr/local/lib", 2); # /usr
?>
--- 由 [email protected] 编辑 ---
您也可以查看 getcwd() 函数
--- 编辑结束 ---
一个不错的“当前目录”函数。
function current_dir()
{
$path = dirname($_SERVER[PHP_SELF]);
$position = strrpos($path,'/') + 1;
print substr($path,$position);
}
current_dir();
我发现这对很多东西都很有用!您可以使用目录名称作为模块名称来维护一个模块化的网站。至少我希望 PHP 开发人员能够将此添加到函数列表中!
如果有任何类似的东西,请告诉我。