Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: [Validation] field with asterisk (nested array) throws exception #5922

Closed
mostafakhudair opened this issue Apr 25, 2022 · 3 comments · Fixed by #5938
Closed

Bug: [Validation] field with asterisk (nested array) throws exception #5922

mostafakhudair opened this issue Apr 25, 2022 · 3 comments · Fixed by #5938
Labels
bug Verified issues on the current code behavior or pull requests that will fix them

Comments

@mostafakhudair
Copy link
Contributor

mostafakhudair commented Apr 25, 2022

PHP Version

7.4

CodeIgniter4 Version

4.1.9

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Linux

Which server did you use?

apache

Database

MySQL 4.9

What happened?

    protected array $validationRules = [
        'customer_account_number'                 => [
            'label' => 'ACCOUNT NUMBER',
            'rules' => 'required|exact_length[5]',
        ],
        'debit_amount'                            => [
            'label' => 'DEBIT AMOUNT',
            'rules' => 'required|decimal|is_natural_no_zero',
        ],
        'beneficiaries_accounts.*.account_number' => [
            'label' => 'BENEFICIARY ACCOUNT NUMBER',
            'rules' => 'exact_length[5]',
        ],
        'beneficiaries_accounts.*.credit_amount'  => [
            'label' => 'CREDIT AMOUNT',
            'rules' => 'required|decimal|is_natural_no_zero',
        ],
        'beneficiaries_accounts.*.purpose'        => [
            'label' => 'PURPOSE',
            'rules' => 'required_without[beneficiaries_accounts.*.account_number]|min_length[3]|max_length[255]',
        ],
    ];
    $this->validation->setRules($model->getValidationRules());

Case 1:

    $data = [
        "customer_account_number" => "A_490",
        "debit_amount"            => "1500",
        "beneficiaries_accounts"  => [],
    ];

Case 2:

    $data = [
        "customer_account_number" => "A_490",
        "debit_amount"            => "1500",
        "beneficiaries_accounts"  => [
            "account_1" => [
                "account_number" => "A_103",
                "credit_amount"  => 1000,
                "purpose"        => "",
            ],
        ],
    ];

Case 3:

    $data = [
        "customer_account_number" => "A_490",
        "debit_amount"            => "1500",
        "beneficiaries_accounts"  => [
            "account_1" => [
                "account_number" => "A_103",
                "credit_amount"  => 1000,
                "purpose"        => "Personal",
            ],
            "account_2" => [
                "account_number" => "A_258",
                "credit_amount"  => null,
                "purpose"        => "A",
            ],
        ],
    ];
    if (! $this->validation->run($data))) {
        if ($this->validation->hasError())) {
            return $this->validation->listErrors();
        }

        return "Success";
    }

Steps to Reproduce

Case 1: validation throws an exception: Argument 1 passed to CodeIgniter\Validation\Rules::exact_length() must be of the type string or null, array given, called in .*/vendor/codeigniter4/framework/system/Validation/Validation.php on line 292.

Case 2:
beneficiaries_accounts.account_1.account_number validation successfully as expected
beneficiaries_accounts.account_1.credit_amount validation successfully as expected.
beneficiaries_accounts.account_1.purpose validation successfully as expected.

Case 3:
beneficiaries_accounts.account_1.account_number validation successfully as expected
beneficiaries_accounts.account_1.credit_amount validation successfully as expected.
beneficiaries_accounts.account_1.purpose validation successfully as expected.

beneficiaries_accounts.account_2.account_number validation successfully as expected.
beneficiaries_accounts.account_2.credit_amount validation successfully while value is null, and it's ignored required rule.
beneficiaries_accounts.account_2.purpose validation fails Purpose field must be at least 3 characters in length, and it's ignored required_without rule.

Expected Output

Case 1: expect validation fails without throws an exception

Case 3: validate each array separately

@mostafakhudair mostafakhudair added the bug Verified issues on the current code behavior or pull requests that will fix them label Apr 25, 2022
@kenjis
Copy link
Member

kenjis commented Apr 30, 2022

@mostafakhudair

beneficiaries_accounts.account_2.purpose validation fails Purpose field must be at least 3 characters in length, and it's ignored required_without rule.

The error message seems to be expected behavior.

The purpose is A. So it is invalid.

@iRedds
Copy link
Collaborator

iRedds commented Apr 30, 2022

@kenjis the required_without rule will not work if the field is specified with a wildcard (asterisk).
For a field with dot notation, the dot_array_search() helper will be called.

if ((strpos($field, '.') === false && (! array_key_exists($field, $data) || empty($data[$field]))) || (strpos($field, '.') !== false && empty(dot_array_search($field, $data)))) {

$data = [
    'a' => [
        ['b' => 1, 'c' => 2],
        ['c' => ''],
    ]
];

dd(dot_array_search('a.*.b', $data)); // 1

// Therefore, this test will fail.
$this->validation->setRules([
    'a.*.c' => 'required_without[a.*.b]',
])->run([
    'a' => [
        ['b' => 1, 'c' => 2],
        ['c' => ''],
    ]
]);

$this->assertSame(
    'The a.*.c field is required when a.*.b is not present.', 
    $this->validation->getError('a.1.c')
);

@kenjis
Copy link
Member

kenjis commented Apr 30, 2022

@iRedds Thank you for explanation. I created an issue: #5942

@kenjis kenjis changed the title Bug: Validation nested array throws exception Bug: Validation field with dot-notation (nested array) throws exception Apr 30, 2022
@kenjis kenjis changed the title Bug: Validation field with dot-notation (nested array) throws exception Bug: Validation field with asterisk (nested array) throws exception May 1, 2022
@kenjis kenjis changed the title Bug: Validation field with asterisk (nested array) throws exception Bug: [Validation] field with asterisk (nested array) throws exception May 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Verified issues on the current code behavior or pull requests that will fix them
Projects
None yet
3 participants