Is this a bug in PHP - php

<?php
if(stripos('http://cp.uctorrent.com', 'cp.utorrent.com') >= 0){
echo "Good1";
}else{
echo "Bad1";
}
if(stripos('http://uctorrent.com', 'cp.utorrent.com') >= 0){
echo "Good2";
}else{
echo "Bad2";
}
?>
output is
Good1Good2
whereas it should be
Good1Bad2

<?php
if(false >= 0) echo "Good";
else echo "Bad";
// this code prints Good
?>
It's not a bug, it's a "weird" boolean conversion.
stripos returns false when the string is not found, and false converts to 0 in PHP.
Directly from the documentation (the problem is the other way around) :
Warning This function may return
Boolean FALSE, but may also return a
non-Boolean value which evaluates to
FALSE, such as 0 or "". Please read
the section on Booleans for more
information. Use the === operator for
testing the return value of this
function.

In case 2 stripos returns false as the search fails and false when compared with 0 returns true.
The right way of doing it is to use the identity operator which checks both type and value:
if(stripos('http://cp.uctorrent.com','cp.utorrent.com') !== false)
echo "Good1"; ^^^^^^^^^^
else
echo "Bad1";

Reading the manual would help greatly:
Warning
This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE, such as 0 or "". Please read the section on Booleans for more information. Use the === operator for testing the return value of this function.

If needle is not found, stripos() will return boolean FALSE.
http://php.net/manual/en/function.stripos.php
Boolean FALSE in PHP is equivalent to integer 0, which is >= 0.

If you want to check whether stripos failed to get a match, you need to test for type and value with !== or ===, for example:
<?php
if(stripos('http://cp.uctorrent.com','cp.utorrent.com')!==false)echo "Good1";
else echo "Bad1";
if(stripos('http://uctorrent.com','cp.utorrent.com')!==false)echo "Good2";
else echo "Bad2";
?>

Again, try this and avoid the issues caused by microoptimization function use patterns:
if (stristr('http://cp.uctorrent.com', 'cp.utorrent.com')) {
echo "Good1";
}
else {
echo "Bad1";
}

Below $p has value 'false' (means 0), so it's >=0
$p = stripos('http://uctorrent.com','cp.utorrent.com');
You need to check stripos('http://uctorrent.com','cp.utorrent.com') !== false first then get $p (found position) like above...

utorrent <---> uctorrent
i am such an idiot...
it was spell mistake ...
comparing uctorrent with utorrent
sorry every one

Related

strpos function error. I'm trying to parse MRZ from string [duplicate]

if(strpos("http://www.example.com","http://www.")==0){ // do work}
I'd expect this to resolve as true, which it does. But what happens when I do
if(strpos("abcdefghijklmnop","http://www.")==0){// do work}
This also passes on php 5 because as far as I can work out the strpos returns false which translates as 0.
Is this correct thinking/behaviour? If so what is the workaround for testing for that a substring is at the beginning of another string?
Yes, this is correct / expected behavior :
strpos can return 0 when there is a match at the beginning of the string
and it will return false when there is no match
The thing is you should not use == to compare 0 and false ; you should use ===, like this :
if(strpos("abcdefghijklmnop","http://www.") === 0) {
}
Or :
if(strpos("abcdefghijklmnop","http://www.") === false) {
}
For more informations, see Comparison Operators :
$a == $b will be TRUE if $a is equal to $b.
$a === $b will be TRUE if $a is equal to $b, and they are of the same type.
And, quoting the manual page of strpos :
This function may return Boolean
FALSE, but may also return a
non-Boolean value which evaluates to
FALSE, such as 0 or "". Please
read the section on Booleans for
more information. Use the ===
operator for testing the return
value of this function.
=== and !== compare type and value as shown below:
if (strpos("abcdefghijklmnop", "http://www.") !== false) {
// do work
}
strpos returns an int or boolean false. the == operator also evaluates 0 to mean false, you want to use the === operator (three equals signs) that also checks that the types being compared are the same instead of just seeing if they can be evaluated to mean the same.
so
if (strpos($hastack, $needle) === 0)
{
// the $needle is found at position 0 in the $haystack
}
0 is a possible return value from strpos when it finds a match at the very beginning. In case if the match is not found it returns false(boolean). So you need to check the return value of strpos using the === operator which check the value and the type rather than using == which just checks value.
I personally tend to use this way :
if(!strpos($v,'ttp:'))$v='http://'.$v;
or
if(strpos(' '.$v,'http'))
to avoid the "0" position then always make it a number more than 0
cheers

strpos fails unexpectedly

Question, how come the following executed the echo:
$str = "Hello World";
if (strpos($str, 'He') !== false) {
echo 'GOOD';
}
But this doesn't:
$str = "Hello World";
if (strpos($str, 'He') === true) {
echo 'GOOD';
}
Aren't the two conditions equivalent in that they are both checking for the returned to be a boolean that is set to true? Isn't !== false the same as === true, and if not, why not?
I appreciate the clarification.
No they're not equivalent:
strpos() returns either boolean FALSE (if not found) or an integer offset value (which can be 0 if found at offset 0 and so on), but it never returns a boolean TRUE. ie., Boolean TRUE !== an INT.
The operator === compares not only value but also a datatype. If strpos finds the substring, it returns the position which is of type int. As it is not bool, the condition is not met.

PHP: Are these statements equivalent? (file_exists())

Aren't these equivalent?
==SCRIPT A==
if (file_exists($file) == false) {
return false;
}
==SCRIPT B==
if(!file_exists($file)) {
return false;
}
Plain answer: Y E S
They evaluate to the same thing.
That first one might be even better suited like this:
if (file_exists($file) === false) { // === checks type and value
return false;
}
OR:
return file_exists($file);
yes, file_exists returns a boolean, so it's either true or false.
so you could return file_exists($file) as well...
If you are making boolean comparisons, then you would rather do this:
if (file_exists($file) === false) {
return false;
}
using the === operator, to ensure that what you are receiving is a variable of type boolean and of value equivalent to false.
Yes.
But if you would use:
if (file_exists($file) === false) {
return false;
}
then it would not be the same as:
if(!file_exists($file)) {
return false;
}
because in the first case it would check whether the value returned by function matches strictly to false, and in the second case the value returned by function would be evaluated to boolean value.
EDIT:
That is general rule.
But in case of file_exists() function, which returns boolean value, evaluating to boolean is not necessary, thus you can use strict condition and this will have the same result (but only in case you know the value will be either true or false.
If you're asking "what's the difference between the === and == operator" then:
'===' is a strict comparison that checks the types of both sides.
'==' is an 'equivalent to' comparison operator that will cast either side to the appropriate type if deemed necessary.
To expand, '==' can be used to check for 'falsey' values and '===' can be used to check for exact matches.
if (1 == TRUE) echo 'test';
>> "test"
if (1 === TRUE) echo 'test';
>>
If you're asking if there's any functional / practical difference between your two code blocks then no, there isn't and you should be returning as such: return file_exists($file);
Worth a read:
http://php.net/manual/en/language.operators.comparison.php

verify, if the string starts with given substring

I have a string in $str variable.
How can I verify if it starts with some word?
Example:
$str = "http://somesite.com/somefolder/somefile.php";
When I wrote the following script returns yes
if(strpos($str, "http://") == '0') echo "yes";
BUT it returns yes even when I wrote
if(strpos($str, "other word here") == '0') echo "yes";
I think strpos returns zero if it can't find substring too (or a value that evaluates to zero).
So, what can I do if I want to verify if word is in the start of string? Maybe I must use === in this case?
You need to do:
if (strpos($str, "http://") === 0) echo "yes"
The === operator is a strict comparison that doesn't coerce types. If you use == then false, an empty string, null, 0, an empty array and a few other things will be equivalent.
See Type Juggling.
You should check with the identity operator (===), see the documentation.
Your test becomes:
if (strpos($str, 'http://') === 0) echo 'yes';
As #Samuel Gfeller pointed out: As of PHP8 you can use the str_starts_with() method. You can use it like this:
if (str_starts_with($str, 'http://')) echo 'yes';
PHP does have 2 functions to verify if a string starts with a given substring:
strncmp (case sensitive);
strncasecmp (case insensitive);
So if you want to test only http (and not https), you can use:
if (strncasecmp($str,'http://',7) == 0) echo "we have a winner"
check with
if(strpos($str, "http://") === 0) echo "yes";
as == will turn positive for both false & 0 check the documentation
Another option is:
if (preg_match("|^(https?:)?\/\/|i", $str)) {
echo "the url starts with http or https upper or lower case or just //.";
}
As shown here: http://net.tutsplus.com/tutorials/other/8-regular-expressions-you-should-know/
strncmp($str, $word, strlen($word))===0
Is a bit more performant than strpos
Starting with PHP 8 (2020-11-24), you can use str_starts_with:
if (str_starts_with($str, 'http://')) {
echo 'yes';
}
PHP 8 has now a dedicated function str_starts_with for this.
if (str_starts_with($str, 'http://')) {
echo 'yes';
}
if(substr($str, 0, 7)=="http://") {
echo("Statrs with http://");
}
There's a big red warning in the documentation about this:
This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE, such as 0 or "". Please read the section on Booleans for more information. Use the === operator for testing the return value of this function.
strpos may return 0 or false. 0 is equal to false (0 == false). It is not identical to false however, which you can test with 0 === false. So the correct test is if (strpos(...) === 0).
Be sure to read up on the difference, it's important: http://php.net/manual/en/language.operators.comparison.php

php 5 strpos() difference between returning 0 and false?

if(strpos("http://www.example.com","http://www.")==0){ // do work}
I'd expect this to resolve as true, which it does. But what happens when I do
if(strpos("abcdefghijklmnop","http://www.")==0){// do work}
This also passes on php 5 because as far as I can work out the strpos returns false which translates as 0.
Is this correct thinking/behaviour? If so what is the workaround for testing for that a substring is at the beginning of another string?
Yes, this is correct / expected behavior :
strpos can return 0 when there is a match at the beginning of the string
and it will return false when there is no match
The thing is you should not use == to compare 0 and false ; you should use ===, like this :
if(strpos("abcdefghijklmnop","http://www.") === 0) {
}
Or :
if(strpos("abcdefghijklmnop","http://www.") === false) {
}
For more informations, see Comparison Operators :
$a == $b will be TRUE if $a is equal to $b.
$a === $b will be TRUE if $a is equal to $b, and they are of the same type.
And, quoting the manual page of strpos :
This function may return Boolean
FALSE, but may also return a
non-Boolean value which evaluates to
FALSE, such as 0 or "". Please
read the section on Booleans for
more information. Use the ===
operator for testing the return
value of this function.
=== and !== compare type and value as shown below:
if (strpos("abcdefghijklmnop", "http://www.") !== false) {
// do work
}
strpos returns an int or boolean false. the == operator also evaluates 0 to mean false, you want to use the === operator (three equals signs) that also checks that the types being compared are the same instead of just seeing if they can be evaluated to mean the same.
so
if (strpos($hastack, $needle) === 0)
{
// the $needle is found at position 0 in the $haystack
}
0 is a possible return value from strpos when it finds a match at the very beginning. In case if the match is not found it returns false(boolean). So you need to check the return value of strpos using the === operator which check the value and the type rather than using == which just checks value.
I personally tend to use this way :
if(!strpos($v,'ttp:'))$v='http://'.$v;
or
if(strpos(' '.$v,'http'))
to avoid the "0" position then always make it a number more than 0
cheers

Categories