I am practising with the AdventureWorks database for now and I will be receiving strings like the following: SalesOrderNumber=SOH123
and CustomerID=1
. The strings may not always contain =
, as they may be >
, <
, >=
, <=
, !=
, <>
.
Ideally, I would like to split each string into 3 fields – the database column to query, the comparison (e.g. =, >, !=, etc) and the value to search for.
I can achieve what I want with lots of code, comparing character by character, but I am hoping someone can suggest a really simple way to do this, as I am sure this must be a fairly common task for websites.
I don’t want to just use the strings as they come through, as I need to sanitise them first. I also don’t want to send bad queries to the database that may generate SQL errors.
Advertisement
Answer
It is indirect and feasibly inefficient to make calls of explode()
within nested loops with break
condition.
I recommend preg_split()
as the right tool for the job. Create a capture group containing a character class of whitelisted symbols. Allow a maximum of 3 elements as its return value. Use the PREG_SPLIT_DELIM_CAPTURE
flag to inform the function to preserve the delimiting comparison operators when exploding the string into three parts.
Code: (Demo)
var_export( array_map( fn($v) => preg_split( '/([!<=>]+)/', $v, 3, PREG_SPLIT_DELIM_CAPTURE ), $array ) );
Output:
array ( 0 => array ( 0 => 'SalesOrderNumber', 1 => '=', 2 => 'SOH123', ), 1 => array ( 0 => 'CustomerID', 1 => '=', 2 => '1', ), 2 => array ( 0 => 'BigOrEqual', 1 => '>=', 2 => '44', ), 3 => array ( 0 => 'SmallOrEqual', 1 => '<=', 2 => '67', ), 4 => array ( 0 => 'NotEqual', 1 => '!=', 2 => '123', ), 5 => array ( 0 => 'NotEqual', 1 => '<>', 2 => '2000', ), 6 => array ( 0 => 'Smaller', 1 => '<', 2 => '21', ), 7 => array ( 0 => 'Bigger', 1 => '>', 2 => '12', ), )