Modeling LIKE in PHP

Is there a way to simulate a LIKE SQL statement in PHP with the same syntax? ( %and _generic $ escape as well)? So, having:

$value LIKE $string ESCAPE $escape

can you have a function that returns a PHP score without using a database? (consider the values $value, $stringand are $escapealready set).

+5
source share
4 answers

Well, after many fun and games here, what I came 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 will find something that will be. The main way that mine differs from @nickb is that my "parses" (ish) the input expression in tokens to generate a regular expression, rather than converting it to a regular expression in situ.

. PCRE, , . , , - i, - - , , .

, , $input $pattern.

, , .

EDIT /:

  • /
  • , .*?
+2

- :

$input = '%ST!_ING_!%';
$value = 'ANYCHARS HERE TEST_INGS%';

// Mapping of wildcards to their PCRE equivalents
$wildcards = array( '%' => '.*?', '_' => '.');

// Escape character for preventing wildcard functionality on a wildcard
$escape = '!';

// Shouldn't have to modify much below this

$delimiter = '/'; // regex delimiter

// Quote the escape characters and the wildcard characters
$quoted_escape = preg_quote( $escape);
$quoted_wildcards = array_map( function( $el) { return preg_quote( $el); }, array_keys( $wildcards));

// Form the dynamic regex for the wildcards by replacing the "fake" wildcards with PRCE ones
$temp_regex = '((?:' . $quoted_escape . ')?)(' . implode( '|', $quoted_wildcards) . ')';

// Escape the regex delimiter if it present within the regex
$wildcard_replacement_regex = $delimiter . str_replace( $delimiter, '\\' . $delimiter, $temp_regex) . $delimiter;

// Do the actual replacement
$regex = preg_replace_callback( $wildcard_replacement_regex, function( $matches) use( $wildcards) { return !empty( $matches[1]) ? preg_quote( $matches[2]) : $wildcards[$matches[2]]; }, preg_quote( $input)); 

// Finally, test the regex against the input $value, escaping the delimiter if it present
preg_match( $delimiter . str_replace( $delimiter, '\\' . $delimiter, $regex) . $delimiter .'i', $value, $matches);

// Output is in $matches[0] if there was a match
var_dump( $matches[0]);

$wildcards $escape, "" PCRE, "" escape-, . $wildcard_replacement_regex.

$wildcard_replacement_regex , :

/((?:\!)?)(%|_)/

() escape- . , escape . escape , $matches[1] escape-. , $matches[1] . , PCRE , preg_quote() - .

.

+4

regexp, : preg_match.

+1

( ), :

public function like($needle, $haystack, $delimiter = '~')
{
    // Escape meta-characters from the string so that they don't gain special significance in the regex
    $needle = preg_quote($needle, $delimiter);

    // Replace SQL wildcards with regex wildcards
    $needle = str_replace('%', '.*?', $needle);
    $needle = str_replace('_', '.', $needle);

    // Add delimiters, beginning + end of line and modifiers
    $needle = $delimiter . '^' . $needle . '$' . $delimiter . 'isu';

    // Matches are not useful in this case; we just need to know whether or not the needle was found.
    return (bool) preg_match($needle, $haystack);
}

Modifiers:

  • i: .
  • s: , .
  • u: UTF-8.
0
source

All Articles