-3

I have a code in php it takes a well formatted string such as 'field,operator,value' and produces a WHERE statement to MySQL database query. if the two fields names below end with the same characters such as '*id' such as 'id' and 'classid' it produces strange behavior. such as the following:

$where = $_GET['where'];
$tokens = multiexplode(array("^", "~", "(", ")"), $where);
$where = str_replace("^", " AND ", $where);
foreach ($tokens as $item) {
    if (!empty($item)) {
        $where = str_replace($item, getOperand($item), $where);
    }
}
echo 'WHERE '.$where;

function multiexplode($delimiters, $string)
{
    $unifydelimters = str_replace($delimiters, $delimiters[0], $string);
    $conditions = explode($delimiters[0], $unifydelimters);
    return  $conditions;
}
function getOperand($item)
{
    $extokens = explode (",", $item);
    switch (trim($extokens[1])) {
        case 'eq':
            return trim($extokens[0])  . " = '" . trim($extokens[2]) . "' ";
            break;
        default:
            return "";
            break;
    }
}

tested with : http://localhost/test/test.php?where=id,eq,1^classid,eq,19

ALways show: id = '1' AND classid='1' 9 Not: id = '1' AND classid='19'

But if any other field ends differently from the other such as:

http://localhost/test/test.php?where=id,eq,1^class,eq,19

It correctly shows: id = '1' AND class='19'

Any idea why this is happening??

Thanks,

Progman
  • 16,827
  • 6
  • 33
  • 48
Shangab
  • 39
  • 1
  • 9

1 Answers1

0

The problem is that when you search for the first expression id,eq,1 for the replacement in the string

id,eq,1^classid,eq,19

You will find two positions:

id,eq,1^classid,eq,19
^            ^
id,eq,1      |
             id,eq,1

This means you will do two replacements, even though you wanted only replace one.

To solve this problem you don't need to work with the original input string $where. Instead you can use the already create array in $tokens and change the individual array elements. You can use array_map() to do that, like this:

$changed = array_map('getOperand', $tokens);

Then you can put the array together to a string with ' AND ' as the separator:

$result = implode(' AND ', $changed);

This will finally generate the following result:

id = '1'  AND classid = '19' 

Keep in mind that you should use prepared statements to avoid SQL injections, see How can I prevent SQL injection in PHP?

Progman
  • 16,827
  • 6
  • 33
  • 48