0

Here's a tiny section of php code:

if(file_exists('question.txt')) print("File exists<br>");
else print("File does not exist<br>");
$handle = fopen('question.txt', 'r') || die("Cannot open file");
print("fopen returns handle=[$handle]");
fclose($handle);
die("all done");

The result is

File exists
fopen returns handle=[1]
( ! ) Warning: fclose() expects parameter 1 to be resource, bool given in C:\wamp64\www\htdocs\NewCompany\ProofOfLearn\Development\test.php on line 6
Call Stack
#   Time    Memory  Function    Location
1   0.0002  362584  {main}( )   ...\test.php:0
2   0.0003  362696  fclose( $fp = TRUE )    ...\test.php:6
all done

In other words, fopen is returning TRUE, which is impossible

Of all the logs, only php.error.log shows an error, and it doesn't help

[16-Feb-2022 03:00:52 UTC] PHP Warning:  fclose() expects parameter 1 to be resource, bool given in C:\wamp64\www\htdocs\NewCompany\ProofOfLearn\Development\test.php on line 6
[16-Feb-2022 03:00:52 UTC] PHP Stack trace:
[16-Feb-2022 03:00:52 UTC] PHP   1. {main}() C:\wamp64\www\htdocs\NewCompany\ProofOfLearn\Development\test.php:0
[16-Feb-2022 03:00:52 UTC] PHP   2. fclose($fp = TRUE) C:\wamp64\www\htdocs\NewCompany\ProofOfLearn\Development\test.php:6

And unlike many newbies with questions, I've been programming for 66 years, and this is the first time I've been stumped.

1 Answer 1

1

This is happening because you are actually assigning $handle to the full result of your "OR" statement:

$handle = fopen('question.txt', 'r') || die("Cannot open file");
          \___________________________________________________/

Your $handle variable isn't just being assigned to the result of fopen, rather it's getting the boolean value of foo || bar. Make sense?

You need to assign the return value from fopen on its own, perhaps like this:

if(!$handle = fopen('question.txt', 'r')) {
    die("Cannot open file");
}
Sign up to request clarification or add additional context in comments.

5 Comments

You are correct. Thank you. That fixes the problem. But one thing about the solution puzzles me: I have used statements of the form if(expr1 || expr2) {...} very often in the past, confident that if expr1 were true then expr2 would NOT be evaluated. And I always assumed that !false is true. But here fopen is giving a result which is !false, and nevertheless expr2 is somehow affecting the result. So, is my assumption true about some languages but not true of php?
expr1 is returning a resource to you, which is truthy. As soon as you add the OR || with a second expression, you get that file handle resources cast to a boolean value.expr2 is still not being evaluated, if it was your script would die!
See here for a simpler example: 3v4l.org/U3Kc1. The second expression is definitely not being evaluated, or else you'd see the die message. The first expression is truthy (returning a json encoded string) and so that immediately means a true value comes back from the overall "OR" statement.
I may not be explaining this very well. Your expr2 is not being evaluated, it is not affecting the result. The first 'truthy' result in an "OR" statement results in a true value right away, and stops evaluating any further expressions.
That makes sense. I just had the right paren in the wrong place. I should have written if($handle = fopen('question.txt', 'r')) || die("Cannot open file");

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.