PhpNativeTypeCaster incorrectly casts string "false" and "0" to true

Open Beginner friendly
#127 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
85/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
php
Domain
backend

Research direction

Start in PhpNativeTypeCaster at the bool branch of the second pass, then inspect the existing 'string-to-bool' coverage in HydratorTest. Add coverage for string values 'false', 'true', '0', and '1', and verify that hydration returns the expected booleans without changing existing integer behavior.

Written by the indexing model from the issue text.

Description

Problem

PhpNativeTypeCaster casts scalar values to bool using native PHP cast (bool) $value.
This produces incorrect results for common HTTP input values.

HTTP query parameters and form data are always strings. When hydrating a DTO property
typed as bool, values such as "false" and "0" are cast to true instead of false.

Steps to reproduce
use Yiisoft\Hydrator\ArrayData;
use Yiisoft\Hydrator\Hydrator;

final class Input
{
    public bool $active = false;
}

$hydrator = new Hydrator();
$input = $hydrator->create(Input::class, new ArrayData(['active' => 'false']));

var_dump($input->active); // bool(true), expected bool(false)

The same issue occurs for query-string input in applications using yiisoft/input-http
with #[FromQuery] / #[FromBody] attributes.

Actual behavior
Input value Cast result
"false" true
"true" true
"0" true
"1" true
"" false
0 false
1 true
Expected behavior

String representations of boolean values should be parsed explicitly, similar to
how integer and float strings are handled via NumericHelper::normalize():

Input value Expected result
"false" false
"true" true
"0" false
"1" true
Root cause

In PhpNativeTypeCaster, the bool branch of the second pass uses unconditional
native cast:

case 'bool':
    if (is_scalar($value) || $value === null || is_array($value) || is_object($value)) {
        return Result::success((bool) $value);
    }
    break;

In PHP, any non-empty string is truthy when cast to bool:

(bool) 'false'; // true
(bool) '0';     // true
Context
  • The current test suite only covers 'string-to-bool' with input '1' (HydratorTest).
    Cases 'false', 'true', and '0' are not covered.
  • The official typecasting guide demonstrates bool hydration with integer 1,
    not string "false".
  • yiisoft/validator provides BooleanValue rule for validation, but it does not
    transform raw values during hydration. Even when validation passes, PhpNativeTypeCaster
    still applies the incorrect cast afterward.
Suggested fix

For string and Stringable values, parse boolean keywords explicitly before
falling back to native cast. For example, filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)
may be used for string input, with null mapped to Result::fail().

Suggested test cases
  • 'false' -> false
  • 'true' -> true
  • '0' -> false
  • '1' -> true
Impact

Any application hydrating bool properties from HTTP input (query string, form data)
may silently receive inverted boolean values. This is especially dangerous for
filtering, feature flags, and opt-out parameters where false is the intended value.

Dominant language
PHP
Stars
34
Forks
6
Avg merge
17m
Merged PRs (30d)
4

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from yiisoft/hydrator

All issues in yiisoft/hydrator

Similar issues

More PHP issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.