php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #76500 fputcsv() is ignoring the value FALSE
Submitted: 2018-06-19 14:32 UTC Modified: 2018-06-19 17:07 UTC
Votes:1
Avg. Score:1.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: thomas at landauer dot at Assigned:
Status: Closed Package: Filesystem function related
PHP Version: 7.1.18 OS: Linux Mint
Private report: No CVE-ID: None
 [2018-06-19 14:32 UTC] thomas at landauer dot at
Description:
------------
When a data value is `false`, fputcsv() just omits it - instead of exporting it as `0`.

Test script:
---------------
$data = array('name'=>'foo', 'active'=>false);
$f = fopen('php://memory', 'r+');
fputcsv($f, $data);
rewind($f);
echo stream_get_contents($f);

Expected result:
----------------
foo,0

Actual result:
--------------
foo,

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-06-19 14:41 UTC] haseeb dot basil at gmail dot com
This doesn't sound like a bug, it is possible for false to be interpreted as null rather than 0. You can probably do something like this to get 0(adjust according to your actual code):

Script:
---------------------
$data = array('name'=>'foo', 'active'=> (int)false);
$f = fopen('php://memory', 'r+');
fputcsv($f, $data);
rewind($f);
echo stream_get_contents($f);

Result:
--------------------------
foo,0
 [2018-06-19 14:57 UTC] cmb@php.net
-Status: Open +Status: Verified -Type: Bug +Type: Documentation Problem -Assigned To: +Assigned To: cmb
 [2018-06-19 14:57 UTC] cmb@php.net
Indeed, this is not a bug, since (string)false === ''.
The docs could be improved in this regard, though.
 [2018-06-19 15:02 UTC] cmb@php.net
Automatic comment from SVN on behalf of cmb
Revision: http://svn.php.net/viewvc/?view=revision&revision=345171
Log: Fix #76500: fputcsv() is ignoring the value FALSE
 [2018-06-19 15:03 UTC] cmb@php.net
-Status: Verified +Status: Closed
 [2018-06-19 15:03 UTC] cmb@php.net
This bug has been fixed in the documentation's XML sources. Since the
online and downloadable versions of the documentation need some time
to get updated, we would like to ask you to be a bit patient.

Thank you for the report, and for helping us make our documentation better.
 [2018-06-19 15:19 UTC] thomas at landauer dot at
Yeah, sure `(string)false === ''`. But `(string)null === ''` too! So if you have a nullable boolean field in your database, this function becomes completely useless, since you can't tell `null` from `false`.

Fixing the documentation is certainly better than nothing (haven't seen it live, though). But I'd suggest to add an optional argument to configure how `false` is treated - something like the $options constants in `json_encode()`.
 [2018-06-19 15:44 UTC] cmb@php.net
> So if you have a nullable boolean field in your database, this
> function becomes completely useless, since you can't tell `null`
> from `false`.

And you won't be able to distinguish either from an empty string.
CSV knows nothing about NULLs and booleans – it's all about
strings. You have to cater to that yourself in any way that suits
your use-case.

> But I'd suggest to add an optional argument to configure how
> `false` is treated - […]

In my opinion, adding yet another optional argument to fputcsv()
does more harm than good.  However, feel free to start the RFC
process[1]. :)

[1] <https://wiki.php.net/rfc/howto>
 [2018-06-19 15:52 UTC] thomas at landauer dot at
> And you won't be able to distinguish either from an empty string.

Well, an empty string is not possible in a boolean field ;-)

> In my opinion, adding yet another optional argument to fputcsv()
does more harm than good.

Why? Which harm?
 [2018-06-19 16:30 UTC] thomas at landauer dot at
> CSV knows nothing about NULLs and booleans – it's all about
strings

Just reasoned about this some more. And I came to the conclusion that it isn't true ;-)

CSV (and `fputcsv()`) does have a distinction between strings and numbers: the quotes! `true` is exported as `1`, not as `"1"`. Why?? => The only possible answer I see: Because it's casted to `int` (not to `string`).

Well, and if you cast `false` to an `int`, what do you get? => `0`!
 [2018-06-19 16:49 UTC] cmb@php.net
-Status: Closed +Status: Re-Opened -Type: Documentation Problem +Type: Feature/Change Request -Assigned To: cmb +Assigned To:
 [2018-06-19 16:55 UTC] spam2 at rhsoft dot net
> CSV (and `fputcsv()`) does have a distinction 
> between strings and numbers: the quotes! `true` 
> is exported as `1`, not as `"1"`. Why?? => The 
> only possible answer I see: Because it's casted 
> to `int` (not to `string`)

you don't understand how PHP works

php > echo (string)true;
1
php > echo (string)false;
php >
 [2018-06-19 17:01 UTC] thomas at landauer dot at
You don't understand what I mean ;-)

php > echo (int)true;
1
php > echo (int)false;
0
 [2018-06-19 17:06 UTC] spam2 at rhsoft dot net
but csv is all about TEXT and not numbers, so there is no point that something is casted to int - if you want 

http://php.net/manual/en/language.types.type-juggling.php
if you want to avoid this you have to cast your values explicit, that's it
 [2018-06-19 17:07 UTC] nikic@php.net
-Status: Re-Opened +Status: Not a bug
 [2018-06-19 17:07 UTC] nikic@php.net
> CSV (and `fputcsv()`) does have a distinction between strings and numbers: the quotes! `true` is exported as `1`, not as `"1"`. Why?? => The only possible answer I see: Because it's casted to `int` (not to `string`).

Such a distinction does not exist. The quotes are not part of the string (unless you explicitly include them), so obviously they will not be printed. In PHP, (string)false=="". That may or may not be a good choice, but it's the way it is and not going to change. fputcsv() does nothing more and nothing less than a simple string cast before printing the value. If you want to deviate from the standard string casting logic, you need to do so yourself.
 [2018-06-19 17:11 UTC] spam2 at rhsoft dot net
and if you want to distinct between false and NULL you have to be prepared to do that by hand anyways in the export as well as in the import because your "So if you have a nullable boolean field in your database, this function becomes completely useless, since you can't tell `null` from `false`" is pointless too

php > echo (int)false;
0
php > echo (int)NULL;
0
 [2018-06-19 18:13 UTC] thomas at landauer dot at
> The quotes are not part of the string

Yeah, you're right, sorry! The quotes are added only if the string contains special characters.

> echo (int)NULL;

Yeah ;-)

But let's see it from a different perspective:
In the database, we have three possible values: true, false, null
In the CSV file, we have three options: 1, 0, nothing

I guess we all agree that the current mapping isn't quite smart:
true => 1
false, null => nothing

So what I'm asking for is *some* way to get:
true => 1
false => 0
null => nothing
 [2018-06-19 18:19 UTC] spam2 at rhsoft dot net
> I guess we all agree that the current mapping isn't quite smart

no, because there is no mapping at all, it's that easy
that's how implicit type casting works

if you touch that here and make special cases you open a can of worms
 [2020-02-07 06:05 UTC] phpdocbot@php.net
Automatic comment on behalf of cmb
Revision: http://git.php.net/?p=doc/en.git;a=commit;h=e5273c2500a0e42341935cd1fe2811cce83db5c0
Log: Fix #76500: fputcsv() is ignoring the value FALSE
 [2020-02-07 06:05 UTC] phpdocbot@php.net
-Status: Not a bug +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 18 23:01:27 2024 UTC