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

Type of $_GET #1087

Closed
vasily-kartashov opened this issue Nov 21, 2018 · 6 comments
Closed

Type of $_GET #1087

vasily-kartashov opened this issue Nov 21, 2018 · 6 comments

Comments

@vasily-kartashov
Copy link

Is there a way to specify the type of $_GET superglobal (or alternatively the result's type of parse_str)?

0=                                                 array<int,string>                                 
&&&&a=example                                      array<string,string>                              
x=&y[]=2&y[xxx]=null&0=false                       array<int|string,array<int|string,string>|string> 
x=&y[]=2&y[xxx]=null&0=false&[1]=23                array<int|string,array<int|string,string>|string> 
x=&y[][]=2&y[][1]=null&y[][][]=0&false=-1          array<string,array<int,array<int,array<int,string>>|array<int,string>>|string>
5=6                                                array<int,string> 

With recursive types it would be something like

@var V=array<int|string,string|V>
@weirdan
Copy link
Collaborator

weirdan commented Nov 21, 2018

That might be quite tricky since $_GET is not read-only: https://3v4l.org/qLFMP . And it's superglobal nature further complicates things, since it could be assigned anywhere.

@vasily-kartashov
Copy link
Author

Sorry, I haven't been very precise here. I wasn't talking about a universal annotation that should apply to $_GET superglobal in every context.

But there are situations where we capture the content of $_GET, or pass similar parameters, or expect the "canonical" form, for example:

$request = Request::fromSuperGlobals();

or

$request->withQueryParams($params);

@TysonAndre
Copy link
Contributor

It's implemented in src/Psalm/Internal/Analyzer/Statements/Expression/Fetch/VariableFetchAnalyzer.php

        if (in_array(
            $stmt->name,
            [
                'GLOBALS',
                '_SERVER',
                '_GET',
                '_POST',
                '_FILES',
                '_COOKIE',
                '_SESSION',
                '_REQUEST',
                '_ENV',
            ],
            true
        )
        ) {
            $stmt->inferredType = Type::getArray();
            $context->vars_in_scope['$' . $stmt->name] = Type::getArray();
            $context->vars_possibly_in_scope['$' . $stmt->name] = true;

            return null;
        }

It's easy to do, the main issue is deciding what you want to do. E.g. 0=something is going to be pretty rare in most web apps. (array<string,array|string> might work)

My thoughts would be to use the following union types, or something similar (will have false positives in the very rare cases when you use integers as keys):

I don't think psalm supports recursive union types, or that there are plans to

[
        '_GET' => 'array<string,string|string[]>',  // or array<string,string|array>, if you want to support arbitrary nesting - same for the others
        '_POST' => 'array<string,string|string[]>',
        '_COOKIE' => 'array<string,string|string[]>',
        '_REQUEST' => 'array<string,string|string[]>',
        '_SERVER' => 'array<string,mixed>',
        '_ENV' => 'array<string,string>',
        '_FILES' => 'array<string,array<string,int|string|array<string,int|string>>>',  // Can have multiple files with the same name.
        '_SESSION' => 'array<string,mixed>',
        'GLOBALS' => 'array<string,mixed>',
]

@muglug
Copy link
Collaborator

muglug commented Nov 22, 2018

I don't think psalm supports recursive union types

Does Phan?

@TysonAndre
Copy link
Contributor

No

@muglug
Copy link
Collaborator

muglug commented Mar 6, 2019

Fixed by #1430

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants