1

start.php

<?php
if(file_exists('/config.php')) require_once('/config.php');
echo TEST;
?>

config.php

<?php
define('TEST','Hamsters');
?>

I have Windows XP + XAMPP with PHP Version 5.3.8.
If I run start.php it gives me this error:

Notice: Use of undefined constant TEST - assumed 'TEST' in C:\programs\xampp\htdocs\start.php on line 3

Now I modify start.php to the following and he gives me my Hamsters:

<?php
require_once('/config.php');
echo TEST;
?>

How can file_exists() say the file not exist but without the condition still be able to require_once() the file that claimed non-existent?

totymedli
  • 29,531
  • 22
  • 131
  • 165
  • 1
    Wow, this reminds me from stories of the bible like giving birth without being pregnant. Rest assured, when PHP requires a file, it does exist. Just by definition. So you should more wonder about the fact *you think* it would be non-existent. – hakre Aug 24 '13 at 21:30
  • oh and in case you didn't know, there is something called include_path, it's a setting: http://php.net/include_path – hakre Aug 24 '13 at 21:31
  • Probably because of the leading `/`. If your files are in C:\Web\path\to\website\ then including /config.php will include C:\config.php. – Sverri M. Olsen Aug 24 '13 at 21:40

3 Answers3

2

Making a require (or include) conditional is something you should not do at all:

if (file_exists('/config.php')) {
  require_once('/config.php');
}

Instead either take include if it's not a must, or take require if it's a must. See as well:

Wrapping include/require into conditions make those complicated and as includes are often related to program flow you really want to keep it simple.

Additionally some optimizations you might want to make use of later on are not possible with conditional includes.

and in your case, I wonder why you actually check for a file existence. Instead of require_once you most certainly meant include_once, the if is superfluous:

include_once('/config.php');
Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836
  • Than what about this question: [How to include only if file exists](http://stackoverflow.com/questions/4604965)? – totymedli Aug 24 '13 at 21:45
  • Well what should be about that question? It technically gives the right answer, however, only something can be done that way it does not mean you *should* do it that way. I mean it's the internet. You find enough lunatics to think something is cool or good enough (or not even awesome as it's called nowadays. everything is awesome). really, include does not break if the file does not exist, whoever answered that question must have missed to point that out clearly. – hakre Aug 24 '13 at 21:47
  • Ok, I understand what you said. Your answer is helpful but not answer the question. – totymedli Aug 24 '13 at 21:53
  • Well, the file does exist *in the include path*, however when you use `file_exist` you don't search for that file *in the include path*. That's what I already commented above. And the answer is still valid. Just use `include_once` and it will test for that file in the include path and if it exists, will include. If it doesn't, will leave a warning. – hakre Aug 24 '13 at 21:55
1

Here's what I think it is.

require_once tries its very best to find the file, and if it finds a file in the working directory or the calling script's directory, it will treat that directory as the root for the purpose of interpreting a leading slash.

file_exists is tighter: it looks for that absolute filesystem path and reports it not found.

a.php:

echo 'a';

main script:

require_once ('/a.php');
echo '<br/>',file_exists('/a.php') ? 'exists' : 'not';

yields:

a
not

to confirm:

require_once ('./a.php');
echo '<br/>',file_exists('./a.php') ? 'exists' : 'not';

yields:

a
exists
Peter Rowntree
  • 601
  • 5
  • 7
  • @totymedli: everything you say in your 'answer' is trivially true. I read the manual before posting and assumed you had too. It also explicitly says: "If a path is defined — whether absolute (starting with a drive letter or \ on Windows, or / on Unix/Linux systems) or relative to the current directory (starting with . or ..) — the include_path will be ignored altogether." The only thing interesting here is that require_once finally ignored the leading slash. – Peter Rowntree Aug 24 '13 at 23:44
0

The problem was that /config.php actually means C:/config.php.

File_exists() only checks the actual file or folder if it is exist and if not it will give a false.
Require_once() does some more. According to the PHP manual this function is almost identical to require() that is almost identical to include(). The non identical parts are not important in our case. What is important, that the manual says about include:

Files are included based on the file path given or, if none is given, the include_path specified. If the file isn't found in the include_path, include will finally check in the calling script's own directory and the current working directory before failing.

Because config.php was in the same directory where start.php was, after require_once() found out that config.php is not in C:/ it searched and found it in the directory where start.php called him. File_exists() does not do this search thus it returns false and require_once() can't be called.

If I copy my config.php file to C:/ it will work with the file_exists() way too.

totymedli
  • 29,531
  • 22
  • 131
  • 165