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

Error: Argument #2 ($array) must be of type array, null given - Validation.php #8134

Closed
xonipatino opened this issue Nov 1, 2023 · 10 comments · Fixed by #8153
Closed

Error: Argument #2 ($array) must be of type array, null given - Validation.php #8134

xonipatino opened this issue Nov 1, 2023 · 10 comments · Fixed by #8153
Labels
bug Verified issues on the current code behavior or pull requests that will fix them

Comments

@xonipatino
Copy link

xonipatino commented Nov 1, 2023

PHP Version

8.2

CodeIgniter4 Version

4.4.3

CodeIgniter4 Installation Method

Composer (using codeigniter4/appstarter)

Which operating systems have you tested for this bug?

Windows

Which server did you use?

cli-server (PHP built-in webserver)

Database

No response

What happened?

CodeIgniter\\Validation\\DotArrayFilter::run(): Argument #2 ($array) must be of type array, null given, called in ...\\vendor\\codeigniter4\\framework\\system\\Validation\\Validation.php on line 203

Steps to Reproduce

I have the next code:

if (
            !$this->validate(
                [
                    'start' => [
                        'label' => 'Inicio',
                        'rules' => 'if_exist|numeric|integer|is_natural',
                    ],
                    'length' => [
                        'label' => 'Limite',
                        'rules' => 'if_exist|numeric|integer|is_natural_no_zero',
                    ],
                    'columns' => [
                        'label' => 'Columnas',
                        'rules' => 'if_exist|valid_json',
                    ],
                    'order' => [
                        'label' => 'Orden',
                        'rules' => 'if_exist|required_with[columns]|valid_json',
                    ],
                    'filters' => [
                        'label' => 'Filtros',
                        'rules' => 'if_exist|valid_json',
                    ],
                ]
            )
        ) {
            $errores = validation_errors();

            return response()->setJSON(
                [
                    'estado' => false,
                    'msje'   => view_cell(
                        'AlertCell',
                        [
                            'tipo'      => 'warning',
                            'contenido' => ul($errores, ['class' => 'mb-0']),
                        ]
                    ),
                    'errores' => $errores,
                    // Propiedad del datatable para respuesta de error
                    'error'   => current($errores),
                ]
            );
        }

and returns:

{
    "title": "TypeError",
    "type": "TypeError",
    "code": 500,
    "message": "CodeIgniter\\Validation\\DotArrayFilter::run(): Argument #2 ($array) must be of type array, null given, called in C:\\Users\\xonip\\OneDrive - ADN ERP S.A.S\\www\\local_html\\macc\\vendor\\codeigniter4\\framework\\system\\Validation\\Validation.php on line 203",
    "file": "C:\\Users\\xonip\\OneDrive - ADN ERP S.A.S\\www\\local_html\\macc\\vendor\\codeigniter4\\framework\\system\\Validation\\DotArrayFilter.php",
    "line": 29,
    "trace": [
        {
            "file": "C:\\Users\\xonip\\OneDrive - ADN ERP S.A.S\\www\\local_html\\macc\\vendor\\codeigniter4\\framework\\system\\Validation\\Validation.php",
            "line": 203,
            "function": "run",
            "class": "CodeIgniter\\Validation\\DotArrayFilter",
            "type": "::"
        },
        {
            "file": "C:\\Users\\xonip\\OneDrive - ADN ERP S.A.S\\www\\local_html\\macc\\vendor\\codeigniter4\\framework\\system\\Controller.php",
            "line": 152,
            "function": "run",
            "class": "CodeIgniter\\Validation\\Validation",
            "type": "->"
        },
        {
            "file": "C:\\Users\\xonip\\OneDrive - ADN ERP S.A.S\\www\\local_html\\macc\\app\\Controllers\\InformacionController.php",
            "line": 33,
            "function": "validate",
            "class": "CodeIgniter\\Controller",
            "type": "->"
        },
        {
            "file": "C:\\Users\\xonip\\OneDrive - ADN ERP S.A.S\\www\\local_html\\macc\\vendor\\codeigniter4\\framework\\system\\CodeIgniter.php",
            "line": 942,
            "function": "list",
            "class": "App\\Controllers\\InformacionController",
            "type": "->"
        },
        {
            "file": "C:\\Users\\xonip\\OneDrive - ADN ERP S.A.S\\www\\local_html\\macc\\vendor\\codeigniter4\\framework\\system\\CodeIgniter.php",
            "line": 502,
            "function": "runController",
            "class": "CodeIgniter\\CodeIgniter",
            "type": "->"
        },
        {
            "file": "C:\\Users\\xonip\\OneDrive - ADN ERP S.A.S\\www\\local_html\\macc\\vendor\\codeigniter4\\framework\\system\\CodeIgniter.php",
            "line": 361,
            "function": "handleRequest",
            "class": "CodeIgniter\\CodeIgniter",
            "type": "->"
        },
        {
            "file": "C:\\Users\\xonip\\OneDrive - ADN ERP S.A.S\\www\\local_html\\macc\\public\\index.php",
            "line": 79,
            "function": "run",
            "class": "CodeIgniter\\CodeIgniter",
            "type": "->"
        },
        {
            "file": "C:\\Users\\xonip\\OneDrive - ADN ERP S.A.S\\www\\local_html\\macc\\vendor\\codeigniter4\\framework\\system\\Commands\\Server\\rewrite.php",
            "line": 47,
            "args": [
                "C:\\Users\\xonip\\OneDrive - ADN ERP S.A.S\\www\\local_html\\macc\\public\\index.php"
            ],
            "function": "require_once"
        }
    ]
}

Expected Output

a JSON of data or a JSON with invalid input information

Anything else?

This was working in CI 4.4.2

@xonipatino xonipatino added the bug Verified issues on the current code behavior or pull requests that will fix them label Nov 1, 2023
@xonipatino
Copy link
Author

xonipatino commented Nov 1, 2023

Hello. I found the solution by changing the following line in the system\Validation\Validation.php file

Line 481:

/** @var IncomingRequest $request */
if (strpos($request->getHeaderLine('Content-Type'), 'application/json') !== false) {
    // $this->data = $request->getJSON(true);
    $this->data = $request->getJSON(true) ?? [];

    return $this;
}

@kenjis
Copy link
Member

kenjis commented Nov 1, 2023

Thank you for reporting.

The error should not be thrown, but if $request->getJSON(true) returns null,
it means the JSON string is invalid.
Do you really want the data to be valid?

@kenjis
Copy link
Member

kenjis commented Nov 1, 2023

This was working in CI 4.4.2

It is strange. Because there is no change in Validation except the exact_length rule.
codeigniter4/framework@a033985#diff-291972258304139308a9538a9fb7abfb92c903481df2a0af105dfdf8515cebd3

@kenjis
Copy link
Member

kenjis commented Nov 1, 2023

@codeigniter4/core-team
If we apply the suggested patch, the following test would pass.
However, it seems a bit odd that the test would pass.
If the result of the validation were to fail, there would be no field to store the error message.
Should we throw an exception?

    public function testJsonInputInvalid(): void
    {
        $config          = new App();
        $json            = 'invalid';
        $request         = new IncomingRequest($config, new URI(), $json, new UserAgent());
        $request->setHeader('Content-Type', 'application/json');

        $rules = [
            'role' => 'if_exist|max_length[5]',
        ];
        $result = $this->validation
            ->withRequest($request->withMethod('POST'))
            ->setRules($rules)
            ->run();

        $this->assertTrue($result);
        $this->assertSame([], $this->validation->getErrors());
        $this->assertSame([], $this->validation->getValidated());
    }

@xonipatino
Copy link
Author

xonipatino commented Nov 1, 2023

Thank you for reporting.

The error should not be thrown, but if $request->getJSON(true) returns null, it means the JSON string is invalid. Do you really want the data to be valid?

Hello, I was checking more carefully and I found that if you make a GET request with the header Content-Type = application/json it generates the error, so I deduced that it is illogical to make a GET request with that header, even though the query parameters they are sent by url.

@xonipatino
Copy link
Author

xonipatino commented Nov 1, 2023

Hello. I found the solution by changing the following line in the system\Validation\Validation.php file

Line 481:

/** @var IncomingRequest $request */
if (strpos($request->getHeaderLine('Content-Type'), 'application/json') !== false) {
    // $this->data = $request->getJSON(true);
    $this->data = $request->getJSON(true) ?? [];

    return $this;
}

It is not necessary to modify the line that I had named, it is just knowing how to put the headings for each case. But they should clarify it in the documentation.

AJAX Requests

@kenjis
Copy link
Member

kenjis commented Nov 2, 2023

@xonipatino I sent PR #8135

@MGatner
Copy link
Member

MGatner commented Nov 4, 2023

@kenjis does the doc fix make your question above irrelevant? I didn't understand it at first read but I can process to more if it is still relevant.

@kenjis
Copy link
Member

kenjis commented Nov 5, 2023

@MGatner I must say no? It is just a fix to a incorrect sample code that was pointed out by the reporter of this.

The TypeError issue still remains.

@MGatner
Copy link
Member

MGatner commented Nov 5, 2023

Okay I have now fully read and understood the issue. Yes, this is a bug in Validation - IncomingRequest::getJson() has no need to return an array, but Validation will only work on an array of data.

In my opinion this feature of Validation is assuming too much from the underlying stack and it should be pulled. We cannot assume a particular API schema nor even RESTful protocols. If things a desirable feature it should be moved somewhere appropriate, to IncomingRequest or even our API trait.

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
Development

Successfully merging a pull request may close this issue.

3 participants