Checking for multiple characters in multiple variables

Hi,

I am using a check to see if $var1, $var2 and $var3 contain $char1, $char2, $char3.

I am using the following if statement to do this check:

if ((strpos($var1, $char1) !== false) || (strpos($var1, $char2) !== false) || (strpos($var1, $char3) !== false) || (strpos($var2, $char1) !== false) || (strpos($var2, $char2) !== false) || (strpos($var2, $char3) !== false) || (strpos($var3, $char1) !== false) || (strpos($var3, $char2) !== false) || (strpos($var3, $char3) !== false))

I was wondering if there is a more practical (shorter) way to do this, maybe with an array, as the number of variables and characters I need to check may increase later on.

Thanks for ideas.

Definitely. The following isn’t the most efficient, but I think is pretty easy to follow:

/**
 * Returns an array of blacklisted strings
 * - A string is blacklisted only if it contains a substring
 * @param  [STR/ARR] $blacklist Either a string of characters to blacklist, or an array of substrings to blacklist
 * @param  [STR/ARR] $strings   Either a string to check against, or a list of strings to check against
 * @return [BOOL]            	Whether one of the strings is blacklisted
 */
function blacklisted($blacklist, $strings){
	# Make $blacklist and $strings loopable
	if(is_string($blacklist))
		$blacklist = str_split($blacklist);
	if(is_string($strings))
		$strings = str_split($strings);

	# Compare each substring to each string
	foreach($blacklist as $checkedBlack){
		foreach($strings as $checkedStr){
			if(strpos($checkedStr, $checkedBlack) !== false)
				return true;
		}
	}

	return false;
}

Instead of doing a crazy manual, matrix comparison as you are now, simply pass in a list of blacklisted characters or an array of blacklisted substrings with a string or or list of strings to try and blacklist.

You then use it like this:

$vars = array('site', 'point', 'rules');
if(blacklisted('aeiou', $vars)){echo 'Has vowels';}     # This will get called because each of the $vars has a vowel
if(blacklisted('jqz', $vars)){echo 'Has j, q, or z';}   # this will not get called, because none of the $vars has j, q, or z

The great thing about building helper functions like this is that they are reusable. If you really want to get fancy, you can use a combination of array functions, which could potentially reduce all that to a line or two.

1 Like

Or you could just use the existing PHP functions.

if(count(preg_grep("~char1|char2|char3~",array($var1,$var2,$var3))) > 0) { //one of the chars was in one (or more) of the vars.
2 Likes

Womp womp…wow I didn’t know of preg_grep, definitely just go with that haha!

Sometimes it’s not about knowing all the functions, but how to hook-and-crook your way into getting them to do what you want :wink: preg_grep is designed to find pattern matches in an array; but with careful manipulation of the regex pattern, you can make it fit the find-one-of-many-chars function.

Thanks, I tried to make it work but couldn’t. The characters I check are double quotes ("), single quotes (') and backslash (\). Tried

if (count(preg_grep("~\"|'|\~", array($var1, $var2, $var3))) > 0)

and it gives the error:

Warning: preg_grep(): No ending delimiter ‘~’ found in…

errrm, you’ve escaped it with the backslash

I also tried

if (count(preg_grep("~\"|'|\\~", array($var1, $var2, $var3))) > 0)

which didn’t work too. I need the check for double quote, single quote and backslash.

Because we’re talking about single-character matching, we can actually simplify the pattern further than what i posted above.

Believe you’ll find the pattern: "~[\"\\']~" matches what you’re looking for. (\" , \\, ')

1 Like

Thanks. Tried

if (count(preg_grep("~[\"\\']~", array($var1, $var2, $var3))) > 0)

It catches double quotes and single quotes but not the backslash.

You may need to use this pattern "~[\"\\\\']~" to ensure that it matches a backslash. This was taken from the PHP documenation on Escape sequences.

Thanks, but I guess that covers the case where you need to match two backslashes consequently (\\). I need to match just one backslash (\). I tried that anyway, and it didn’t work. I guess I will continue with the long if statement I have in the first post.

For whatever reason (the logic escapes me atm), I find that you actually need -3- slashes to match a backslash.

"~[\"\\\']~"

<?php
$var1 = "Moo";
$var2 = "Brown";
$var3 = "Cow";
if (count(preg_grep("~[\"\\\']~", array($var1, $var2, $var3))) > 0) { echo "1"; }
$var3 = "I've got a \" quote in me.";
if (count(preg_grep("~[\"\\\']~", array($var1, $var2, $var3))) > 0) { echo "2"; }
$var3 = "Good";
$var1 = 'Backslashes \ are a thing.';
if (count(preg_grep("~[\"\\\']~", array($var1, $var2, $var3))) > 0) { echo "3"; }
$var1 = "Done";
$var2 = "Single'quotes";
if (count(preg_grep("~[\"\\\']~", array($var1, $var2, $var3))) > 0) { echo "4"; }
$var2 = "Finale";
if (count(preg_grep("~[\"\\\']~", array($var1, $var2, $var3))) > 0) { echo "5"; }

Output: 234

1 Like

I definitely don’t mean to sound arrogant, but after seeing all the back and forth I’m going to resuggest the helper function as it’s pretty open (you can pass strings or arrays of strings), compare characters or sub strings, works for the ", ', and , and at least for this case is much more readable:

function blacklisted($blacklist, $strings){
	# Make $blacklist and $strings loopable
	if(is_string($blacklist))
		$blacklist = str_split($blacklist);
	if(is_string($strings))
		$strings = str_split($strings);

	# Compare each substring to each string
	foreach($blacklist as $checkedBlack){
		foreach($strings as $checkedStr){
			if(strpos($checkedStr, $checkedBlack) !== false)
				return true;
		}
	}

	return false;
}
if(blacklisted([$char1, $char2, $char3], [$var1, $var2, $var3])){
	echo 'fail';
} else {
	echo 'pass';
}

The helper function way (whether you use regex or loops) is a little more future proof as well, because if later you decide that you also need to know which strings were bad you can easily just return those strings instead of just true/false without rewriting your logic. Even if you use regex, with a helper function you can just change preg_grep to another method.

1 Like

that’s because \' is not considered an escape sequence here.

Yeah but the \\ should have matched the backslash.

Thank you very much, finally got it working now.

Thanks for your contribution, I will keep your solution as an alternative just in case.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.