views:

146

answers:

3

It's very odd,has anyone ever sum up with a conclusion yet?

Sometimes it checks the directory of the included file,too.

But sometimes not.

D:\test\1.php

<?php

include('sub\2.php');

D:\test\2.php

<?php

include('3.php');

Where 3.php is in the same dir as 2.php.

The above works,but why?The current directory should be D:\test,but it can still find 3.php,which is in D:\test\sub

More story(final)

About a year ago I met this problem,and then I ended up fixed it with the hardcoding like below:

Common.php:

if (file_exists("../../../Common/PHP/Config.inc"))
    include('../../../Common/PHP/Config.inc');

if (file_exists("../../Common/PHP/Config.inc"))
    include('../../Common/PHP/Config.inc');

if (file_exists("../Common/PHP/Config.inc"))
    include('../Common/PHP/Config.inc');

if (file_exists("Common/PHP/Config.inc"))
    include('Common/PHP/Config.inc');

Where Config.inc is in the same directory as Common.php

+1  A: 

It checks in the current path, and the directories listed in include_path.

You can run a phpinfo() to see your include path.

Pekka
This doesn't explain the problem I described:(
@user as far as I know, that's all there is to it. Please show some examples of when files get loaded, and when they don't.
Pekka
Will `getcwd()` change during a request if we don't explicitly change it(like `chdir()`).I'll give an example soon.
+1  A: 

Sometimes directory of the included file being current working directory and sometimes not
Current directory can be checked with getcwd()

Col. Shrapnel
Hey,I've updated my question,take a look:)
+1  A: 

If you take a look at the source code for php in main/fopen_wrappers.c you will find

/* check in calling scripts' current working directory as a fall back case
     */
    if (zend_is_executing(TSRMLS_C)) {
        char *exec_fname = zend_get_executed_filename(TSRMLS_C);
        int exec_fname_length = strlen(exec_fname);

        while ((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
        if (exec_fname && exec_fname[0] != '[' &&
            exec_fname_length > 0 &&
            exec_fname_length + 1 + filename_length + 1 < MAXPATHLEN) {
            memcpy(trypath, exec_fname, exec_fname_length + 1);
            memcpy(trypath+exec_fname_length + 1, filename, filename_length+1);
            actual_path = trypath;

This seems to be executed unconditionally and therefore will always make a file in the same path as the including/file-opening script accessible ...as the last choice after all possibilities specified in include_path. And only if you do not define a relative or absolute path in the include().

VolkerK
I dont seem to understand this code,are there some clues why sometimes it doesn't check the directory of the included file?
For `3.php` it first tests all locations given in the include\_path. A relative path given there, e.g. `include_path=.;..;lalala` would be relative to the current working directory (which is not changed by an include()). Only the last (additional) option is to look in the same directory as the including file is in. It "takes" the first `3.php` it can find. Is that your problem: php grabs another 3.php as you'd expect? Your other questions seem to indicate that...
VolkerK
My problem is sometimes it won't find 3.php,but I can't reproduce it easily.But it's in the same directory as the including file is in.Maybe when the `include` is in a function/method,I guess...
So, for clarification: It doesn't find _any_ 3.php in that case (not simply the "wrong" one but none at all). You can't reproduce it easily... hm. Does it happen on different servers/versions/configurations? Or is it like a heisenbug that happens on the _same machine_ with the _same code_ without touching anything that seems to be related?
VolkerK
Yes.It happens on different servers,I don't think it's a heisenbug
And you're sure the problem really boils down to the example you've provided in the question? (Sorry for me nagging, but I have the feeling there's something missing in the example and the question "The above works,but why?" as it is right now is answered ;-) )
VolkerK
@VolkerK ,this answers half the question(why it works),did you miss the **But sometimes not.** part in my post?:-)
Yes I did ;-) But since I have no further clue maybe there's some information you can add. E.g. "It happens on different servers" is something that should make you hit the "edit" button of your original question. Maybe you have noticed some/any pattern. The php version, something in the setting of include\_path on the servers, something remarkable about the "configure command" in the output of phpoinfo() on the different servers ...anything ;-) Because as you can see from all the answers so far this behaviour of php is not something too obvious.
VolkerK
I've provided the whole story(imo) here:http://stackoverflow.com/questions/2438356/is-debug-backtrace-safe-for-serious-usage-in-production-environment
Ok, that's the story of the hack you want add to your code. I meant the story of how you discovered _and explored_ the underlying problem. It may be just me but I've never seen code before that had to resort to debug\_backtrace() to get an include right ;-) Right now you're working on a hack around the problem. And as hacks go they come back at you at the least favorable time in the least favorable manner.
VolkerK
Yes,glad you've fully understood my problem(which can't be reproduced with ease:():-)Finally I manually changed the cwd by `chdir()` as a workaround,which is much safer/efficient(imo)..
Just one last question... which versions of php are involved? There have been some patches (and reverts) in the 4.3/5.0 branch that might affect whether php is executing the code I quoted above at all or not.
VolkerK
@VolkerK ,PHP 5.3.0.But I don't think it's related with OOP,because I noticed this before using classes,but I didn't stop to think about the reason at that time:-)
Each and every server involved is php 5.3? Ok, then I don't have a clue (and no I didn't mean oop, but zend\_stream\_open\_function ;-))
VolkerK
I've provided another story on this topic(final one),which is about a year ago..
+1 never knew that php would use the directory of the file that did the include as a last resort. I always thought the cwd and include_path were the only choices.
chris