13

Does anyone know why my require_once () or die(); is not working. It's always shown the Fatal error instead of the error message that I key in into the die(). See below for my code:

require_once ('abc.php') or die("oops");

Error message display as below

"Fatal error: controller::require_once() [function.require]: Failed opening required '1' (include_path='....."

instead of the message ("oops") I key in.

Greg
  • 316,276
  • 54
  • 369
  • 333
Jin Yong
  • 42,698
  • 72
  • 141
  • 187

3 Answers3

30

or has a higher precedence than require/require_once. Therefore php evaluates

('abc.php') or die("oops")

before passing the result to require_once. Or takes two boolean operands. ('abc.php') evaluates to true therefore the whole expression is true and

require_once true;

is invoked. require_once takes a string, bool(true)->string => 1 =>

Failed opening required '1'
You don't need the or die(...) there. If the file can't be read require_once will stop the php instance anyway.
VolkerK
  • 95,432
  • 20
  • 163
  • 226
  • 4
    Brilliant answer. It needs to be stressed that require_once is not a function. It's a unary operator (or language construct, if you prefer), so is echo, new, include, etc. – Michał Niedźwiedzki Jul 22 '09 at 09:28
  • thank you! kinda sucks though that by adding the `die()` in a seemingly acceptable way, it throws an error that LOOKS like a failure to find the file and/or require it -or- an error in the included file... when really it is bad code at `require() or die()` – aequalsb May 28 '15 at 19:02
13

As include is a special language construct and not a function, it doesn’t need paranthesis for the paremeter list:

Because include() is a special language construct, parentheses are not needed around its argument. Take care when comparing return value.

In fact it has just one parameter and wrapping it in additional parenthesis doesn’t change anything:

1 ≡ (1) ≡ ((1)) ≡ (((1))) ≡ …

So your statement is identical to this (the paremter is just wrapped):

require_once (('abc.php') or die("oops"));

So we have a boolean expression as parameter that is either true or false. And that values have the string equivalent of "1" and "" respectively:

var_dump((string) true === "1");
var_dump((string) false === "");

That’s the reason why get this Failed opening required '1' error message.

But using parenthesis on the right place like this makes it work like you want it:

(@include_once 'abc.php') or die("oops");

Here 'abc.php' is clearly the parameter and the disjunction with die("oops") is performed on the return value of include_once. The @ operator is just to ignor the error message includ_once will throw if the file does not exist.

PS: print is also a special language construct and works the same way.

Gumbo
  • 643,351
  • 109
  • 780
  • 844
7

When evaluating:

require_once ('abc.php') or die("oops");

PHP evaluates 'OR die("oops")' first for some reason. to force PHP to evaluate the "require_once ('abc.php')" encolse it in brackets.

(require_once ('abc.php')) OR die("oops");

However, if "require" fails, PHP stops processing so use "include" instead (see https://stackoverflow.com/a/2418514/1704651). Also, the @ symbol before include_once supresses the error message from MySQL so only the "oops" is output.

(@include_once ('abc.php')) OR die("oops");

Works as expected.

Source: My own frustration and https://bugs.php.net/bug.php?id=22342

Community
  • 1
  • 1
n00dle
  • 81
  • 2
  • 4
  • include or die is what I used also. It's helpful for when you need to clarify why a file is missing (e.g. a config file you needed to define) – jocull Feb 03 '13 at 01:11
  • Putting @ before include is probably a bad idea. @include causes ALL errors in the included file, and any files included by that file, to be suppressed which makes troubleshooting and error handling a nightmare. – Gregor Macgregor Mar 25 '16 at 13:54