1

I was working on a project at my job and came upon this code:

$queryStringValue = $_GET['var'];

if ( is_string($queryStringValue) )
{
    // Do something.
}

My question: Is calling is_string() to check if the query string value is a string completely unnecessary? By definition, "query string" leads me to believe the data type can only be a string, thus making a call to is_string() redundant.

Am I right, or are there times when a different data type can be passed in a query string?

Thank you for any insight!

GTS Joe
  • 3,612
  • 12
  • 52
  • 94
  • 1
    i didn't test it, but refer to the response of [Esailija](https://stackoverflow.com/a/13389026/8010101) `$_GET["index"]` may be an array – GNassro Aug 08 '20 at 17:35
  • 1
    Using `!is_array()`, while functionally equivalent in this case, would be more enlightening in your sample code. – Markus AO Aug 08 '20 at 21:24

3 Answers3

2

Per PHP manual on Variables From External Sources under "Determining variable types":

HTTP being a text protocol, most, if not all, content that comes in Superglobal arrays, like $_POST and $_GET will remain as strings. PHP will not try to convert values to a specific type.

Again, in the manual's FAQ: Arrays in HTML Form, we read on arrays:

To get your <form> result sent as an array to your PHP script you name the <input>, <select> or <textarea> elements like this: <input name="MyArray[]" /> ...

This would turn into a query string ?MyArray[]=foo&MyArray[]=bar etc., available as $_GET['MyArray'][0] and $_GET['MyArray'][1]. You can also use named keys; the query ?var[x]=one&var[y]=two would result in the associative array $_GET['var] = ['x' => 'one', 'y' => 'two']; and ?var[x][]=deep would become $_GET['var']['x'] = ['deep'], etc.

In addition, the manual for $_GET notes the following:

Note: The GET variables are passed through urldecode().

Then, see the signature of urldecode:

urldecode ( string $str ) : string

In other words, the function used for preprocessing $_GET values accepts a string and returns a string. Evidently, when there's an array incoming, it will apply urldecode to each string value of that array instead. (If someone cares to find the PHP source code section responsible for generating $_GET, please share the link, will include it here.)

Note that an empty value, e.g. in ?foo&bar=1, will not result in [foo] NULL, but rather in [foo] string(0) "", in other words a zero-length string. Again, we get [bar] string(1) "1". There's no type-casting of get or post values into integers, floats, booleans or null.

In conclusion, the possible datatypes received in $_GET are string and array (of strings; or further arrays; with the final, scalar "leaves" being strings). Of course, if you explicitly declare $_GET['foo'] = null or $_GET['bar'] = 1 in your PHP code, then there will be integers and nulls. The above applies to variables parsed by PHP from external sources.


Update: While the above is true for all the values parsed from the query string, things are different for the keys PHP extracts from a query string. Suppose the following URL:

test.php?101=foo&202=bar&dev=ops

Now, what will var_dump(array_keys($_GET)) return for the numeric keys? Integers, not strings:

array(3) {
    [0] · int(101)
    [1] · int(202)
    [2] · string(3) "dev"
}

This is in line with PHP's standard casting of array keys: "Strings containing valid decimal integers, unless the number is preceded by a + sign, will be cast to the integer type.". The following key cast will however not happen: "Floats are also cast to integers, which means that the fractional part will be truncated." Because (as noted in Variables from External Sources): "Dots and spaces in [external] variable names are converted to underscores."


External Variable Typecasting: Summary

  • A query string's values will always be strings, or arrays (of arrays) with strings as their final scalar values.
  • A query string's keys will always be strings, excepting whole numbers (unsigned positive: 3, signed negative: -3) that are cast as integers instead.
Markus AO
  • 4,771
  • 2
  • 18
  • 29
  • Great answer. Thanks for the explanation, examples and sources. – GTS Joe Aug 08 '20 at 22:20
  • thanks for you @Markus and thanks for GTS for this question, upvote for both :) – GNassro Aug 08 '20 at 23:44
  • 1
    Seemed like this question wasn't ever definitively asked/answered on SO -- glad to oblige. :) On a footnote on external input datatypes, we have the case of AJAX requests sending JSON data in a POST request body. These won't appear in the superglobals, and need to be accessed via `php://input`. When `json_decode()`'d, such data will have the full spectrum of datatypes known to JSON. Here's an excellent Q/A with more details: [PHP “php://input” vs $_POST](https://stackoverflow.com/questions/8893574/php-php-input-vs-post) – Markus AO Aug 09 '20 at 11:43
  • Added a note on *integer casting* that happens to numeric keys. Then, the complete conclusion is: **A query string's *values* will always be strings or arrays with strings. A query string's *keys* will always be strings, except for whole numbers that are cast as integers.** – Markus AO Aug 15 '20 at 21:02
1

the query string itself is a string, but variables from it may be parsed as string or array:

url.com?var=123 => var is string

url.com?var[]=123&var[]=321 => var is an array

-4

Yes it contains. It can have any type you want, including array, integers, floats etc..