loading...

Why PHP...???

kevinhch profile image Kevin ・2 min read

Hello, today i was working with some PHP and AJAX, and i had a problem, finally i fixed it, but i was asking myself, why PHP works like this.
This is my JS file.

<html>
<script>
        (() => {
            const formData = new FormData();
            formData.append('orange', false)
            formData.append('purple', true)
            formData.append('someData', 'lorem ipsum...you know right')
            formData.append('numbers', [1,1,2,3,5,8])

            const sendData = async (url, method, data) => {
                let response = await fetch(url, {method: method, body: data})
                let dataRes = await response.json()
                console.log(dataRes)
            };//senData
            const url = window.location

            sendData(`${url}back.php`, 'post', formData)


        })()    
</script>
<html>

I was validating a form and preparing the data to send to my backend and play with this data in my Data Base, ok no problem.
But when i tried to validate the data on the backend...was horrible, because I tried to validate Booleans, and PHP did weird things with Booleans.

<?php
// This is my "validation"
if(isset($_POST['orange']) && $_POST['orange'] == true){
    echo "Why im here, orange is false!!";
}

And this is the response from server.



OK, no problem, let me check what types of variables i have:



I got you, i can't compare a string with a boolean, ok, let me cast.

<?php
echo "<pre>";
var_dump($_POST['orange']);
echo "</pre>";

$orange = (bool) $_POST['orange'];
echo "casting to boolean...";
echo "<pre>";
var_dump($orange);
echo "</pre>";

// This is my "validation"
if($orange == true){
    echo "Why im here, orange is false!!";
    echo "<pre>";
    var_dump($orange);
    echo "</pre>";
}//if

But still true, why? I cas't the variable, now should be false, but still true.

<?php

$orange = (bool) $_POST['orange'];
echo "casting to boolean...";
echo "<pre>";
var_dump($orange);
echo "</pre>";

// This is my "validation"
if($orange == true){
    echo "Why im here, orange is false!!";
    echo "<pre>";
    var_dump($orange);
    echo "</pre>";
}//if
echo "<pre>";
print_r($_POST);
echo "</pre>";



And that's the problem, if i want to cast to a boolean I need to use json_decode (WHAT?), I have an string, i cast to a boolean, but PHP don't cast the variable, PHP check if he can cast, if he can, they will return true, not the content of the variable.

<?php
$orange = (bool) json_decode($_POST['orange']);
//finally
if($orange == true){
    echo "Why im here, orange is false!!";
}else{
    echo "win win for me.<br>";
    var_dump($orange);
}

Finally!



The question is: Why PHP works so weird with booleans?.
I'm pretty sure others progamming langs can be solve this types of problems pretty good.

Other way to fix this problem was:

<?php
if($orange == "true"){
    echo "do something";
}

But this is not my style.
Tell me situations like these that have happened, to avoid them.

Posted on by:

Discussion

markdown guide
 

What about using the filter_input function from php?

$orange = filter_input(INPUT_POST, 'orange', FILTER_VALIDATE_BOOLEAN);

Returns TRUE for "1", "true", "on" and "yes". Returns FALSE otherwise.

$orange = filter_input(INPUT_POST, 'orange', FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);

If FILTER_NULL_ON_FAILURE is set, FALSE is returned only for "0", "false", "off", "no", and "", and NULL is returned for all non-boolean values.

 

I am afraid that FormData will always convert your values to string, if it is not a Blob or a File type.

Check this StackOverflow answer, you solved your issue the right way, but I guess this has nothing to do with PHP (you would have the same issue with a NodeJS backend for instance).

Tips for your client side payload

You can take advantage of JSON.stringify to encode your data:

const response = await fetch("/fruits.php", {
  headers: {
    Accept: "application/json",
    "Content-Type": "application/json"
  },
  method: "POST",
  body: JSON.Stringify({
    "orange": true,
    "purple": false
  })
});

Decode your payload seemlesly server side

I found this GitHub issue, with an interesting solution. I adapted it to make this seemless in your actual code:

$payload = file_get_contents('php://input');
$_POST = json_decode($payload);

var_dump($_POST["orange"]); // bool(true)
var_dump($_POST["purple"]); // bool(false)

Hope it helps!

 

PHP is how you get ants. :)

On a side note, all fields send in a post request are strings.

Use integers instead, then you can parse the string to a number, and check for 0 or 1.

Or use a JSON payload instead like Khalyomede suggests. ;)

JSON has boolean as a type

 
 

I will started to use it, thnx dudes :)

 

Well since the dawn of time the following has held true:

false == 0
true != false

And of course "false" != 0 and must therefore be true.

This is also the reason for the following weirdness:

echo true + 1;
2

echo false * 1;
0

echo true + true;
2

echo (bool) 99 + 1;
2
 

All HTTP 1.0/1.1 payload is string and integer values. Even binary files are BinHex'ed before transmitting.

If another language has booleans it's because it is converting the string for you. Will it do it for an online questionnaire? Answer a true/false question on a form and then save it to the database? Are you saving 0/1? Can't assume all answers will be boolean or ints? How about reports on the questionnaire? "98% answered 1". that will require the dev to flag the question as a boolean output then convert it back to a string.

Since you need to sanitize your data you should use the PHP filter_input library that was recommended by /mikcat.

Note: I am not lecturing or talking down to you but trying to provide you with the possible view of the PHP developers.

 

Not sure about PHP, but in most cases casting strings to booleans works like this:

bool("true") // true
bool("false") // true
bool(" ") // true
bool("") // false