-
Notifications
You must be signed in to change notification settings - Fork 6
/
phpLIKE.php
94 lines (86 loc) · 3.06 KB
/
phpLIKE.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<?php
/*
// Program : PHP equivalent of MySQL LIKE operator
// Author : Ap.Muthu <apmuthu@usa.net>
// Version : 1.0
// Release Date : 2021-03-08
// Return Value : Boolean
// Reference : https://stackoverflow.com/questions/4912294/php-like-thing-similar-to-mysql-like-for-if-statement
// Usage Notes : Unicode aware
// like('Hello 🙃', 'Hello _'); // true
// like('Hello 🙃', '_e%o__'); // true
// like('asdfas \\🙃H\\\\%🙃É\\l\\_🙃\\l\\o asdfasf', '%' . escapeLike('\\🙃h\\\\%🙃e\\l\\_🙃\\l\\o') . '%'); // true
*/
/**
* Removes the diacritical marks from a string.
*
* Diacritical marks: {@link https://unicode-table.com/blocks/combining-diacritical-marks/}
*
* @param string $string The string from which to strip the diacritical marks.
* @return string Stripped string.
*/
function stripDiacriticalMarks($string) {
return preg_replace('/[\x{0300}-\x{036f}]/u', '', \Normalizer::normalize($string, \Normalizer::FORM_KD));
}
/**
* Escapes a string in a way that `UString::like` will match it as-is, thus '%' and '_'
* would match a literal '%' and '_' respectively (and not behave as in a SQL LIKE
* condition).
*
* @param string $str The string to escape.
* @return string The escaped string.
*/
function escapeLike($str) {
return strtr($str, ['\\' => '\\\\', '%' => '\%', '_' => '\_']);
}
/**
* Checks if the string $haystack is like $needle, $needle can contain '%' and '_'
* characters which will behave as if used in a SQL LIKE condition. Character escaping
* is supported with '\'.
*
* @param string $haystack The string to check if it is like $needle.
* @param string $needle The string used to check if $haystack is like it.
* @param bool $ai Whether to check likeness in an accent-insensitive manner.
* @param bool $ci Whether to check likeness in a case-insensitive manner.
* @return bool True if $haystack is like $needle, otherwise, false.
*/
function like($haystack, $needle, $ai = true, $ci = true) {
if ($ai) {
$haystack = stripDiacriticalMarks($haystack);
$needle = stripDiacriticalMarks($needle);
}
$needle = preg_quote($needle, '/');
$tokens = Array();
$needleLength = strlen($needle);
for ($i = 0; $i < $needleLength;) {
if ($needle[$i] === '\\') {
$i += 2;
if ($i < $needleLength) {
if ($needle[$i] === '\\') {
$tokens[] = '\\\\';
$i += 2;
} else {
$tokens[] = $needle[$i];
++$i;
}
} else {
$tokens[] = '\\\\';
}
} else {
switch ($needle[$i]) {
case '_':
$tokens[] = '.';
break;
case '%':
$tokens[] = '.*';
break;
default:
$tokens[] = $needle[$i];
break;
}
++$i;
}
}
return preg_match('/^' . implode($tokens) . '$/u' . ($ci ? 'i' : ''), $haystack) === 1;
}
?>