如何让PHP、Symlinks和__FILE__一起很好地工作?

4urapxun  于 2023-03-28  发布在  PHP
关注(0)|答案(8)|浏览(140)

在localhost上。我有以下目录结构:
/share/www/trunk/wp-content/plugins/otherfolders
/share/www/portfolio/wp-content/symlink
其中symlink/trunk/.../plugins/的符号链接。基本上,这是因为我需要测试多个WordPress安装并设置它们,但我不想到处移动插件并复制粘贴它们。
然而,有时我需要爬上目录树来包含配置文件:

$root = dirname(dirname(dirname(dirname(__FILE__))));
      if (file_exists($root.'/wp-load.php')) {
          // WP 2.6
          require_once($root.'/wp-load.php');
      }

文件夹始终解析为:
/share/www/trunk
即使插件正在执行并包含在
/share/www/portfolio/ .
在PHP中,是否可以从执行到/share/www/trunk/.../plugins目录的符号链接中的脚本中包含share/www/portfolio目录中的文件?
虽然这个问题只发生在我的测试服务器上,但我希望有一个安全的可分发解决方案,因此爬上一个额外的级别不是一个选项

zlhcx6iw

zlhcx6iw1#

我在您的代码中看到的问题是__FILE__自动解析符号链接。
摘自PHP Manual on Magic Constants
...从PHP 4.0.2开始,__FILE__总是包含一个符号链接解析的绝对路径...
您可以尝试使用$_SERVER["SCRIPT_FILENAME"]

$root = realpath(dirname(dirname(dirname(dirname($_SERVER["SCRIPT_FILENAME"])))));
  if (file_exists($root.'/wp-load.php')) {
      // WP 2.6
      require_once($root.'/wp-load.php');
  }

请注意,我将realpath()函数添加到根目录。根据您的设置,您可能需要也可能不需要它。
编辑:使用$_SERVER["SCRIPT_FILENAME"]代替$_SERVER["PHP_SELF"]作为文件系统路径。

ldfqzlk8

ldfqzlk82#

下面是解决这个问题的方法:https://github.com/logical-and/symlink-detective

$root = dirname(dirname(dirname(dirname(__FILE__))));
  if (file_exists(SymlinkDetective::detectPath($root.'/wp-load.php'))) {
      // WP 2.6
      require_once(SymlinkDetective::detectPath($root.'/wp-load.php'));
  }

或者你可以试试

try {
  $root = dirname(dirname(dirname(dirname(__FILE__))));
  require_once SymlinkDetective::detectPath($root.'/wp-load.php', '', 
    false /* this would throw an exception if file doesn't exists */);
}
catch (Exception $e) {
  // nothing to do if file doesn't exists
}
bxpogfeg

bxpogfeg3#

你可以使用这个代码片段来获取一个没有解析符号链接的路径。如果你没有bash,你可以使用一个不同的命令,但是它在linux环境下工作。
我确实认为php解析FILE中的符号链接是一种弊端,因为没有办法通过符号链接获得路径。否则我们可以很容易地使用realpath获得它。
好吧。

<?php
$output = array();
exec('pwd', &$output);
define('__LINK__', $output[0].substr(__FILE__, strpos(__FILE__, DIRECTORY_SEPARATOR)));
?>
pbpqsu0x

pbpqsu0x4#

在某些情况下,可以更改工作目录并使用getenv('PWD '):

$root = dirname(dirname(dirname(getenv('PWD'))));
if (file_exists($root.'/wp-load.php')) {
    // WP 2.6
    require_once($root.'/wp-load.php');
}

并在运行此代码之前更改工作目录:

cd /var/www/wp-content/themes/twenty_twelve/ && php script.php
7xllpg7q

7xllpg7q5#

如果我试图解决这个问题,我会沿着路径位分割__FILE__,并为每个路径位创建一个SplFileInfo,用isDirisLink进行测试,然后尝试确定如何处理路径的重建,一旦它与预期的不同,那么你就可以从正确的目录中拉取。(如果您更倾向于程序类型,则有is_diris_link
话虽如此,我认为你已经不符合这个解决方案。也许工具足够聪明,可以为你做这件事。试着比较getRealPathgetPath的结果?getRealPath明确表示它可以解析符号链接,而getPath没有明确表示。
即使这样,这种嗅探在客户端站点上也可能不安全,这取决于主机是谁。我见过一些非常 * 创造性 * 的共享主机文件系统设置。你可以在php_uname中添加一个检查,并提取机器的主机名,如果它不是你的开发机器,就不要做额外的工作。

6yt4nkrj

6yt4nkrj6#

PHP解释器在处理符号链接之前会解析符号链接。你可以自己用readlink函数来完成这个任务。PHP解析链接是因为它对*_once函数和代码缓存(如APC,Xcache等)更有效。
你可能需要的是另一种方法来找到一个特定的安装存储它的文件。我建议使用{$_SERVER['DOCUMENT_ROOT']}/wp-content/wp-load.php假设/share/www/portfolio是文档根。

tyg4sfes

tyg4sfes7#

没有一个建议的解决方案能在所有这些环境中工作,CLI,PHPUNIT,WebServer。
最后,我为项目的根定义了一个变量。

define( 'ABSPATH', __DIR__ . '/' );

然后在我的符号链接插件中使用它。

这可能不是你总是可以做的,但如果你的用例可以,它肯定在任何地方都可以工作!

例如:

require_once(ABSPATH .'/wp-load.php');

如果你正在使用WordPress,这是已经定义,你可以只使用它!

c2e8gylq

c2e8gylq8#

如果有人因为在符号链接的文件(symlinked)中使用__DIR__而对此感到困惑,请将其转换为DOT '.'相对变量。
例如:

require_once __DIR__ . '/vendor/autoload.php';

变成

require_once './vendor/autoload.php';

相关问题