Is there a way to simulate the LIKE operator of SQL in PHP with the same syntax? (% and _ wildcards and a generic $escape escape character)?
So that having:
$value LIKE $string ESCAPE $escape
you can have a function that returns the PHP evaluation of that without using the database?
(consider that the $value, $string and $escape values are already set).
OK, after much fun and games here's what I have come up with:
function preg_sql_like ($input, $pattern, $escape = '\\') {
    // Split the pattern into special sequences and the rest
    $expr = '/((?:'.preg_quote($escape, '/').')?(?:'.preg_quote($escape, '/').'|%|_))/';
    $parts = preg_split($expr, $pattern, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
    // Loop the split parts and convert/escape as necessary to build regex
    $expr = '/^';
    $lastWasPercent = FALSE;
    foreach ($parts as $part) {
        switch ($part) {
            case $escape.$escape:
                $expr .= preg_quote($escape, '/');
                break;
            case $escape.'%':
                $expr .= '%';
                break;
            case $escape.'_':
                $expr .= '_';
                break;
            case '%':
                if (!$lastWasPercent) {
                    $expr .= '.*?';
                }
                break;
            case '_':
                $expr .= '.';
                break;
            default:
                $expr .= preg_quote($part, '/');
                break;
        }
        $lastWasPercent = $part == '%';
    }
    $expr .= '$/i';
    // Look for a match and return bool
    return (bool) preg_match($expr, $input);
}
I can't break it, maybe you can find something that will. The main way in which mine differs from @nickb's is that mine "parses"(ish) the input expression into tokens to generate a regex, rather than converting it to a regex in situ.
The first 3 arguments to the function should be fairly self explanatory. The fourth allows you to pass PCRE modifiers to affect the final regex used for the match. The main reason I put this in is to allow you to pass  Removed per comments belowi so it is case insensitive - I can't think of any other modifiers that will be safe to use but that may not be the case.
Function simply returns a boolean indicating whether the $input text matched the $pattern or not.
Here's a codepad of it
EDIT Oops, was broken, now fixed. New codepad
EDIT Removed fourth argument and made all matches case-insensitive per comments below
EDIT A couple of small fixes/improvements:
.*? sequences in generated regexIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With