Rss

  • youtube
  • linkedin
  • google

PHP Comparison Error

Today, I was writing a script in PHP to be used in the command line when I came across unexpected behavior (at least on my part).
The script should receive three arguments, the last of them a list containing one or more numeric codes.
Trying to validate this last argument was getting a different result than imagined.
See the code snippet that I was using:

// test.php
if (php_sapi_name() == 'cli') {
    $di = isset($argv[1]) ? $argv[1] : date('Y-m-d'); // Initial Date
    $df = isset($argv[2]) ? $argv[2] : date('Y-m-d'); // Final Date
    $prods = isset($argv[3]) ? explode(',', $argv[3]) : array(); // Code List

    ##### Validating
    // Initial Date
    if ($di != date('Y-m-d', strtotime($di))) {
        echo "\n";
        echo "ERROR! Invalid INITIAL DATE!\n";
        exit;
    }
    // Final Date
    if ($df != date('Y-m-d', strtotime($df))) {
        echo "\n";
        echo "ERRO! Invalid FINAL DATE!\n";
        exit;    
    }

    // Codes
    if (count($prods) > 0) {
        foreach ($prods as $prod) {
            if ($prod != (int)$prod) {
                echo "\n";
                echo "ERROR! The CODE " . $prod . " is invalid!\n" ;
                exit;
            }
        }
    }
    echo "DONE!";
}

Interestingly, when I ran

# php -f test.php 2015-12-10 2015-12-11 33b

the result was

# DONE

and reversing the condition to

        if ($prod == (int)$prod)

show the expected message.
I tried to assign to a separate variable and still continued not working.

            $check = (int) $prod;
            if ($prod != $check) {

Whyyy??

The Type Comparison

!==

cannot be used here, since all arguments will be strings. When I though about this I got the answer.

So I did some command line tests and I check for the actually behavior of PHP Comparisons.

When we do things like:

$string == $integer

PHP will always do a CAST from String to the other type before comparison, so the code

$string == (int) $string

will always return true, since $string will be changed to int in both sides.

To avoid this kind of trouble, is necessary to have the same type in both sides of comparison.

            $conf = (int) $prod;
            if ($prod != (string) $conf) {
            // OR
            if ($prod != (string)(int)$prod) {

See you.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.