Needle is in haystack but barn door is jammed shut! - php

The test below returns false ($pos = 0) when $haystack = "my keyword" and $needle = "my keyword", presumably because my stripos test returns 0 since there is no empty space in the barn.
What do I need to change in the comparison to return true in this case?
function my_test($post){
if($post->post_title == "") return false;
$haystack = my_esc2($post->post_title);
$needle = trim(my_getKeyword($post));
$pos = stripos($haystack, $needle);
if ($pos !== false) return true;
//returns 0 when $needle and $haystack are the same exact phrase. but should return 1
}
function my_getKeyword($post)
{
$myKeyword = get_post_meta($post->ID, '_my_keyword', true);
if($myKeyword == "") $myKeyword = $post->post_title;
$myKeyword = my_esc($myKeyword);
return " ".$myKeyword;
}
function my_esc($str, $quotation='"') {
if ($quotation != '"' && $quotation != "'") return false;
return str_replace($quotation, $quotation.$quotation, $str);
}
function my_esc2($str, $quotation='"') {
if ($quotation != '"' && $quotation != "'") return false;
return str_replace($quotation, '', $str);
}

If both strings are the same, stripos is supposed to return 0 as 0 is the position in the string where the match if found.
However, you are using the !== operator, so that test should return true anyway (by the way, you can just use return ($pos !== false)).
Are you sure you are getting to that statement, can you echo both $haystack and $needle right before the return statement?
It seems to me that haystack and needle are not the same or needle is not found or ($post->post_title == "")...

Related

How can I check a string for multiple certain characters?

I have a string and I need to check it for several characters. I can do that with strpos();. But in this case, I would need to use strpose(); several times. something like this:
$str = 'this is a test';
if(
strpos($str, "-") === false &&
strpos($str, "_") === false &&
strpos($str, "#") === false &&
strpos($str, "/") === false &&
strpos($str, "'") === false &&
strpos($str, "]") === false &&
strpos($str, "[") === false &&
strpos($str, "#") === false &&
strpos($str, "&") === false &&
strpos($str, "*") === false &&
strpos($str, "^") === false &&
strpos($str, "!") === false &&
strpos($str, "?") === false &&
strpos($str, "{") === false &&
strpos($str, "}") === false
)
{ do stuff }
Now I want to know, is it possible to use a regex to define my condition summary?
Edit: here is some examples:
$str = 'foo' ----I want this output---> true
$str = 'foo!' -------------------------> false
$str = '}foo' -------------------------> false
$str = 'foo*bar' -------------------------> false
and so on. In other word, I want just text character: abcdefghi... .
You could use a basic regex:
$unwantedChars = ['a', '{', '}'];
$testString = '{a}sdf';
if(preg_match('/[' . preg_quote(implode(',', $unwantedChars)) . ']+/', $testString)) {
print "Contains invalid characters!";
} else {
print "OK";
}
Use negative lookahead assertion.
if (preg_match("~^(?!.*?[-_^?}{\]\[/'#*&#])~", $str) ){
// do stuff
}
This will do the stuff inside braces only if the string won't contain anyone of the mentioned characters.
If you want the string to contain only word chars and spaces.
if (preg_match("~^[\w\h]+$~", $str)){
// do stuff
}
or
AS #Reizer metioned,
if(preg_match("~^[^_#/'\]\[#&*^!?}{-]*$~", $str)){
Replace the * (present next to the character class) in the above with +, if you don't want to match an empty string.
For only alphabets and spaces.
if(preg_match("~^[a-z\h]+$~i", $str) ){
May be something like that:
function strpos_multi(array $chars, $str) {
foreach($chars as $char) {
if (strpos($str, $char) !== false) {
return false;
}
}
return true;
}
$res = strpos_multi(["-", "_", "#", "/", "'", "]", "[", "#", "&", "*", "^", "!", "?", "{", "}"], $str);
if ($res) {
//do some stuff
}

Function returning boolean only returns false

I've a simple function that apprently puts me up with a lot of trouble. The function is:
function valid_mail($email) {
$atpointers = strstr($email, "#");
$spacepointers = count(explode(" ", $email));
$dotpointers = strstr($email, ".");
$ltpointers = strstr($email, "<");
$gtpointers = strstr($email, ">");
$illegalpts = $ltpointers + $gtpointers;
if($atpointers >= 2 || $dotpointers == 0 || strlen($email) <= 6 || $illegalpts >= 1) { return false; } else { return true; }
}
And calling it in the context:
if(valid_mail($email) === false) { // Code } else { // Code }
The problem is apparently it only returns false. Any ideas for why this happens ?
strstr returns a substr of the string being checked, not a length. Use strpos instead.

Checking if sentence contains a word in PHP

How can I check if a sentence contains a word. I used names sentence and word instead of string and substring expressly. For example:
for sentence
$s = "Ala makota, a kot ma przesrane";
calling function
checkIfContains("kota",$s)
returns false.
But for
checkIfContains("makota",$s)
returns true.
If you're looking to match only full words, you'll need a regular expression to accomplish this. Try the following:
<?php
function checkIfContains( $needle, $haystack ) {
return preg_match( '#\b' . preg_quote( $needle, '#' ) . '\b#i', $haystack ) !== 0;
}
You need strpos.
if (strpos($s, 'kota') !== false) {
}
Or if you insist..
function checkIfContains($needle, $haystack) {
return (strpos($haystack, $needle) !== false);
}
For full words you could consider regex:
if (preg_match('/\bkota\b/i', $s)) { }
I'd use explode to separate the string into an array based on a character (" " in this case).
function checkIfContains($toTest, $toCheck)
{
// Check if length of either string is zero for validation purposes
if(strlen($toTest) == 0 || strlen($toCheck) == 0)
{
return false;
}
$exploded = explode(" ", $toCheck);
foreach($exploded as $word)
{
if($word == $toTest)
{
// Found a match, return true!
return true;
}
}
// None matched, return false
return false;
}
You can try :
function checkIfContains($needle, $haystack) {
// Remove punctuation marks
$haystack = preg_replace('/[^a-zA-Z 0-9]+/', '', $haystack);
// Explode sentence with space
$haystack = explode(' ', $haystack);
// Check if $needle exist
return in_array($needle, $haystack);
}
$string = "Ala makota, a kot ma przesrane";
checkIfInString("makota", $string);
function checkIfInString($needle, $haystack) {
$delimiters = ' ,.';
return in_array($needle, explode($haystack, $delimiters);
}
you can try like :
if(strpos($s,"kota") !== false){
echo true;
}
or :
function checkIfContains($string, $letter){
return strpos($string, $letter) !== false;
}

find the multiple occurance of a substring in a string

I want to get the position of a sub string from a string using php. I can use strpos(), but it returns only first occurrence. How can I get the positions of multiple occurrence.
From: http://www.php.net/manual/en/function.strpos.php#108426
function strpos_r($haystack, $needle)
{
if(strlen($needle) > strlen($haystack))
trigger_error(sprintf("%s: length of argument 2 must be <= argument 1", __FUNCTION__), E_USER_WARNING);
$seeks = array();
while($seek = strrpos($haystack, $needle))
{
array_push($seeks, $seek);
$haystack = substr($haystack, 0, $seek);
}
return $seeks;
}
This will return an array with the position of occurences.
From the manual, there are such functions in the comments.
function strpos_recursive($haystack, $needle, $offset = 0, &$results = array()) {
$offset = strpos($haystack, $needle, $offset);
if($offset === false) {
return $results;
} else {
$results[] = $offset;
return strpos_recursive($haystack, $needle, ($offset + 1), $results);
}
}
Third parameter of strpos, has a $offset you can use:
$positions_of_string = array();
$str_to_find = "string to find";
$str_length = strlen( $str_to_find );
$last_found = 0 - $str_length;
while( false !== $last_found ) {
$last_found = strpos( $the_string, $str_to_find, $last_found+$str_length );
if( false !== $last_found )
$positions_of_strings[] = $last_found;
}

Using an array as needles in strpos

How do you use the strpos for an array of needles when searching a string? For example:
$find_letters = array('a', 'c', 'd');
$string = 'abcdefg';
if(strpos($string, $find_letters) !== false)
{
echo 'All the letters are found in the string!';
}
Because when using this, it wouldn't work, it would be good if there was something like this
#Dave an updated snippet from http://www.php.net/manual/en/function.strpos.php#107351
function strposa($haystack, $needles=array(), $offset=0) {
$chr = array();
foreach($needles as $needle) {
$res = strpos($haystack, $needle, $offset);
if ($res !== false) $chr[$needle] = $res;
}
if(empty($chr)) return false;
return min($chr);
}
How to use:
$string = 'Whis string contains word "cheese" and "tea".';
$array = array('burger', 'melon', 'cheese', 'milk');
if (strposa($string, $array, 1)) {
echo 'true';
} else {
echo 'false';
}
will return true, because of array "cheese".
Update: Improved code with stop when the first of the needles is found:
function strposa(string $haystack, array $needles, int $offset = 0): bool
{
foreach($needles as $needle) {
if(strpos($haystack, $needle, $offset) !== false) {
return true; // stop on first true result
}
}
return false;
}
$string = 'This string contains word "cheese" and "tea".';
$array = ['burger', 'melon', 'cheese', 'milk'];
var_dump(strposa($string, $array)); // will return true, since "cheese" has been found
str_replace is considerably faster.
$find_letters = array('a', 'c', 'd');
$string = 'abcdefg';
$match = (str_replace($find_letters, '', $string) != $string);
The below code not only shows how to do it, but also puts it in an easy to use function moving forward. It was written by "jesda". (I found it online)
PHP Code:
<?php
/* strpos that takes an array of values to match against a string
* note the stupid argument order (to match strpos)
*/
function strpos_arr($haystack, $needle) {
if(!is_array($needle)) $needle = array($needle);
foreach($needle as $what) {
if(($pos = strpos($haystack, $what))!==false) return $pos;
}
return false;
}
?>
Usage:
$needle = array('something','nothing');
$haystack = "This is something";
echo strpos_arr($haystack, $needle); // Will echo True
$haystack = "This isn't anything";
echo strpos_arr($haystack, $needle); // Will echo False
The question, is the provided example just an "example" or exact what you looking for? There are many mixed answers here, and I dont understand the complexibility of the accepted one.
To find out if ANY content of the array of needles exists in the string, and quickly return true or false:
$string = 'abcdefg';
if(str_replace(array('a', 'c', 'd'), '', $string) != $string){
echo 'at least one of the needles where found';
};
If, so, please give #Leon credit for that.
To find out if ALL values of the array of needles exists in the string, as in this case, all three 'a', 'b' and 'c' MUST be present, like you mention as your "for example"
echo 'All the letters are found in the string!';
Many answers here is out of that context, but I doubt that the intension of the question as you marked as resolved. E.g. The accepted answer is a needle of
$array = array('burger', 'melon', 'cheese', 'milk');
What if all those words MUST be found in the string?
Then you try out some "not accepted answers" on this page.
You can iterate through the array and set a "flag" value if strpos returns false.
$flag = false;
foreach ($find_letters as $letter)
{
if (strpos($string, $letter) !== false)
{
$flag = true;
}
}
Then check the value of $flag.
If you just want to check if certain characters are actually in the string or not, use strtok:
$string = 'abcdefg';
if (strtok($string, 'acd') === $string) {
// not found
} else {
// found
}
This expression searches for all letters:
count(array_filter(
array_map("strpos", array_fill(0, count($letters), $str), $letters),
"is_int")) == count($letters)
You can try this:
function in_array_strpos($word, $array){
foreach($array as $a){
if (strpos($word,$a) !== false) {
return true;
}
}
return false;
}
You can also try using strpbrk() for the negation (none of the letters have been found):
$find_letters = array('a', 'c', 'd');
$string = 'abcdefg';
if(strpbrk($string, implode($find_letters)) === false)
{
echo 'None of these letters are found in the string!';
}
This is my approach. Iterate over characters in the string until a match is found. On a larger array of needles this will outperform the accepted answer because it doesn't need to check every needle to determine that a match has been found.
function strpos_array($haystack, $needles = [], $offset = 0) {
for ($i = $offset, $len = strlen($haystack); $i < $len; $i++){
if (in_array($haystack[$i],$needles)) {
return $i;
}
}
return false;
}
I benchmarked this against the accepted answer and with an array of more than 7 $needles this was dramatically faster.
If i just want to find out if any of the needles exist in the haystack, i use
reusable function
function strposar($arrayOfNeedles, $haystack){
if (count(array_filter($arrayOfNeedles, function($needle) use($haystack){
return strpos($haystack, $needle) !== false;
})) > 0){
return true;
} else {
return false;
}
}
strposar($arrayOfNeedles, $haystack); //returns true/false
or lambda function
if (count(array_filter($arrayOfNeedles, function($needle) use($haystack){
return strpos($haystack, $needle) !== false;
})) > 0){
//found so do this
} else {
//not found do this instead
}
With the following code:
$flag = true;
foreach($find_letters as $letter)
if(false===strpos($string, $letter)) {
$flag = false;
break;
}
Then check the value of $flag. If it is true, all letters have been found. If not, it's false.
I'm writing a new answer which hopefully helps anyone looking for similar to what I am.
This works in the case of "I have multiple needles and I'm trying to use them to find a singled-out string". and this is the question I came across to find that.
$i = 0;
$found = array();
while ($i < count($needle)) {
$x = 0;
while ($x < count($haystack)) {
if (strpos($haystack[$x], $needle[$i]) !== false) {
array_push($found, $haystack[$x]);
}
$x++;
}
$i++;
}
$found = array_count_values($found);
The array $found will contain a list of all the matching needles, the item of the array with the highest count value will be the string(s) you're looking for, you can get this with:
print_r(array_search(max($found), $found));
Reply to #binyamin and #Timo.. (not enough points to add a comment..) but the result doesn't contain the position..
The code below will return the actual position of the first element which is what strpos is intended to do. This is useful if you're expecting to find exactly 1 match.. If you're expecting to find multiple matches, then position of first found may be meaningless.
function strposa($haystack, $needle, $offset=0) {
if(!is_array($needle)) $needle = array($needle);
foreach($needle as $query) {
$res=strpos($haystack, $query, $offset);
if($res !== false) return $res; // stop on first true result
}
return false;
}
Just an upgrade from above answers
function strsearch($findme, $source){
if(is_array($findme)){
if(str_replace($findme, '', $source) != $source){
return true;
}
}else{
if(strpos($source,$findme)){
return true;
}
}
return false;
}
<?php
$Words = array("hello","there","world");
$c = 0;
$message = 'Hi hello';
foreach ($Words as $word):
$trial = stripos($message,$word);
if($trial != true){
$c++;
echo 'Word '.$c.' didnt match <br> <br>';
}else{
$c++;
echo 'Word '.$c.' matched <br> <br>';
}
endforeach;
?>
I used this kind of code to check for hello, It also Has a numbering feature.
You can use this if you want to do content moderation practices in websites that need the user to type

Categories