3

Depending on the submission-mechanism of an HTML form, any checkbox element values may be seen as 'on', 'off', 1, 0, 'true', 'false'. For this problem an unchecked input field will be also be submitted (because that's what I want) and it may appear as 0 or no or false.

The purpose here is to convert scalar values that logically represent a boolean value to a boolean variable. Such as:

  • "yes" => true
  • "no" => false
  • "false" => false
  • 0 => false
  • 1 => true

Is there a helper in the Laravel framework that can "cast" a submitted FormData checkbox (or a plain form) to a boolean?

I could roll my own, but asking here is worth a shot.

Here is what I would use:

<?php


function checkbox_boolean($parameter) {
    if (is_bool($parameter)) return $parameter;
    if (is_object($parameter)) return count(get_object_vars($parameter)) !== 0;
    if (is_array($parameter)) return count($parameter) !== 0;
    if (is_numeric($parameter)) { return (boolean) $parameter; }
    $p = is_string($parameter) ? strtolower($parameter) : $parameter;

    switch ($p) {
        case 'yes';
        case 'on';
        case 'true';
            return true;
            break;

        case null;
        case 'no';
        case 'off';
        case 'false';
            return false;
            break;
    }
    return false;
}

These are the most common cases I would like to cover:

<?php
print_r([
    'yes' => [
        '"true"' => checkbox_boolean('true'),
        'true' => checkbox_boolean(true),
        '1' => checkbox_boolean(1),
        '"1"' => checkbox_boolean('1'),
        'yes' => checkbox_boolean('yes'),
        'YEs' => checkbox_boolean('YEs'),
        '<non-empty object>' => checkbox_boolean((object) [ 'z' => 'z']),
        '<non-empty array[0]>' => checkbox_boolean([0]),
    ],
    'no' => [
        '"false"' => checkbox_boolean('false'),
        'false' => checkbox_boolean(false),
        '0' => checkbox_boolean(0),
        '"0"' => checkbox_boolean('0'),
        'no' => checkbox_boolean('no'),
        'No' => checkbox_boolean('No'),
        '<empty object>' => checkbox_boolean(new stdClass),
        '<empty array []>' => checkbox_boolean([]),
    ]
]);

This question is not a duplicate of "How to convert strings to boolean" because this is not a generic problem.

I am asking about the specific process of converting HTML forms, or rather checkbox elements to a boolean. An important part of the question/problem is identifying the common values that these checkboxes generate when submitted by various (common) methods and parsed by PHP. In retrospect this does not make much sense because the value can be 100% arbitrary and set via the value= attribute of the input element.


According to this article, the canonical way would be something like the following and would return;

  • true for: "1", "true", "on" and "yes".
  • false for: "0", "false", "off", "no", and ""
  • null otherwise

if (filter_has_var(INPUT_POST, 'agree')) {
    $agree = filter_input(INPUT_POST, 'agree', 
                 FILTER_VALIDATE_BOOLEAN,
                 [FILTER_NULL_ON_FAILURE]);
    if (! is_null($agree)) {
        ... 
    }
}

Resources:

  • Possible duplicate of [How to convert string to boolean php](http://stackoverflow.com/questions/7336861/how-to-convert-string-to-boolean-php) – Limon Monte May 24 '16 at 09:01
  • I'm not so familiar with Laravel, but a HTML input element with type="checkbox" requires you to set the value attribute as well, which is the value to be submitted with the form. So wouldn't it be easier to use consistent values for all your checkboxes instead of worrying about converting the values later on? – matt May 24 '16 at 09:08
  • @matt The only time value is required is when the `type` is `button`, [as far as I can see](https://www.w3.org/TR/html-markup/input.checkbox.html#input.checkbox-constraints). – Ivar May 24 '16 at 09:17
  • @matt No, I don't want to deal with the value attribute in the HTML. I do not always (want to) control the front-end or how the forms are submitted. – Ярослав Рахматуллин May 24 '16 at 09:28
  • @Ivar You're right, let me phrase it like this: In order to control the value being submitted by the form, you need to set the value attribute for the checkbox. My point remains the same though. – matt May 24 '16 at 09:29
  • Looking at this years later, I’m not sure I understand the question. Do you just want to get a boolean value from the checkbox? If so, `isset()` will return a boolean value if the checkbox has been selected, regardless of its value. If the checkbox has not been selected, there’s no point in checking its value since it won’t be submitted anyway. Or are you saying that _some_ checkboxes should be interpreted as `false`? Perhaps a sample form might be helpful. – Manngo Nov 30 '21 at 06:16
  • @Manngo the original question had a set of values to test against, I have made that part more visible. isset() will return true for a values such as 0, "no", "false" which is not what I want. Also, as noted in one of the answers it is possible to always get a value from a checkbox - even if it is uncheked. – Ярослав Рахматуллин Nov 30 '21 at 08:05

5 Answers5

2

This answer has nothing to do with Laravel, but offers a generic PHP solution.

When a form is submitted, all text-like fields are included, even if they are empty. This includes type="text", any of the newer types such as email and date as well as all unknown types such as type="testing". It also includes textarea.

As for buttons, only those which have been selected are included; unselected buttons will be absent. In practical terms, selected buttons will include 0 or more check boxes, only one (if any) radio button in a group, and the submit button selected.

The important thing about buttons is that selected buttons will be sent, but unselected ones won’t. This is regardless of the actual values of the buttons.

You can check for a checkbox, regardless of whatever value it is supposed to have, by testing its existence. For example, if you have a POST form with

<input type="checkbox" name="ok">

you can check for it using:

$ok = isset($_POST['ok']);

Some developers prefer to express the test as:

$ok = array_key_exists($_POST,'ok');

In both cases, the result is strictly boolean.

EDIT: Simplifying

There is a simple trick which allows you to assume that the checkbox always has a value:

<input name="ok" type="hidden" value="0">
<input name="ok" type="checkbox" value="1">

The checkbox shadows the hidden input, but only if it’s set. Otherwise the hidden input will be set instead.

At the PHP end, the vale of $_POST['ok'] will always be 0 or 1. You can use something like this:

$ok = !!$_POST['ok'];
Manngo
  • 14,066
  • 10
  • 88
  • 110
  • Looking at this years later I don't think this solution so great after all, because this solution assumes we can trust the client - which is a big assumption. It also clutters the UI markup and the intent is murky at best (hidden OR checkbox - wtf?). – Ярослав Рахматуллин Nov 06 '21 at 21:50
  • @ЯрославРахматуллин You may have missed the point. The first part is the standard way of checking for a checkbox. From the client end, there is just a checkbox, which, as I mentioned, is in the `$_POST` array only if it has been checked. As for trusting the client, that’s always an issue, and the solution above makes no difference to that. That’s why we have server validation. The second part, I did say was a “simple trick”, and you can take that as you wish. FYI, hidden fields have no impact on UI because, well, they’re hidden. – Manngo Nov 07 '21 at 04:18
0

In my case the checkbox returns "on" or "null", so in the controller I just do a IF statement:

 $checkbox_value = $request->checkbox_value ? 1 : 0

Hope it helps someone out there.

Mário

Mar Yo
  • 33
  • 1
  • 1
  • 6
0

My code to convert checkbox name="home" to int. If the checkbox is checked -> issert = true <=> 1 If the checkbox is unchecked -> issert = false <=> 0

$data = $request->all();            
$data['home'] = isset($data['home'])? 1 : 0;
Gim
  • 79
  • 1
  • 4
0

The checkbox_boolean($parameter) function in the question is good enough. You can even get it with composer.

0

Adding an attribute of value="1" to the input was the solution for me.

MT_Shikomba
  • 129
  • 1
  • 6