I was recently working on a pull request where I wanted to take an array of object IDs and convert that into a string to be used in a SQL statement.

But, to prevent potential issues such as SQL injection, I needed to find a way to sanitize the array of integers and make sure that we only had integers in the array. Here is the solution that I used.

// Sanitize so that the array only has integer values.
$sanitized_array = array_map( 'intval', $ids );

// Now that we have all integers in our array, we can safely implode the
// array to be used in a SQL statement.
$ids_string = implode( ', ', $sanitized_array );
$sql = "SELECT * FROM {$table} WHERE {$object_id_column} IN ( {$ids_string} ) AND meta_key = %s";

If you’re not used to mapping an array of values, you may be wondering what the heck array_map() is doing. What array_map() does is iterate over an array (the second argument) and apply a callback function (the first argument) to each value in the array.

We then get back the resulting array with each value being sanitized by intval().

Alternative solution to sanitizing an array of integers

If you’re still a bit confused about what array_map( 'intval', $ids ), here’s another way to approach the issue:

// Sanitize so that the array only has integer values.
$sanitized_array = array();
foreach( $ids as $id ) {
    $sanitized_array[] = intval( $id );
}

// Now that we have all integers in our array, we can safely implode the
// array to be used in a SQL statement.
$ids_string = implode( ', ', $sanitized_array );
$sql = "SELECT * FROM {$table} WHERE {$object_id_column} IN ( {$ids_string} ) AND meta_key = %s";

In both examples, we iterate over the $ids array and apply the intval() function to each value.

4 thoughts on “Sanitize array of integers in PHP

    1. That is a good question sir. I didn’t know, so I checked the developer handbook, StackOverflow. πŸ™‚

      Based on this article, it looks like array_map() is actually slower than foreach().

      That being said, I don’t think that array_map() is so much slower than foreach() that you should always use foreach(). Ultimately, you’ll probably want to go with whatever you believe is more readable.

      1. Fwiw it should perform about the same, the most expensive part of this process is most likely intval() call, not array_map or foreach. Casting with (int) could be faster, I’m curious Eric, can you run a comparison for us casting with (int) instead?

        1. It’s not very scientific, but here are the results from my testing.

          Before time is 1472957143.3285 and the after time is 1472957143.7474
          Mapped difference in microseconds is 0.41890907287598
          
          Before time is 1472957144.3045 and the after time is 1472957144.6375
          Foreach intval() difference in microseconds is 0.33299684524536
          
          Before time is 1472957145.1842 and the after time is 1472957145.5962
          Foreach cast difference in microseconds is 0.412024974823

          Which is interesting, because it contradicts articles I read that suggested casting was faster. Here is the script I used to test if you’re interested. It’s likely I made a mistake. Β―_(ツ)_/Β―

          <?php
          ini_set( 'memory_limit','1024M' );
          
          $values = array();
          
          for ( $i = 1; $i <= 1000000; $i++ ) {
              $values[] = (string) $i;
          }
          
          $before_mapped = microtime( true );
          $mapped_values = array_map( 'intval', $values );
          $after_mapped = microtime( true );
          
          $mapped_difference = $after_mapped - $before_mapped;
          echo "Before time is {$before_mapped} and the after time is {$after_mapped}\n";
          echo "Mapped difference in microseconds is {$mapped_difference}\n\n";
          
          // Reset
          $values = array_map( 'strval', $values );
          
          $before_foreach = microtime( true );
          $hand_rolled = array();
          foreach ( $values as $value ) {
              $hand_rolled[] = intval( $value );
          }
          $after_foreach = microtime( true );
          
          $foreach_difference = $after_foreach - $before_foreach;
          echo "Before time is {$before_foreach} and the after time is {$after_foreach}\n";
          echo "Foreach intval() difference in microseconds is {$foreach_difference}\n\n";
          
          // Reset
          $before_foreach = null;
          $after_foreach = null;
          $values = array_map( 'strval', $values );
          
          $before_foreach = microtime( true );
          $hand_rolled = array();
          foreach ( $values as $value ) {
              $hand_rolled[] = (int) $value;
          }
          $after_foreach = microtime( true );
          
          $foreach_difference = $after_foreach - $before_foreach;
          echo "Before time is {$before_foreach} and the after time is {$after_foreach}\n";
          echo "Foreach cast difference in microseconds is {$foreach_difference}\n\n";

Leave a Reply