readlink()仅原样返回软链接存储的字符串路径,不解析、不归一化、不检查目标存在性;需结合dirname()和realpath()才能获取真实绝对路径,且二者功能不可替代。

直接说结论:readlink() 只返回软链接里存的原始字符串路径,不解析、不归一化、不检查目标是否存在——它就是个“读配置项”的函数,不是“找文件”的函数。
为什么 readlink() 返回的是相对路径,但你想要绝对路径
软链接内容本身是字符串,比如 ../shared/config.php 或 ./current/index.php,readlink() 原样吐出来,不做任何路径计算。它不知道自己在哪,也不关心目标是否有效。
- 想得到真实磁盘路径,得先用
dirname($link_path)拿到链接所在目录 - 再把
readlink($link_path)的结果拼上去,形成临时路径(如/var/www/current/../shared/config.php) - 最后用
realpath()归一化——注意:若中间某级目录权限不足或不存在,realpath()会直接返回false
readlink() 失败时返回 false,但链接明明存在
常见原因不是函数坏了,而是参数不满足前提:
-
$link_path不是符号链接(is_link($link_path)应为true) - 路径不存在(
file_exists($link_path)为false),readlink()会触发警告并返回false - PHP 运行用户对该路径无读权限(Linux 下表现为
EACCES错误) - Windows 系统下该函数不可用(截至 PHP 7.4,官方仍未实现)
别拿 realpath() 替代 readlink(),它们解决的问题完全不同
realpath() 是“顺着链接走到底”,遇到断链、权限问题、循环链接都会失败;readlink() 是“只看一眼链接里写了啥”,哪怕目标删了、权限不对、甚至根本是无效路径,只要链接文件本身可读,它就照常返回字符串。
立即学习“PHP免费学习笔记(深入)”;
- 你想确认软链接是否被篡改?用
readlink()对比原始值 - 你想加载链接指向的配置文件?先
readlink(),再realpath(),再file_exists()和is_readable() - 直接对软链接路径调
file_get_contents(),行为等同于读目标文件——如果目标不存在,就报错;而你可能只想知道“链接指哪”
真正容易被忽略的点:软链接路径里的 .. 和 . 是相对于链接自身所在目录计算的,不是相对于当前工作目录(getcwd())。写路径解析逻辑时,必须用 dirname($link_path) 而不是 __DIR__ 或 getcwd() 做拼接起点。



















