你如何让 PHP、Symlinks 和 __FILE__ 很好地协同工作?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3221771/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 09:02:58  来源:igfitidea点击:

How do you get PHP, Symlinks and __FILE__ to work together nicely?

phplinuxsymlink

提问by Aaron Harun

On localhost. I have the following directory structure:

在本地主机上。我有以下目录结构:

/share/www/trunk/wp-content/plugins/otherfolders

/share/www/trunk/wp-content/plugins/otherfolders

/share/www/portfolio/wp-content/symlink

/share/www/portfolio/wp-content/symlink

Where symlinkis a symbolic link to /trunk/.../plugins/. Basically, this is because I need to test multiple WordPress installs and set them up, but I don't want to have to move plugins around and copy and paste them everywhere.

symlink到 的符号链接在哪里/trunk/.../plugins/?基本上,这是因为我需要测试多个 WordPress 安装并设置它们,但我不想移动插件并将它们复制并粘贴到任何地方。

However, sometimes I need to crawl up the directory tree to include a config file:

但是,有时我需要爬上目录树以包含配置文件:

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

The folder always resolves to:

该文件夹始终解析为:

/share/www/trunk

/share/www/trunk

Even when the plugin is being executed and included in

即使插件正在执行并包含在

/share/www/portfolio/.

/share/www/portfolio/.

Is it possible in PHP to include files in the share/www/portfoliodirectory from a script executing in a symlink to the /share/www/trunk/.../pluginsdirectory?

是否可以在 PHP 中将share/www/portfolio文件从在符号链接中执行的脚本包含在/share/www/trunk/.../plugins目录中?

While this problem only happens on my test server, I'd like to have a safely distributable solution so crawling up an extra level is not an option.

虽然这个问题只发生在我的测试服务器上,但我想要一个安全的可分发解决方案,所以爬上一个额外的级别不是一个选项

采纳答案by pferate

The problem that I see with your code is that __FILE__resolves symlinks automatically.

我在您的代码中看到的问题是__FILE__自动解析符号链接。

From the PHP Manual on Magic Constants

来自魔法常量的 PHP 手册

... Since PHP 4.0.2, __FILE__always contains an absolute path with symlinks resolved ...

... 自 PHP 4.0.2 起,__FILE__始终包含已解析符号链接的绝对路径 ...

You can try using $_SERVER["SCRIPT_FILENAME"]instead.

您可以尝试使用$_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');
  }

Note that I added the realpath()function to the root directory. Depending on your setup, you may or may not need it.

请注意,我将realpath()函数添加到根目录。根据您的设置,您可能需要也可能不需要它。

EDIT: Use $_SERVER["SCRIPT_FILENAME"]instead of $_SERVER["PHP_SELF"]for the file system path.

编辑:用于$_SERVER["SCRIPT_FILENAME"]代替$_SERVER["PHP_SELF"]文件系统路径。

回答by Dag

You can use this code snippet to get a path where symlinks are not resolved. If you don't have bash available, there's probably a different command you can use, but it works on linux enviroments.

您可以使用此代码片段获取未解析符号链接的路径。如果您没有可用的 bash,您可能可以使用不同的命令,但它适用于 linux 环境。

I do think it's a malpractice that php resolves symlinks in FILE, since there's no way to get the path with symlinks. Otherwise we could easily get it using realpath.

我确实认为 php 解析FILE 中的符号链接是一种不当行为,因为无法通过符号链接获取路径。否则我们可以使用 realpath 轻松获得它。

Oh well.

那好吧。

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

回答by AndreyP

In some case its possible to change working dir and use getenv('PWD'):

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

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

And change working directory before run this code:

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

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

回答by And

Here is the solution to that issue: https://github.com/logical-and/symlink-detective

这是该问题的解决方案: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'));
  }

or you can try that

或者你可以试试

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
}

回答by jmz

The PHP interpreter resolves symlinks before it processes them. You can do this yourself with the readlinkfunction. PHP resolves the links because it's more efficient for *_oncefunctions and code caches like APC, Xcache etc.

PHP 解释器在处理符号链接之前先解析它们。您可以使用该readlink功能自己完成此操作。PHP 解析链接是因为它对*_onceAPC、Xcache 等函数和代码缓存更有效。

What you propably need is another way to find where a particular installation stores it's files. I'd recommend using {$_SERVER['DOCUMENT_ROOT']}/wp-content/wp-load.phpassuming /share/www/portfoliois the document root.

您可能需要的是另一种方法来查找特定安装存储文件的位置。我建议使用{$_SERVER['DOCUMENT_ROOT']}/wp-content/wp-load.php假设/share/www/portfolio是文档根目录。

回答by Charles

If I were trying to solve this, I'd split __FILE__along the path bits and create a SplFileInfofor each along the way, test with isDirand isLink, then try to determine how to handle reconstruction of the path once it's known to be different than expected so you can pull from the right directory. (If you're more of a procedural type, there's is_dirand is_link.)

如果我试图解决这个问题,我会__FILE__沿着路径位拆分并沿途为每个位创建一个SplFileInfo,使用isDirisLink 进行测试,然后尝试确定如何处理路径的重建,一旦它已知不同于预期,因此您可以从正确的目录中提取。(如果您更喜欢程序类型,则有is_diris_link。)

That being said, I think you've already disqualified this solution. Maybe the tools are smart enough to do it for you. Try comparing the result of getRealPathto getPath? getRealPath expressly says that it resolves symlinks, while getPath doesn't expressly say that.

话虽如此,我认为您已经取消了此解决方案的资格。也许这些工具足够聪明,可以为你做这件事。尝试将getRealPath的结果与getPath进行比较?getRealPath 明确表示它解析符号链接,而 getPath 没有明确表示。

Even then, this sniffing might not be safe on client sites, depending on who the host is. I've seen some pretty creativeshared hosting filesystem setups. You could add a check to php_unameand pull out the hostname of the machine, and if it isn't your dev box, don't do the extra work.

即便如此,这种嗅探在客户端站点上可能并不安全,具体取决于主机是谁。我见过一些非常有创意的共享托管文件系统设置。您可以在php_uname 中添加一个检查并提取机器的主机名,如果它不是您的开发框,请不要做额外的工作。