使用包含路径时,为什么file_put_contents和fopen无法创建?

时间:2013-03-14 04:28:39

标签: php fopen

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

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

简短版本:查看迭代2和迭代3.为什么后者在前者失败时有效?

迭代1

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

这很好用。

迭代2

但是,我在此模块的“root”中有公共目录,并希望使用预设的包含路径更直接地引用它。例如:

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,但我也希望它也能使用include路径:

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);

这是有效的,也是我能得到的最好的。

结论

我想知道为什么Iteration 2在Iteration 3成功时失败了。

迭代4意味着fopen存在问题(因为file_put_contents显然只是fopen / fwrite / fclose的包装器)

思想?

1 个答案:

答案 0 :(得分:0)

花了一些时间检查the PHP source

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-ified”路径。

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

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

神秘解决了。