Repository: codeigniter4/CodeIgniter4 (PHP)

Issue:
Bug: For set_checkbox, when default is true the checkbox will become checked when redirected back with input.
### PHP Version

8.1

### CodeIgniter4 Version

4.3.5

### CodeIgniter4 Installation Method

Manual (zip or tar.gz)

### Which operating systems have you tested for this bug?

Windows

### Which server did you use?

apache

### Database

_No response_

### What happened?

`<input type="checkbox" name="fruit" value="apple" <?= set_checkbox("fruit", "apple", true) ?>>`
The input is part of a user submitted form. 
When the view is generated, I want the checkbox to be checked by default. Then the user submits their form, the controller validates the information, then is redirected accordingly.
However, when the user is redirected back with input, 'fruit' is checked, even when the user unchecks it.

I suspect that this is because when 'fruit' is unchecked, 'fruit' is not added to $_POST, then when set_checkbox does not find an old value, which causes it to use the default value, which is checked. I think this because my CI_ENVIRONMENT is development, and I can see that _ci_old_input does not contain 'fruit'.

### Steps to Reproduce

have 
`<input type="checkbox" name="fruit" value="apple" <?= set_checkbox("fruit", "apple", true) ?>>`
in the view,

then 
`return redirect()->back()->withInput();`
in the controller, after the user submits the form


### Expected Output

Checkbox should be checked by default, then checked/unchecked according to user input when redirected back with input.

### Anything else?

_No response_


Discussion:
Yes, `withInput()` stores POST values in the session, 
and there is no `fruit` data if you don't check anything.
Then `set_checkbox()` checks it because the default is `true`.

This behavior is from CI3, so maybe this is the spec?

@WrestlingPotato If you could fix this issue, please send a PR.
https://github.com/codeigniter4/CodeIgniter4/blob/develop/contributing/README.md
Ah, CI3 does not have `withInput()`. So there is no problem!

The workaround is not to use the redirect.
I found a bug in the documentation: #7816
I'm just starting to learn CI4, so I don't know how to fix the issue, and wanted to bring attention to the issue. For now I just gave up on having the checkbox be checked by default.
use set_value('fruit', $fruit === 'apple' ? true : false) ? $fruit it _POST value
@WrestlingPotato No problem. I found how to fix. Try #7818



Patch:
diff --git a/system/Helpers/form_helper.php b/system/Helpers/form_helper.php
index c553bddee2c3..7f8f191a3a6f 100644
--- a/system/Helpers/form_helper.php
+++ b/system/Helpers/form_helper.php
@@ -629,8 +629,11 @@ function set_checkbox(string $field, string $value = '', bool $default = false):
             return '';
         }
 
+        $session     = Services::session();
+        $hasOldInput = $session->has('_ci_old_input');
+
         // Unchecked checkbox and radio inputs are not even submitted by browsers ...
-        if ((string) $input === '0' || ! empty($request->getPost()) || ! empty(old($field))) {
+        if ((string) $input === '0' || ! empty($request->getPost()) || $hasOldInput) {
             return ($input === $value) ? ' checked="checked"' : '';
         }
 


Test patch:
diff --git a/tests/system/Helpers/FormHelperTest.php b/tests/system/Helpers/FormHelperTest.php
index 639d03c48f47..ca90ce53c12e 100644
--- a/tests/system/Helpers/FormHelperTest.php
+++ b/tests/system/Helpers/FormHelperTest.php
@@ -867,6 +867,29 @@ public function testSetCheckboxWithValueZero(): void
         $this->assertSame(' checked="checked"', set_checkbox('foo', '0', true));
     }
 
+    /**
+     * @see https://github.com/codeigniter4/CodeIgniter4/issues/7814
+     */
+    public function testSetCheckboxWithUnchecked(): void
+    {
+        $_SESSION = [
+            '_ci_old_input' => [
+                'post' => [
+                ],
+            ],
+        ];
+
+        $this->assertSame(
+            '',
+            set_checkbox('fruit', 'apple', true)
+        );
+
+        $this->assertSame(
+            '',
+            set_checkbox('fruit', 'apple')
+        );
+    }
+
     /**
      * @runInSeparateProcess
      * @preserveGlobalState disabled