PHP: Check if string is part of an array - php

I'm working on my little ticketing-system based on PHP.
Now I would like to exclude senders from being processed.
This is a possible list of excluded senders:
Array (
"badboy#example.com",
"example.org",
"spam#spamming.org"
)
Okay - now I would like to check if the sender of an mail matches one of these:
$sender = "badboy#example.com";
I think this is quite easy, I think I could solve this with in_array().
But what about
$sender = "me#example.org";
example.org is defined in the array, but not me#example.org - but me#example.org should also excluded, because example.org is in the forbidden-senders-list.
How could I solve this?

Maybe you are looking for stripos function.
<?php
if (!disallowedEmail($sender)) { // Check if email is disallowed
// Do your stuff
}
function disallowedEmail($email) {
$disallowedEmails = array (
"badboy#example.com",
"example.org",
"spam#spamming.org"
)
foreach($disallowedEmails as $disallowed){
if ( stripos($email, $disallowed) !== false)
return true;
}
return false
}

Another short alternative with stripos, implode and explode functions:
$excluded = array(
"badboy#example.com",
"example.org",
"spam#spamming.org"
);
$str = implode(",", $excluded); // compounding string with excluded emails
$sender = "www#example.com";
//$sender = "me#example.org";
$domainPart = explode("#",$sender)[1]; // extracting domain part from a sender email
$isAllowed = stripos($str, $sender) === false && stripos($str, $domainPart) === false;
var_dump($isAllowed); // output: bool(false)

Related

Most efficient way to check if array element exists in string

I've been looking for a way to check if any of an array of values exists in a string, but it seems that PHP has no native way of doing this, so I've come up with the below.
My question - is there a better way of doing this, as this seems pretty inefficient? Thanks.
$match_found = false;
$referer = wp_get_referer();
$valid_referers = array(
'dd-options',
'dd-options-footer',
'dd-options-offices'
);
/** Loop through all referers looking for a match */
foreach($valid_referers as $string) :
$referer_valid = strstr($referer, $string);
if($referer_valid !== false) :
$match_found = true;
continue;
endif;
endforeach;
/** If there were no matches, exit the function */
if(!$match_found) :
return false;
endif;
Try with following function:
function contains($input, array $referers)
{
foreach($referers as $referer) {
if (stripos($input,$referer) !== false) {
return true;
}
}
return false;
}
if ( contains($referer, $valid_referers) ) {
// contains
}
What about this:
$exists = true;
array_walk($my_array, function($item, $key) {
$exists &= (strpos($my_string, $item) !== FALSE);
});
var_dump($exists);
This will check if any of the array values exists in the string. If only one is missing, You are given a false response. Should You need to find out which one are not present in the string, try this:
$exists = true;
$not_present = array();
array_walk($my_array, function($item, $key) {
if(strpos($my_string, $item) === FALSE) {
$not_present[] = $item;
$exists &= false;
} else {
$exists &= true;
}
});
var_dump($exists);
var_dump($not_present);
First of, alternate syntax is nice to use, but historically it's used in template files. Since it's structure is easily readable while coupling/decouping the PHP interpreter to interpolate HTML data.
Second, it's generally wise if all your code does is to check something, to immediately return if that condition is met:
$match_found = false;
$referer = wp_get_referer();
$valid_referers = array(
'dd-options',
'dd-options-footer',
'dd-options-offices'
);
/** Loop through all referers looking for a match */
foreach($valid_referers as $string) :
$referer_valid = strstr($referer, $string);
if($referer_valid !== false) :
$match_found = true;
break; // break here. You already know other values will not change the outcome
endif;
endforeach;
/** If there were no matches, exit the function */
if(!$match_found) :
return false;
endif;
// if you don't do anything after this return, it's identical to doing return $match_found
Now as specified by some of the other posts in this thread. PHP has a number of functions that can help. Here's a couple more:
in_array($referer, $valid_referers);// returns true/false on match
$valid_referers = array(
'dd-options' => true,
'dd-options-footer' => true,
'dd-options-offices' => true
);// remapped to a dictionary instead of a standard array
isset($valid_referers[$referer]);// returns true/false on match
Ask if you have any questions.

Filter a set of bad words out of a PHP array

I have a PHP array of about 20,000 names, I need to filter through it and remove any name that has the word job, freelance, or project in the name.
Below is what I have started so far, it will cycle through the array and add the cleaned item to build a new clean array. I need help matching the "bad" words though. Please help if you can
$data1 = array('Phillyfreelance' , 'PhillyWebJobs', 'web2project', 'cleanname');
// freelance
// job
// project
$cleanArray = array();
foreach ($data1 as $name) {
# if a term is matched, we remove it from our array
if(preg_match('~\b(freelance|job|project)\b~i',$name)){
echo 'word removed';
}else{
$cleanArray[] = $name;
}
}
Right now it matches a word so if "freelance" is a name in the array it removes that item but if it is something like ImaFreelaner then it does not, I need to remove anything that has the matching words in it at all
A regular expression is not really necessary here — it'd likely be faster to use a few stripos calls. (Performance matters on this level because the search occurs for each of the 20,000 names.)
With array_filter, which only keeps elements in the array for which the callback returns true:
$data1 = array_filter($data1, function($el) {
return stripos($el, 'job') === FALSE
&& stripos($el, 'freelance') === FALSE
&& stripos($el, 'project') === FALSE;
});
Here's a more extensible / maintainable version, where the list of bad words can be loaded from an array rather than having to be explicitly denoted in the code:
$data1 = array_filter($data1, function($el) {
$bad_words = array('job', 'freelance', 'project');
$word_okay = true;
foreach ( $bad_words as $bad_word ) {
if ( stripos($el, $bad_word) !== FALSE ) {
$word_okay = false;
break;
}
}
return $word_okay;
});
I'd be inclined to use the array_filter function and change the regex to not match on word boundaries
$data1 = array('Phillyfreelance' , 'PhillyWebJobs', 'web2project', 'cleanname');
$cleanArray = array_filter($data1, function($w) {
return !preg_match('~(freelance|project|job)~i', $w);
});
Use of the preg_match() function and some regular expressions should do the trick; this is what I came up with and it worked fine on my end:
<?php
$data1=array('JoomlaFreelance','PhillyWebJobs','web2project','cleanname');
$cleanArray=array();
$badWords='/(job|freelance|project)/i';
foreach($data1 as $name) {
if(!preg_match($badWords,$name)) {
$cleanArray[]=$name;
}
}
echo(implode($cleanArray,','));
?>
Which returned:
cleanname
Personally, I would do something like this:
$badWords = ['job', 'freelance', 'project'];
$names = ['JoomlaFreelance', 'PhillyWebJobs', 'web2project', 'cleanname'];
// Escape characters with special meaning in regular expressions.
$quotedBadWords = array_map(function($word) {
return preg_quote($word, '/');
}, $badWords);
// Create the regular expression.
$badWordsRegex = implode('|', $quotedBadWords);
// Filter out any names that match the bad words.
$cleanNames = array_filter($names, function($name) use ($badWordsRegex) {
return preg_match('/' . $badWordsRegex . '/i', $name) === FALSE;
});
This should be what you want:
if (!preg_match('/(freelance|job|project)/i', $name)) {
$cleanArray[] = $name;
}

How to return a boolean if a string contains one of an array of substrings?

I'm struggling with a simple function that loops through an array and returns true only if it finds a given substring in one of the array's elements.
For some reason, I'm ALWAYS getting false... even when the $email parameter is contains one of the valid domains. Ex: scoobydoo#domain1.com.
function check_email($email) {
$whitelist_domains = array(
'#domain1.com',
'#domain2.com',
'#domain3.com'
);
$output = FALSE;
foreach ($whitelist_domains as $domain) {
$pos = strpos( $email, $domain );
if ( $pos ) {
$output = TRUE;
}
}
return $output;
}
you are not breaking the loop if you find the domain, so what you are getting is actually the result for the LAST string checked only.
just add break; after $output = TRUE;
From the official doc of strpos:
Warning
This function may return Boolean FALSE, but may also return a
non-Boolean value which evaluates to FALSE. Please read the section on
Booleans for more information. Use the === operator for testing the
return value of this function.
And make sure to add a break after you set $output to true.
This is a good function to use the === operator with as it makes sure the value and type are equal (1==true, but 1!==true)
if (strpos( $email, $domain )!==false) {
$output = TRUE;
}
Change
if ( $pos ) {
to
if ( $pos !== false) {
this is because is strpos returns 0, that will equate to false, even though the string was found.
Here are two direct/common methods that have different advantages:
Method #1: non-regex approach
function check_email1($email){
$whitelist_domains=['#domain1.com','#domain2.com','#domain3.com'];
foreach($whitelist_domains as $domain){
if(strpos($email,$domain)!==false){
return true; // allow quick return (exit loop & function asap)
}
}
return false; // default response
}
Method #2: regex approach
function check_email2($email){
$whitelist_pattern='/#(?:domain1\.com|domain2\.com|domain3\.com)$/'; // condense if possible /#domain[123]\.com$/
return (bool)preg_match($whitelist_pattern,$email); // convert 0 or 1 output to boolean (false/true)
}
Demo Link
Input / Function Call:
$emails=['user#domain1.com','bad#bad.com'];
foreach($emails as $email){
echo "$email\n";
var_export(check_email1($email));
echo "\n";
var_export(check_email2($email));
echo "\n\n";
}
Output:
user#domain1.com
true
true
bad#bad.com
false
false
Advantages/Disadvantages:
strpos() in the majority of situations will outperform regex functions. Your default method should be to use string functions and only change to regex when string functions are less efficient or too convoluted to code. A related page: Which is more efficient, PHP string functions or regex in PHP?
Looping $whitelist_domains in #1 makes for a clunkier looking code block compared to #2 (which can be condensed to a one-liner if you write the pattern directly into preg_match()).
Simple/common mistakes sometimes occur when dealing with strpos(). These mistakes may include:
not checking for false in the if condition
writing the haystack and needle in the wrong order
#2 does require some knowledge about regex (escaping, character classes, alternatives, etc.) which can be a deterrent for inexperienced coders. Depending on how you write your regex pattern and how many domains will be whitelisted, #2 is likely to be harder to maintain than #1.
#2 has the added benefit of being able to check that the domain.com substring appears at the end of the word via the $ metacharacter. For this reason, regex offers stronger validation.
You should change your code in this:
function check_email($email) {
$whitelist_domains = array(
'#domain1.com',
'#domain2.com',
'#domain3.com'
);
foreach ($whitelist_domains as $domain) {
if ( strpos( $email, $domain ) !== false ) {
return true;
}
}
return false;
}
Documentation of strpos
Quoting from the manual (http://php.net/manual/en/function.strpos.php):
The !== operator can also be used. Using != would not work as expected
because the position of 'a' is 0. The statement (0 != false) evaluates
to false.
Example code
<?php
$mystring = 'abc';
$findme = 'a';
$pos = strpos($mystring, $findme);
// The !== operator can also be used. Using != would not work as expected
// because the position of 'a' is 0. The statement (0 != false) evaluates
// to false.
if ($pos !== false) {
echo "The string '$findme' was found in the string '$mystring'";
echo " and exists at position $pos";
} else {
echo "The string '$findme' was not found in the string '$mystring'";
}
?>

Match Array Values to URL String

I have an array:
$blacklist = array("asdf.com", "fun.com", "url.com");
I have an input string:
$input = "http://asdf.com/asdf/1234/";
I am trying to see if string $input matches any values in $blacklist.
How do I accomplish this?
Sounds like a decent use for parse_url():
<?php
$blacklist = array("asdf.com", "fun.com", "url.com");
$input = "http://asdf.com/asdf/1234/";
$url = parse_url($input);
echo (in_array($url['host'], $blacklist) ? '(FAIL)' : '(PASS)') . $url ['host'];
?>
Output:
(FAIL)asdf.com
Using foreach is probably the best solution for what you're trying to achieve.
$blacklist = array("/asdf\.com/", "/fun\.com/", "/url\.com/");
foreach($blacklist as $bl) {
if (preg_match($bl, $input)){return true;}
}
One way could be (but I didn't measure performance):
$san = preg_replace($blacklist, '', $input);
if($san !== $input) {
//contained something from the blacklist
}
If the input does not contain any string from the backlist, the string will be returned unchanged.
An other, maybe better suited and definitely more efficient approach could be to extract the host part from the input and create the blacklist as associative array:
$blacklist = array(
"asdf.com" => true,
"fun.com" => true,
"url.com" => true
);
Then testing would be O(1) with:
if($blacklist[$host]) {
//contained something from the blacklist
}
in_array is of no use, as it searches for the exact string.
You have to loop through the array, and search for it
foreach($str in $blacklist)
{
if( stristr($input, $str ) )
{
//found
}
}
This code should work:
$blacklist = array("asdf.com", "fun.com", "url.com");
$input = "http://asdf.com/asdf/1234/";
if (in_array(parse_url($input,PHP_URL_HOST),$blacklist))
{
// The website is in the blacklist.
}

How to find a value in an array and remove it by using PHP array functions?

How to find if a value exists in an array and then remove it? After removing I need the sequential index order.
Are there any PHP built-in array functions for doing this?
<?php
$my_array = array('sheldon', 'leonard', 'howard', 'penny');
$to_remove = array('howard');
$result = array_diff($my_array, $to_remove);
?>
To search an element in an array, you can use array_search function and to remove an element from an array you can use unset function. Ex:
<?php
$hackers = array ('Alan Kay', 'Peter Norvig', 'Linus Trovalds', 'Larry Page');
print_r($hackers);
// Search
$pos = array_search('Linus Trovalds', $hackers);
// array_seearch returns false if an element is not found
// so we need to do a strict check here to make sure
if ($pos !== false) {
echo 'Linus Trovalds found at: ' . $pos;
// Remove from array
unset($hackers[$pos]);
}
print_r($hackers);
You can refer: https://www.php.net/manual/en/ref.array.php for more array related functions.
You need to find the key of the array first, this can be done using array_search()
Once done, use the unset()
<?php
$array = array( 'apple', 'orange', 'pear' );
unset( $array[array_search( 'orange', $array )] );
?>
Just in case you want to use any of mentioned codes, be aware that array_search returns FALSE when the "needle" is not found in "haystack" and therefore these samples would unset the first (zero-indexed) item. Use this instead:
<?php
$haystack = Array('one', 'two', 'three');
if (($key = array_search('four', $haystack)) !== FALSE) {
unset($haystack[$key]);
}
var_dump($haystack);
The above example will output:
Array
(
[0] => one
[1] => two
[2] => three
)
And that's good!
You can use array_filter to filter out elements of an array based on a callback function. The callback function takes each element of the array as an argument and you simply return false if that element should be removed. This also has the benefit of removing duplicate values since it scans the entire array.
You can use it like this:
$myArray = array('apple', 'orange', 'banana', 'plum', 'banana');
$output = array_filter($myArray, function($value) { return $value !== 'banana'; });
// content of $output after previous line:
// $output = array('apple', 'orange', 'plum');
And if you want to re-index the array, you can pass the result to array_values like this:
$output = array_values($output);
This solution is the combination of #Peter's solution for deleting multiple occurences and #chyno solution for removing first occurence. That's it what I'm using.
/**
* #param array $haystack
* #param mixed $value
* #param bool $only_first
* #return array
*/
function array_remove_values(array $haystack, $needle = null, $only_first = false)
{
if (!is_bool($only_first)) { throw new Exception("The parameter 'only_first' must have type boolean."); }
if (empty($haystack)) { return $haystack; }
if ($only_first) { // remove the first found value
if (($pos = array_search($needle, $haystack)) !== false) {
unset($haystack[$pos]);
}
} else { // remove all occurences of 'needle'
$haystack = array_diff($haystack, array($needle));
}
return $haystack;
}
Also have a look here: PHP array delete by value (not key)
The unset array_search has some pretty terrible side effects because it can accidentally strip the first element off your array regardless of the value:
// bad side effects
$a = [0,1,2,3,4,5];
unset($a[array_search(3, $a)]);
unset($a[array_search(6, $a)]);
$this->log_json($a);
// result: [1,2,4,5]
// what? where is 0?
// it was removed because false is interpreted as 0
// goodness
$b = [0,1,2,3,4,5];
$b = array_diff($b, [3,6]);
$this->log_json($b);
// result: [0,1,2,4,5]
If you know that the value is guaranteed to be in the array, go for it, but I think the array_diff is far safer. (I'm using php7)
$data_arr = array('hello', 'developer', 'laravel' );
// We Have to remove Value "hello" from the array
// Check if the value is exists in the array
if (array_search('hello', $data_arr ) !== false) {
$key = array_search('hello', $data_arr );
unset( $data_arr[$key] );
}
# output:
// It will Return unsorted Indexed array
print( $data_arr )
// To Sort Array index use this
$data_arr = array_values( $data_arr );
// Now the array key is sorted
First of all, as others mentioned, you will be using the "array_search()" & the "unset()" methodsas shown below:-
<?php
$arrayDummy = array( 'aaaa', 'bbbb', 'cccc', 'dddd', 'eeee', 'ffff', 'gggg' );
unset( $arrayDummy[array_search( 'dddd', $arrayDummy )] ); // Index 3 is getting unset here.
print_r( $arrayDummy ); // This will show the indexes as 0, 1, 2, 4, 5, 6.
?>
Now to re-index the same array, without sorting any of the array values, you will need to use the "array_values()" method as shown below:-
<?php
$arrayDummy = array_values( $arrayDummy );
print_r( $arrayDummy ); // Now, you will see the indexes as 0, 1, 2, 3, 4, 5.
?>
Hope it helps.
Okay, this is a bit longer, but does a couple of cool things.
I was trying to filter a list of emails but exclude certain domains and emails.
Script below will...
Remove any records with a certain domain
Remove any email with an exact value.
First you need an array with a list of emails and then you can add certain domains or individual email accounts to exclusion lists.
Then it will output a list of clean records at the end.
//list of domains to exclude
$excluded_domains = array(
"domain1.com",
);
//list of emails to exclude
$excluded_emails = array(
"bob#domain2.com",
"joe#domain3.com",
);
function get_domain($email) {
$domain = explode("#", $email);
$domain = $domain[1];
return $domain;
}
//loop through list of emails
foreach($emails as $email) {
//set false flag
$exclude = false;
//extract the domain from the email
$domain = get_domain($email);
//check if the domain is in the exclude domains list
if(in_array($domain, $excluded_domains)){
$exclude = true;
}
//check if the domain is in the exclude emails list
if(in_array($email, $excluded_emails)){
$exclude = true;
}
//if its not excluded add it to the final array
if($exclude == false) {
$clean_email_list[] = $email;
}
$count = $count + 1;
}
print_r($clean_email_list);
To find and remove multiple instance of value in an array, i have used the below code
$list = array(1,3,4,1,3,1,5,8);
$new_arr=array();
foreach($list as $value){
if($value=='1')
{
continue;
}
else
{
$new_arr[]=$value;
}
}
print_r($new_arr);

Categories