Удалить все элементы массива, кроме того, что я хочу?

У меня есть контроллер, который принимает пост-параметры из формы HTML, затем отправляет их в модель, которая будет вставлять массив в базу данных Cassandra.

Это SQLInjection доказательство, потому что это NoSQL, однако я боюсь, что пользователь может просто имитировать 100 000 пост-параметров или просто добавить некоторые, которые мне не нужны, и он будет вставлен в базу данных. Как я могу убедиться, что только мои значения останутся в моем массиве.

Пример:

$post = ['parent_id', 'type', 'title', 'body', 'tags']; // Good $post = ['parent_id', 'type', 'title', 'body', 'tags', 'one', 'two', 'three'] // Bad 

Как я могу убедиться, что мой массив отключит все элементы, которые не в хорошем примере?

Вы ищете array_intersect :

 $good = ['parent_id', 'type', 'title', 'body', 'tags']; $post = ['parent_id', 'type', 'title', 'body', 'tags', 'one', 'two', 'three']; print_r(array_intersect($good, $post)); 

Смотрите в действии .

Конечно, этот конкретный пример не имеет особого смысла, потому что он работает с значениями массива, но также есть array_intersect_key который делает то же самое на основе ключей.

Посредством белого списка записей, которые вы ожидаете.

 <?php $post = array( 'parent_id' => 1, 'type' => 'foo', 'title' => 'bar', 'body' => 'foo bar', 'tags' => 'foo, bar', 'one' => 'foo', 'two' => 'bar', 'three' => 'qux' ); $whitelist = array( 'parent_id', 'type', 'title', 'body', 'tags' ); $filtered = array_intersect_key( $post, array_flip( $whitelist ) ); var_dump( $filtered ); 

Во всяком случае, использование Cassandra в качестве хранилища данных, конечно, не является основанием для того, чтобы не выполнять валидацию данных, которые вы получаете.

Используйте пересечение массива. массив пересекается , это поможет вам.

Это будет выводиться так же, как $ post_allowed. То, что он делает, это разрешить только значения в $ post_input, которые также присутствуют в $ post_allow.

 $post_allowed = ['parent_id', 'type', 'title', 'body', 'tags']; $post_input = ['parent_id', 'type', 'title', 'body', 'tags', 'one', 'two', 'three']; $post = array_intersect($post_input, $post_allowed); 

Это называется белым листингом, ваш пример вводит в заблуждение, поскольку $_POST является массивом ассоциаций.

 $post = [ 'parent_id' => 'val', 'type' => 'val', 'title' => 'val', 'body' => 'val', 'tags' => 'val', 'one' => 'val', 'two' => 'val', 'three'=>'val', ]; $whitelist = ['parent_id', 'type', 'title', 'body', 'tags']; $sanitized_post = array_whitelist_assoc($post, $whitelist); 

Это функция «белый список», созданная для ассоциативных массивов.

 if(!function_exists('array_whitelist_assoc')){ /** * Returns an associative array containing all the entries of array1 which have keys that are present in all the arguments when using their values as keys. * * @param array $array The array with master keys to check. * @param array $array2 An array to compare keys against its values. * @return array $array2,... A variable list of arrays to compare. * */ function array_whitelist_assoc(Array $array1, Array $array2) { if(func_num_args() > 2){ $args = func_get_args(); array_shift($args); $array2 = call_user_func_array('array_merge', $args); } return array_intersect_key($array1, array_flip($array2)); } } 

Если вы имеете дело с ассоциативными массивами, и по какой-либо причине вы не хотите использовать array_intersect_key() , вы также можете сделать более простой подход для создания нового массива вручную, используя значения, которые вы хотите использовать из старого.

 $post = array( 'parent_id' => 1, 'type' => "post", 'title' => "Post title", 'body' => "Post body", 'tags' => "Post tags", 'malicious' => "Robert'); DROP TABLE students;--" ); $good = array( 'parent_id' => $post['parent_id'], 'type' => $post['type'], 'title' => $post['title'], 'body' => $post['body'], 'tags' => $post['tags'] ); 

Что относительно многомерного массива? Я был исследован на пару часов для этого решения, нигде не нашел оптимального решения. поэтому, я написал это сам

 function allow_keys($arr, $keys) { $saved = []; foreach ($keys as $key => $value) { if (is_int($key) || is_int($value)) { $keysKey = $value; } else { $keysKey = $key; } if (isset($arr[$keysKey])) { $saved[$keysKey] = $arr[$keysKey]; if (is_array($value)) { $saved[$keysKey] = allow_keys($saved[$keysKey], $keys[$keysKey]); } } } return $saved; } 

использовать: пример

 $array = [ 'key1' => 'kw', 'loaa'=> ['looo'], 'k' => [ 'prope' => [ 'prop' => ['proo', 'prot', 'loolooo', 'de'], 'prop2' => ['hun' => 'lu'], ], 'prop1' => [ ], ], ]; 

call: example

 allow_keys($array, ['key1', 'k' => ['prope' => ['prop' => [0, 1], 'prop2']]]) 

вывод:

 Array ( [key1] => kw [k] => Array ( [prope] => Array ( [prop] => Array ( [0] => proo [1] => prot ) [prop2] => Array ( [hun] => lu ) ) ) ) 

поэтому вы получаете только нужные ключи из многомерного массива. он не ограничивается только «многомерным», вы можете использовать его, передавая массив вроде

 ['key1', 'loaa'] 

вы получаете:

 Array ( [key1] => kw [loaa] => Array ( [0] => looo ) ) 

ура!

Стоит вспомнить, что в то время как array_intersect и array_intersect_key хороши, они вполне могут быть переполнены. В моей ситуации я хотел только 1 элемент слева, поэтому самым простым вариантом было просто перестроить массив, который я хотел, на основе ключа / значений, которые мне нужны. Интересно, в какой момент массив array_intersect не стоит того, и вам просто лучше с $new = array('whatI'=>'want'); , Я верю в ОП, это того стоит, но в меньших случаях это может быть излишним.

Альтернативно, в ответ на исходный вопрос, просто используя unset возможно, был более дешевый вариант – unset($post['one'],$post['two'],$post['three']) . Опять же, это относится к точке, в которой это становится слишком неэффективным, и функции array_intersect лучше.