In PHP, how to compare two "alike" data? For instance, in this code:
$a = "cats are cool";
$b = "1. catS are cool!!!"
if($a == $b) {
echo "TRUE";
}
else {
echo "FALSE";
}
now the obvious output will be "FALSE". But to what I'm trying to achieve, as long as the keyword "cats are cool" is in $b, the result should be "TRUE". How do I do this?
If you are looking for an exact match, use stripos().
//Note the use of !== here, it's because stripos may return 0,
//Which would be interpreted as false without strict comparison.
if (stripos($string, "cats are cool") !== false) {
//Cats are cool indeed.
}
You have to define your own logic, period. Either you look for keywords [e.g. you search how many occurrences of your whitelist pop up in your strings], or you compute some string distance metric, like Levenshtein distance.
If you should find just first string in second you can use strpos
use stripos()
if(stripos($b,$a) !== FALSE)
echo "found";
else
echo "not found";
Related
I've noticed a strange thing about PHP's in_array function. For some reason, it will only check if the first character(s) of the needle match with any of the values of the haystack - as opposed to if the whole needle is in the haystack.
For example, in a situation where $string equals 1thisisatest, the following script will return In array.
$allowed = [0, 1];
if(in_array($string, $allowed)){
echo "In array";
} else {
echo "Not in array";
}
Whereas if $string equals 2thisatest, the script will return Not in array.
Now either this is a bug, or a very strange feature. Wouldn't you want it to check needles against the haystack exactly as they appear?
If this is, indeed, how the function is supposed to work, how does one go about getting the intended result without iterating over every single element in the array? Seems kind of pointless.
EDIT:
Some of you are saying to use strict mode. This is all fine and dandy, until you checking against $_GET data, which is always a string. So the following will return false:
$value = $_GET["value"]; // this returns "1"
in_array($value, [0, 1], true)
Because the in_array function uses the == operator. Thus 1 == "1thisisatest" - so, in_array will return true.
To fix this you can enabled strict mode:
// in the third parameter (to use === instead of ==)
in_array($search_value, $array_name, true)`
in_array by default uses == which will follow the rules of type juggling
The solution is to use strict comparison:
in_array($value, [0, 1], true);
If you are concerned about $_GET variables you need to ensure you always validate and sanitize your input before using it otherwise you might end up with strange results:
$value = filter_input(INPUT_GET, 'value', FILTER_VALIDATE_INT);
in_array($value, [0, 1], true);
It is always good to validate and sanitize your input to avoid things like e.g. someone calling your URL as ?value[]=1 which will mean $_GET['value'] will be an array causing (most likely) errors in the best case and strange undocumented behaviour in the worst case.
Make $allowed an array of strings and use strict mode.
$allowed = ["0", "1"];
if (in_array($_GET['value'], $allowed, true)) {
echo "In array";
} else {
echo "Not in array";
}
If you need to be more accurate you have to put the boolean true in your function like this:
$string = "1thisisatest";
$allowed = array(0, 1);
if(in_array($string, $allowed, true)){
echo "In array";
} else {
echo "Not in array";
}
I had the following in my code:
$mixed = array();
$mixed[0] = "It's a zero!";
$mixed['word'] = "It's a word!";
foreach ($mixed as $key => $value) {
if ($key == 'word') {
echo $value.'<br />';
}
}
The above would for some reason print both "It's a zero!" and "It's a word!". I was expecting it to print only "It's a word!". Why is that?? I feel like I am missing something important. When I was using === in the if statement, it worked as expected, in other words it printed only "It's a word!". I know there's a difference between the equal and identical operators, but the first example is not equal is it?
== does the type-conversion for you before comparison.
When you did an == with an integer 0, it converted 'word' into the appropriate integer value.
intval() returns 0 when supplied a pure-string, so 0 matched. The other was matched in string-context, and that matched as well.
=== does no such implicit conversion, so it returned true only in one case, when the strings were actually identical.
PHP variables have type.
== checkes equality after conversion to the same type, === also checks the type. Use var_dump to see what the real types are.
See #Cthulhu 's answer above which is much clear.
Apart from that, here is a different example.
strpos() function returns the position of the needle from haystack.
<?php
$pos_a = strpos('apple', 'a'); // a is in the first position.
$pos_b = strpos('apple', 'b'); // there is no b.
if ($pos_a){
echo 'we got a!'."\n";
}
if ($pos_b){
echo 'we got b!'."\n";
}
strpos return FALSE if the needle is not found. But you will see that php does not run any echo statement.
If you var_dumo()'d these 2 values, you will see that $pos_a and $pos_b contain 0 and FALSE.
if statement just failed because 0 and FALSE both are considered FALSE unless you use ===
Now try this:
<?php
$pos_a = strpos('apple', 'a'); // a is in the first position.
$pos_b = strpos('apple', 'b'); // there is no b.
if ($pos_a !== FALSE){
echo 'we got a!'."\n";
}
if ($pos_b !== FALSE){
echo 'we got b!'."\n";
}
Now you will see the desired result as it echos "we got a!".
$a == $b Equal TRUE if $a is equal to $b after type juggling.
$a === $b Identical TRUE if $a is equal to $b, and they are of the same type.
it looks that
if you check 0 against a string with == then PHP returns true:
php -r 'var_dump(0 == "statuses");'
-> returns TRUE
but not if your string has a number at the beginning:
php -r 'var_dump(0 == "2statuses");'
-> returns FALSE
from the specs I get it that it attempts a conversion - in this case the string to number.
so better use ===
http://php.net/manual/en/language.operators.comparison.php
I have a variable:
$testingAllDay = $event->when[0]->startTime;
This variable will be this format if it is "All Day":
2011-06-30
It will be this format if it is not "All Day":
2011-07-08T12:00:00.000-05:00
I'm wanting to do something like:
if ($testingAllDay does not contain "T"){
$AllDay = 1;
} else {
$AllDay = 0;
}
Do I need to use a strstr() here, or is there another function that does this? Thanks!
One option is to use strpos to see if the 'T' character is present in the string as follows:
if (strpos($testingAllDay, 'T') !== false) {
// 'T' was present in $testingAllDay
}
That said, it would probably be faster/more efficient (although no doubt meaninglessly so) to use strlen in this case, as according to your example, the time-free field will always be 10 characters long.
For example:
if(strlen($testingAllDay) > 10) {
// 'T' was present in $testingAllDay
}
Use strpos:
if (strpos($testingAllDay,"T")!==false){
or strstr
if (!strstr($testingAllDay,"T")){
if (strpos($testingAllDay, 'T') !== FALSE){
...
}
If those are the only possible cases, even strlen() will do.
not exactly answer to the question, but you could check with strlen().
i.e. "All Day" length is 10, anything above that is not.
The function you're looking for is strpos(). The following is an example picking up your wording for the variable names even:
$testingAllDayTPosition = strpos($testingAllDay, 'T');
$testingAllDayDoesNotContainT = false === $testingAllDayTPosition;
if ($testingAllDayDoesNotContainT){
$AllDay = 1;
} else {
$AllDay = 0;
}
strstr and strpos are two functions by which you can complete your requirement.
strstr will see if substring exists in string and it will echo from first occurrence of string to rest.
While strpos will give you position of first occurrence of the string.
I want to check if a variable has a number in it, I just want to see if there is one I don't care if it has any thing else in it like so:
"abc" - false
"!./#()" - false
"!./#()abc" - false
"123" - true
"abc123" - true
"!./#()123" - true
"abc !./#() 123" -true
There are easy ways of doing this if you want to know that is all numbers but not if it just has one. Thanks for your help.
You can use the strcspn function:
if (strcspn($_REQUEST['q'], '0123456789') != strlen($_REQUEST['q']))
echo "true";
else
echo "false";
strcspn returns the length of the part that does not contain any integers. We compare that with the string length, and if they differ, then there must have been an integer.
There is no need to invoke the regular expression engine for this.
$result = preg_match("/\\d/", $yourString) > 0;
Holding on to spirit of #Martin, I found a another function that works in similar fashion.
(strpbrk($var, '0123456789')
e.g. test case
<?php
function a($var) {
return (strcspn($var, '0123456789') != strlen($var));
}
function b($var) {
return (strpbrk($var, '0123456789'));
}
$var = array("abc", "!./#()", "!./#()abc", "123", "abc123", "!./#()123", "abc !./#() 123");
foreach ($var as $v) {
echo $v . ' = ' . b($v) .'<hr />';
}
?>
This should help you:
$numberOfNumbersFound = preg_match("/[0-9]+/", $yourString);
You could get more out of the preg_match function, so have a look at its manual
you can use this pattern to test your string using regular expressions:
$isNumeric = preg_match("/\S*\d+\S*/", $string) ? true : false;
The standard PHP way to test whether a string $str ends with a substring $test is:
$endsWith = substr( $str, -strlen( $test ) ) == $test
Is this the fastest way?
What Assaf said is correct. There is a built in function in PHP to do exactly that.
substr_compare($str, $test, strlen($str)-strlen($test), strlen($test)) === 0;
If $test is longer than $str PHP will give a warning, so you need to check for that first.
function endswith($string, $test) {
$strlen = strlen($string);
$testlen = strlen($test);
if ($testlen > $strlen) return false;
return substr_compare($string, $test, $strlen - $testlen, $testlen) === 0;
}
This method is a tiny bit more memory-expensive, but it is faster:
stripos(strrev($haystack), $reversed_needle) === 0;
This is best when you know exactly what the needle is, so you can hard-code it reversed. If you reverse the needle programmatically, it becomes slower than the earlier method.
Edit (12 years later): LOL, this is a super-old answer that I wrote when I didn't know what I was actually talking about. I'd like the think I've grown since then. #DavidHarkness is right, it is not very efficient in the negative case. Probably much faster to just iterate in reverse and bail early if you really need as much perf as possible. Also, php probably has better ways to do this now. Honestly, I haven't written php in nearly a decade, so I'll leave it up to others now.
$endsWith = substr_compare( $str, $test, -strlen( $test ) ) === 0
Negative offset "starts counting from the end of the string".
Here’s a simple way to check whether one string ends with another, by giving strpos an offset right where the string should be found:
function stringEndsWith($whole, $end)
{
return (strpos($whole, $end, strlen($whole) - strlen($end)) !== false);
}
Straightforward, and I think this’ll work in PHP 4.
It depends on which sort of efficiency you care about.
Your version uses more memory due to the extra copy from the use of substr.
An alternative version might search the original string for the last occurrence of the substring without making a copy, but would probably be slower due to more testing.
Probably the most efficient way is to do loop char-by-char from the -sterlen(test) position till the end of the string and compare. That's the minimal amount of comparisons you can hope to do and there's hardly any extra memory used.
In PHP 8:
str_ends_with('haystack', 'stack'); // true
str_ends_with('haystack', 'K'); // false
and also:
str_starts_with('haystack', 'hay'); // true
PHP RFC: Add str_starts_with(), str_ends_with() and related functions
Another way would be to use the strrpos function:
strrpos($str, $test) == strlen($str) - strlen($test)
But that’s not faster.
I hope that the below answer may be efficient and also simple:
$content = "The main string to search";
$search = "search";
//For compare the begining string with case insensitive.
if(stripos($content, $search) === 0) echo 'Yes';
else echo 'No';
//For compare the begining string with case sensitive.
if(strpos($content, $search) === 0) echo 'Yes';
else echo 'No';
//For compare the ending string with case insensitive.
if(stripos(strrev($content), strrev($search)) === 0) echo 'Yes';
else echo 'No';
//For compare the ending string with case sensitive.
if(strpos(strrev($content), strrev($search)) === 0) echo 'Yes';
else echo 'No';
Don't know if this is fast or not but for a single character test, these work, too:
(array_pop(str_split($string)) === $test) ? true : false;
($string[strlen($string)-1] === $test) ? true : false;
(strrev($string)[0] === $test) ? true : false;
easiest way to check it via regular expression
for example to check if the mail given is gmail:
echo (preg_match("/#gmail\.com$/","example-email#gmail.com"))?'true':'false';
I'm thinking the reverse functions like strrchr() would help you match the end of the string the fastest.
This is pure PHP, without calling external functions, except for strlen.
function endsWith ($ends, $string)
{
$strLength = strlen ($string);
$endsLength = strlen ($ends);
for ($i = 0; $i < $endsLength; $i++)
{
if ($string [$strLength - $i - 1] !== $ends [$i])
return false;
}
return true;
}
for single-char needle:
if (#strrev($haystack)[0] == $needle) {
// yes, it ends...
}