Search code examples
phpoperatorswhere-clausetext-parsingpreg-split

Split strings in array to form three-element subarrays


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.


Solution

  • 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',
      ),
    )