views:

50

answers:

1

I've never seen anything like this.

File structure:

  • somefolder/base.php
  • includes/stuff.php
  • includes/constants.php

base.php:

<?php require("../includes/stuff.php"); ?>

stuff.php:

<?php 
   require("constants.php"); 
   echo "Welcome to stuff.php";
?>

constants.php:

<?php echo "IMPORTANT CONSTANTS DEFINED HERE!";  ?>

Result:

Welcome to stuff.php

Why doesn't it display the constant.php message?! I'll tell you what isn't the problem: it isn't the php code.

I started off with some complex files where the constants file was actually DEFINE()-ing some constants and for some reason the only the first few constants were working. I ended up disabling all the extraneous code including the DEFINE()'s and just having echo statements and this problem still kept staring me in the face. And by the way how could some of the defined constants make it through but not any echo's, regardless of the order of the code?

So I finally realized this was absurd and decided to just create some new files as a test. Those ones worked. Or maybe they didn't, I forget. Anyway I have had some measure of success by creating new files and experimenting with moving them around and copying code from one file to another but there hardly seems to be any rhyme or reason to it.

Wow, this just in: I got the constants.php file working under a different name but when I changed it to constants.php it stopped working! I tried clearing the cache/opening in a different browser and restarting the server but none of it helps. I feel like either I or my computer is on drugs. Gaaaahh!!!


EDIT

Aha. I left out one very important piece of information it looks like. One file I didn't mention.

  • somefolder/constants.php

That file was being included instead of the includes/constants.php. That's why I wasn't getting any missing file errors. That was totally confusing things! I expected that sub-includes happen before higher level includes so stuff.php would look for constants.php in it's own directory but I guess base.php includes stuff.php and THEN base.php does the include specified in stuff.php which means the include is relative to base.php. So absolute paths is the solution after all.

Additional edit:

Very interesting. I was still puzzled why it worked before when I simply changed the name of includes/constants.php (to constanza.php for example). It looks like file inclusion isn't so cut and dry. If there are two files with the same name it will prefer the one relative to the parent file doing the including. But if it has no choice it will do it relative to the child just fine.

+3  A: 

The path used in your includes are not relative to the file the includes are : they are relative to the include_path.

Which means that using relative paths with includes/requires will generally not do what you expect it to...


The solution that's generally used is to work with absolute paths ; this way, you are sure what gets included.

Of course, using absolute paths in your code is bad (it will work on one server, but not another, when your application is deployed to another path) ; so, the solution is to :

  • get the absolute path to the file you're in
  • use that, in addition to a relative path to another file, to include that file.


The full path to the file you're in can be obtained with __FILE__.

Which means the directory to the current file (the file that instruction is written in) can be obtained with dirname(__FILE__).

After that, it's only a matter of writing the correct paths.
For example, in stuff.php, you'd use :

require(dirname(__FILE__) . "/constants.php"); 

While, in base.php , you'd use :

require(dirname(__FILE__) . "/../includes/stuff.php");
Pascal MARTIN
`dirname(dirname(__FILE__))` will get you the parent directory. I tend to store just the applications' base directory and then use paths relative to that.
nikc
That sounds all very reasonable and good except I already got it working as long as the file isn't named constant.php. The files are getting included fine. There are no errors about missing files. I tried your suggestion, I also used $_SERVER['DOCUMENT_ROOT'] before. Neither one makes a difference.
Moss
I'm sorry. You were right. I didn't try absolute paths on everything just on base.php. See my edit note on my original question. I guess I needed a nights rest to make sense of this one. By the way, with PHP 5.3.0 `__DIR__` would be the simplest way to do what you suggest.
Moss