2

使用file_put_contents在相对位置的文件夹中创建和填充文件。

注意到与包含路径和文件创建相关的一些奇怪的怪癖。

简短版本:查看迭代 2 和迭代 3。为什么后者工作而前者失败?

迭代 1

file_put_contents('../../public/remixes/screenshots/test.txt', $data);

这工作得很好。

迭代 2

但是,我在这个模块的“根”中有公共目录,并且想使用预先设置的包含路径更直接地引用它。例如:

echo(get_include_path()); // this outputs "../../"
file_put_contents('public/remixes/screenshots/test.txt', $data, FILE_USE_INCLUDE_PATH);

错误:“无法打开流:没有这样的文件或目录”

迭代 3

很好,PHP 包含路径很不稳定,所以让我们做一些奇怪的事情,看看会发生什么。我会先尝试使用fopen来实际创建文件。

fopen('../../public/remixes/screenshots/test.txt', 'w');
file_put_contents('public/remixes/screenshots/test.txt', $data, FILE_USE_INCLUDE_PATH);

这又有效了... WAT?

迭代 4

有趣的; 我可以先做一个 fopen 但我希望它也使用包含路径:

fopen('public/remixes/screenshots/test.txt', 'w', 1);
file_put_contents('public/remixes/screenshots/test.txt', $data, FILE_USE_INCLUDE_PATH);

这会产生两个“无法打开流”错误。情况越来越糟糕。

迭代 5

我将自己保留包含路径“魔术”并直接用它构建路径

file_put_contents(get_include_path().'public/remixes/screenshots/test.txt', $data);

这行得通,是我能得到的最好的。

结论

我想知道为什么迭代 2 失败而迭代 3 成功。

迭代 4 暗示这是 fopen 的问题(因为 file_put_contents 显然只是 fopen / fwrite / fclose 的包装器)

想法?

4

1 回答 1

0

刚刚花了一些时间检查PHP 源代码

fopen 解析到/main/streams/streams.c的第 2007 行

我会为您省去达到这一点的堆栈。

代码的以下部分(第 2026 行)处理 FILE_USE_INCLUDE_PATH 参数:

if (options & USE_PATH) {
    resolved_path = zend_resolve_path(path, strlen(path) TSRMLS_CC);
    if (resolved_path) {
        path = resolved_path;
        /* we've found this file, don't re-check include_path or run realpath */
        options |= STREAM_ASSUME_REALPATH;
        options &= ~USE_PATH;
    }
}

事实上,正如 Passerby 在他的评论中指出的那样,这种逻辑将尝试解决路径。如果路径正确解析(到现有文件),则原始路径字符串将替换为“包含化”路径。

如果包含化路径不指向现有文件,则原始路径不会被替换,并且 include_path 将被完全忽略。

该文档并未明确表明这是预期的行为,但正如对该答案的评论中所指出的那样,这并不是那么疯狂。

谜团已揭开。

于 2013-03-14T05:57:48.320 回答