filter_var() is Your Friend
I was recently reading a blog post by Aaron Saray called In PHP, False is Sometimes True. This is an issue that I've encountered in the past and I'd already considered blogging about the solution, which is something Aaron left out of his blog post.
I'm sure that almost everyone that has dealt with handling html form data on the
backend from a
$_POST or a
$_GET variable via http or a JSON string has
encountered a situation in which trying to use a boolean value resulted in the
strange behavior of "false" equaling true. This happens because when casting a
string to a boolean, any non-empty string evaluates to true.
Mr. Saray used the following code snippet to demonstrate this "phenomenon".
$flag = "false"; assert((bool) $flag === true);
Of course, the assetion here returns true, because "false" IS true.
In the past, before I learned about the filter_var function I would do something
assert($flag === "true"); This solution is perfectly valid, however, it
is also perfectly inflexible. If we want to support multiple frontends, some
which may actually send a boolean, or some that may use a 0 = false and 1 = true
schema, this will fail and leave us hunting bugs again.
Introduced in php 5.2 and still valid in php 7+, filter_var() is the best way to tackle this problem. filter_var takes 3 arguments, the variable to filter, the type of filter to use and optional filters, which are dependent on the type of filter.
Using a filter type of
FILTER_VALIDATE_BOOLEAN will return true for 1, "1",
true, "true", "on" and "yes". Any other value will return false. So this solves
the inflexibility issue that arrises with my 'old' solution.
Solving the above bug with filter_var would look like this:
$flag = "false"; $boolFlag = filter_var($flag, FILTER_VALIDATE_BOOLEAN); assert($boolFlag === true);
I've demonstrated that using filter_var with the FILTER_VALIDATE_BOOLEAN filter type is much more predictable than simply casting the variable, and much more flexible than a hard coded solution. However, as implied by having a 'type' parameter in the filter_var function, you can do more than just safe boolean casting with this function. Two of my other most used filter types are FILTER_VALIDATE_EMAIL and FILTER_VALIDATE_IP which do pretty much as their names imply. If the variable is a valid email or IP address, they will return the variable, if not they return false. These are super useful in if statements, so throw out those long confusing regular expressions that you googled that miss edge cases anyway and start using filter_var. You can find a list of the other Validate Filters here. There are also Sanatize filters that will return an altered variable, so you can sanitize your inputs. Last but not least, check out filter_var_array() If you have an array of flags, email or IP addresses that you need to validate in one fell swoop.
If you liked this post, you can follow me @ToddEidson on Twitter for the best way (for now) to be notified of future blog posts.
Date Published: 4 December, 2017