views:

2173

answers:

4

Hi,

I was writing an web app in php, when i encountered a strange situation. I wish to clear my confusion. To illustrate my problem, consider a web app of this structure:

/
    index.php
    f1/
        f1.php
    f2/
        f2.php

contents of these files:

index.php:

<?php require_once("f1/f1.php"); ?>

f1.php:

<?php require_once("../f2/f2.php"); ?>

f2.php: blank

now when I try to open index.php in my browser I get this error:

Warning: require_once(../f2/f2.php) [function.require-once]: 
failed to open stream: No such file or directory in /var/www/reqtest/f1/f1.php on line 2
Fatal error: require_once() [function.require]: 
Failed opening required '../f2/f2.php' (include_path='.:/usr/share/php:/usr/share/pear') in /var/www/reqtest/f1/f1.php on line 2

Is there something obvious I'm missing? how do include paths work in php?


Before I asked this question, I attempted to experiment and find out. I set up another test, like so:

/
    index.php
    f1/
        f1.php
        f2.php

index.php:

<?php require_once("f1/f1.php"); ?>

f1.php:

<?php require_once("f2.php"); ?>

f2.php: blank

To my surprise (and utter confusion), this worked out fine!

so what is the secret behind the path resolution?

Thanks

PS I saw this question, but it still does not answer the second case that i've stated here.

A: 

Normaly in you old structure

<?php require_once("f2/f2.php"); ?>

instead of

<?php require_once("../f2/f2.php"); ?>

should work. As far as i know php takes the paths from the initial script

I know. What I really want to know is why the second case is not failing. Its not a problem, its an itch :)
Here Be Wolves
A: 

When you open index.php, working dir is set to the folder this file resides in. And inside insluded f1.php this working dir does not change.

You can include files by using their absolute paths, relative to the current included file like this:

require_once(dirname(__FILE__).'/../../test/file.php')

But better consider using an autoloader if these files contain classes.

FractalizeR
What about the second case? why is that working?
Here Be Wolves
Try to add 'echo getcwd();' to your scripts to see, how and if current working directory changes. http://php.net/manual/en/function.getcwd.php - comments here says, that it's behavior changed from PHP4 to PHP5 for example.
FractalizeR
A: 

It sounds like your server has the open_basedir setting enabled in the PHP configuration. This makes it impossible to include (and open) files in folders above your in the directory structur (i.e., you can't use ../ to go up in the folder structure).

Emil Vikström
in my server, open_basedir setting has "no value". What would that mean?
Here Be Wolves
no value = disabled
Karsten
@Karsten which means that "../" is allowed, right?
Here Be Wolves
+1  A: 

If you include another file, the working directory remains where the including file is.

Your examples are working as intended.

Edit: The second example works because . (actual directory) is in your include path (see your error message).

Edit2: In your second example, the key point of your interest is this line:

<?php require_once("f2.php"); ?>

At first it will look in the current working dir (/var/www/req_path_test), but does not find f2.php.

As fallback, it will try to find f2.php in your include_path ('.:/usr/share/php:/usr/share/pear'), starting with '.' (which is relative to the actual file, not the including one).

So './f2.php' works and the require does not fail.

Karsten
I tried echo:ing getcwd() in index.php and f1.php. Output from both places is `/var/www/req_path_test`so "." being in the include path would probably mean "/var/www/req_path_test" is in the include path.
Here Be Wolves
and in support of this fact, I tried `require_once("f2/f2.php")`. It worked when I open up index.php, but not when I open f1/f1.php.
Here Be Wolves
I updated my answer to cover your comment.
Karsten
hmm, that seems to be the most appropriate explanation.. can you please cite any sources?
Here Be Wolves