18

I have a kind of 'basics' question about php. In the example code for fgets, it has this snippet as an example of reading through a file's contents:

while (($buffer = fgets($handle, 4096)) !== false) {
    echo $buffer;
}

How is it that the statement ($buffer = fgets($handle, 4096)) can have a value? Is it a kind of assignment+evaluation of $buffer? I mean, how does it get its value? Is there a name for this? I notice its using strict comparison, so do all assignments evaluate to a boolean true or false?

If I wanted to write a function that could be treated this way, do I have to do anything special, other than return false on certain conditions?

user151841
  • 17,377
  • 29
  • 109
  • 171

7 Answers7

21

In PHP an assignment is an expression, i.e. it returns a value. $buffer = fgets($handle, 4096) will first assign the value to $buffer and then return the assigned value.

So, basically, you could write:

$buffer = fgets($handle, 4096);
while ($buffer !== false) {
    echo $buffer;

    $buffer = fgets($handle, 4096);
}

Here you would have the assignment on a separate line. Because in that case you need to duplicate the assignment, the assignment in the loop condition is preferred.

PS: The most common example for an assignment in a while loop is probably fetching rows from mysql:

while ($row = mysql_fetch_assoc($result)) {
    echo $row['firstname'] . ' ' . $row['lastname'];
}
NikiC
  • 100,734
  • 37
  • 191
  • 225
  • So in the example code snippet, the reason it works is because `fgets` could return `false`, which would assign `false` as the value of `$buffer`, which in turn would be the result of evaluating the assignment? – user151841 May 09 '11 at 18:04
  • 1
    @user151841: Yep, that's exactly the reason ;) – NikiC May 09 '11 at 18:05
  • Also note that the strict comparison in your case has more to do with the function result than with the loop condition. It could be that you get a result from in this case the `fgets` function that could be interpreted as false (an empty string for example), where you might only want to check if it returns the boolean false. – Rik Schaaf Oct 23 '17 at 09:07
5

When you do an assignment in PHP, the assignment returns the value that was assigned. This allows you to evaluate the assignment in conditionals or loops or other expressions.

var_dump ($var = 'test');

This results in 'test' being assigned to $var, and also the newly assigned value of $var being displayed.

The above code example does an assignment and a test in the same operation, a kind of programmer's shorthand that's quite common. fgets() returns a line from an open file, or false if there isn't a line to return. You could do

while ($buffer !== false) {
    echo $buffer;
    $buffer = fgets($handle, 4096);
}

but you would of course have to set buffer to a non-false value before entering the loop (by doing a fgets before the loop, or assigning a value that won't get displayed but isn't false such as an empty string).

Or you could simplify even further:

while ($buffer = fgets($handle, 4096) !== false) {
    echo $buffer;
}
GordonM
  • 31,179
  • 15
  • 87
  • 129
  • Stumbled upon that answer and wanted to add: according to the Operator Precedence (https://www.php.net/manual/en/language.operators.precedence.php#language.operators.precedence), `!==` binds stronger than `=`, so in the last example, `$buffer` would become `true` if `fgets` is successful instead of the returned string. It should therefore be `($buffer = fgets($handle, 4096)) !== false` like in the OP. – Johannes H. Aug 22 '21 at 21:24
3

Because FALSE is returned for either "no more data" or "error," the while loop will just execute until it must stop.

A more clear way of writing that would be:

$buffer = fgets($handle, 4096);
while( $buffer !== false )
{
    echo $buffer;
    $buffer = fgets($handle, 4096);
}

But that's nowhere near as clean.

rockerest
  • 10,412
  • 3
  • 37
  • 67
1

In the context of a condition (eg. while or if), (x = y) is both an assignment and an expression. It returns the value that's being assigned.

You don't need to do anything special to your functions to allow them to be used like this - it's a feature of the language.

RichieHindle
  • 272,464
  • 47
  • 358
  • 399
1

It evaulates while fgets is not returning false. Assigment in brackets returns value that has been assigned. So ($buffer = fgets($handle, 4096)) is returning fgets value.

If there is no more data to read in the file pointer, then FALSE is returned.

Simple example:

$a = 'a';
$b = 'b';
echo ($a = $b);

Returns

b
Robik
  • 6,047
  • 4
  • 31
  • 41
1

Per the documentation, and what others have already said, it doesn't alwasy return boolean. It only returns boolean when it's done or there's an error.

From PHP Manual:

Returns a string of up to length - 1 bytes read from the file pointed to by handle.

If an error occurs, returns FALSE.

So, anyway, there's nothing special about how a method like this works, you could write your own method this way:

function increment($num) {
    if( $num < 10 ) { return ++$num; }
    return false;
}

$i=-1;
while( ($i = increment($i)) !== false ) {
    echo( $i."<br />" );
}
Kevin Nelson
  • 7,613
  • 4
  • 31
  • 42
0

The === operator not only checks if a function returns something that might be seen as false (like 0, NULL, etc.) It really checks against the boolean false as you can read here: http://de.php.net/manual/en/language.operators.comparison.php

2ndkauboy
  • 9,302
  • 3
  • 31
  • 65