The expression John-Adams == Alice parses somewhat like (John - Adams) == Alice. The left side is trying to subtract two strings (undefined constants are considered 'barewords', and are equal to a stringification of their names; John === 'John', for example), and in order to make sense of such an odd operation, PHP turns both strings into numbers. As integers, both strings have a value of 0, so the left side equates to 0.
An int.
Now, when PHP wants to compare with ==, it wants to coerce both sides into the same type. In this case, it's converting to int. Alice also converts to 0. Both sides being 0, they're "obviously" equal.
In order to prevent this from happening, you should probably put quotes around your values. You might also consider using the strict equals operator (===), unless you really want that type coercion magic.
Alternatively, if you have a known set of operators, you can eliminate eval and make this safer and more robust all around, by making a comparison function that has sub-functions for the operators. Like so:
function compare($value1, $op, $value2) {
static $known_ops = array(
'==' => function($a, $b) { return $a == $b; },
'!=' => function($a, $b) { return $a != $b; },
...
# you can even make up your own operators. For example, Perl's 'eq':
'eq' => function($a, $b) { return "$a" === "$b"; }
...
);
$func = $known_ops[$op];
return $func($value1, $value2);
}
...
$ruleTrue = compare($value, $operator, $value2);
Now you don't have to worry about your values. You do have to worry about $operator, but that's only an issue if you let a user input it without you validating it. In which case, you may want to throw an exception or something if $op wasn't in $known_ops, cause if you leave PHP to handle it, you'll likely get a fatal error when it tries to call null.