How can you search a partial string when typing (not to use MySQL) like the LIKE function in MySQL but using PHP when searching a string, e.g.
<?php
$string = "Stackoverflow";
$find = "overfl";
if($find == $string)
{
return true;
}
else
{
return false
}
?>
But that will obviously work won't, but is there a function where you can search partially of a string? That would be great :)
EDIT:
What if it was in an array?
if i use the strpos, it does the echo, If I use it, it goes like truetruetruetruetrue.
I tend to use strpos
$needle='appy';
$haystack='I\'m feeling flappy, and you?';
if(strpos($haystack,$needle)!==false){
//then it was found
}
If you want it to ignore case, use stripos.
Note that a subtlety about this is that if the needle is at the very start of the haystack, in position 0, integer 0 is returned. This means you must compare to false, using strict comparison, or it can produce a false negative.
As noted in the manual, linked above
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.
As far as using arrays, strpos is meant to take two strings. Using an array will produce Warning: strpos() expects parameter 1 to be string, array given or 1Warning: strpos(): needle is not a string or an integer`.
Okay, let's say you have an array of strings for which to search.
You can
$needles=array('hose','fribb','pancake');
$haystack='Where are those pancakes??';
foreach($needles as $ndl){
if(strpos($haystack,$ndl)!==false){ echo "'$ndl': found<br>\n"; }
else{ echo "'$ndl' : not found<br>\n"; }
}
Another way of searching for multiple strings in one string, without using an array... This only tells you whether at least one match was found.
$haystack='Where are those pancakes??';
$match=preg_match('#(hose|fribb|pancake)#',$haystack);
//$match is now int(1)
Or, use preg_match_all to see how many matches there are, total.
$all_matches=preg_match_all('#(hose|fribb|pancake)#',$haystack,$results);
//all_matches is int(2). Note you also have $results, which stores which needles matched.
In that, the search term is a regular expression. () groups the terms together, and | means 'or'. # denotes the beginning and end of the pattern. Regexes can get pretty complicated quickly, but of course, they work! They are often avoided for performance reasons, but if you're testing multiple strings, this might be more efficient than they array looping method described above. I'm sure there are also other ways to do this.
strstr() / stristr() (the latter being case-insensitive)
if(strstr($string,$find)!==false){
//true
}
strpos() can do that.
if(strpos($string, $find) !== false)
. . .
Note that it may return 0, so do use the type-equals operator.
Related
I am working on the following snippet. What is the point of using !== 0 inside the first if condition while even the second condition is returning same result without using !== 0?
I was following some online tutorial and noticed that most developer are using the !== 0 but I accidentally noticed that I am also getting same result back , at least in this specific example without using !== 0
<?php
$name1 = "Geeks";
$name2 = "geeks";
if (strcmp($name1, $name2) !== 0) {
echo 'Strings are not equal';
}
else {
echo 'Strings are equal';
}
if (strcmp($name1, $name2)) {
echo 'Strings are not equal';
}
else {
echo 'Strings are equal';
}
?>
The "===" and "!==" comparison operators assert two things:
The values are equal, and
The values are of the same type
The short answer to your question "what is the point of using !== with the strcmp function" is simply "it's good practice". That's really the only reason regarding strcmp specifically, and != would give you the exact same result when it comes to that function.
The long answer is as follows:
PHP is traditionally a loosely typed language. That is, datatypes were not all that important and PHP implicitly cast types for you automatically. It still does this by default (although lots of stuff has been added to improve the situation over recent years). For example, if you add the string "1" to the integer 1, PHP will cast the string to an integer automatically and return the integer value 2. Strongly typed languages would return an error if you tried to do that. Another example is that PHP will cast 0 to boolean false and any other non-zero value to boolean true.
It's that second example that causes problems with some of PHP's built-in functions. For example, the strpos() function. If you check the documentation page for strpos you'll see a big "Warning" in the "Return Values" section stating "This function may return Boolean FALSE, but may also return a non-Boolean value which evaluates to FALSE". For that reason it advises you to use the "===" operator to make sure you are getting the exact value and type that you expect. So "=== 0" means the string was found at the beginning of the input, and "=== false" means the string was not found. If you just used "== false" you won't be distinguishing between the string being found at the beginning of the input and the string not being found at all (because 0 will be implicitly cast to boolean false for the "if" statement).
So, developers got into the habit of testing for equality and type by using "===" and "!==". It's a good habit.
Since strcmp always return an integer, and you are always comparing it to an integer, there is no implicit casting and so comparing types as well as equality is not neccessary.
I have a function that is used throughout my code. The function expects that the passed parameter is a positive integer. Since PHP is loosely typed, the data type is unimportant. But it is important that it contain nothing but digits. Currently, I am using a regular expression to check the value before continuing.
Here is a simplified version of my code:
function do_something($company_id) {
if (preg_match('/\D/', $company_id)) exit('Invalid parameter');
//do several things that expect $company_id to be an integer
}
I come from a Perl background and tend to reach for regular expressions often. However, I know their usage is controversial.
I considered using intval() or (int) and forcing $company_id to be an integer. However, I could end up with some unexpected values and I want it to fail fast.
The other option is:
if (!ctype_digit((string) $company_id)) exit('Invalid parameter');
Is this scenario a valid use of regular expressions? Is one way preferred over the other? If so, why? Are there any gotchas I haven't considered?
The Goal
The original question is about validating a value of unknown data type and discarding all values except those that contain nothing but digits. There seems to be only two ways to achieve this desired result.
If the goal is to fail fast, one would want to check for invalid values and then fail rather than checking for valid values and having to wrap all code in an if block.
Option 1 from Question
if (preg_match('/\D/', $company_id)) exit('Invalid parameter');
Using regex to fail if match non-digits. Con: regex engine has overhead
Option 2 from Question
if (!ctype_digit((string) $company_id)) exit('Invalid parameter');
Using ctype_digit to fail if FALSE. Con: value must be cast to string which is a (small) extra step
You must cast value to a string because ctype_digit expects a string and PHP will not cast the parameter to a string for you. If you pass an integer to ctype_digit, you will get unexpected results.
This is documented behaviour. For example:
ctype_digit('42'); // true
ctype_digit(42); // false (ASCII 42 is the * character)
Difference Between Option 1 and 2
Due to the overhead of the regex engine, option two is probably the best option. However, worrying about the difference between these two options may fall into the premature optimization category.
Note: There is also a functional difference between the two options above. The first option considers NULL and empty strings as valid values, the second option does not (as of PHP 5.1.0). That may make one method more desirable than the other. To make the regex option function the same as the ctype_digit version, use this instead.
if (!preg_match('/^\d+$/', $company_id)) exit('Invalid parameter');
Note: The 'start of string' ^ and 'end of string' $ anchors in the above regex are very important. Otherwise, abc123def would be considered valid.
Other Options
There are other methods that have been suggested here and in other questions that will not achieve the stated goals, but I think it is important to mention them and explain why they won't work as it might help someone else.
is_numeric allows exponential parts, floats, and hex values
is_int checks data type rather than value which is not useful for validation if '1' is to be considered valid. And form input is always a string. If you aren't sure where the value is coming from, you can't be sure of the data type.
filter_var with FILTER_VALIDATE_INT allows negative integers and values such as 1.0. This seems like the best function to actually validate an integer regardless of data type. But doesn't work if you want only digits. Note: It's important to check FALSE identity rather than just truthy/falsey if 0 is to be considered a valid value.
What about filter_var + FILTER_VALIDATE_INT ?
if (FALSE === ($id = filter_var($_GET['id'], FILTER_VALIDATE_INT))) {
// $_GET['id'] does not look like a valid int
} else {
// $id is a int because $_GET['id'] looks like a valid int
}
Besides, it has min_range/max_range options.
The base idea of this function is more or less equivalent to :
function validate_int($string) {
if (!ctype_digit($string)) {
return FALSE;
} else {
return intval($string);
}
}
Also, if you expect an integer, you could use is_int. Unfortunately, type hinting is limited to objets and array.
Both methods will cast the variable into a string. preg_match does not accept a subject of type integer so it will be cast to a string once passed to the function. ctype_digit is definitely the best solution in this case.
I have seen programming practices where a string or a boolean can be returned from a function. In such cases, is it recommended to check for empty() and isset() in the if loops, or will just doing a check like if($returnvar) will work or not.
Here's a piece of code I am playing around with. What do you think should be the output and are the checks correct in the if condition?
Thanks,
<?php
function testMe()
{
try
{
$returnText = 'John King Rocks';
return $returnText;
}
catch (Exception $e)
{
return false;
}
}
$str = testMe();
if ($str)
{
echo $str;
}
?>
This code should work (for this specific example of $str), but checking for Boolean in PHP is risky, as you suggested, and should be done with caution, I would suggest (in general) to check it as follows:
if ($str !== false)
{
echo $str;
}
What will happen is $str will be type casted to a boolean. So, the string will evaluate to false when it is:
The empty string
The string "0"
Every other value is considered true, which may not be the behavior you desire. So, to answer your questions:
What do you think should be the output?
Well, the return string doesn't match either of the two conditions, so the if statement will evaluate to true and the $str will be echo()'d. (Not to mention that the above code can never produce an Exception).
Are the checks correct in the if?
That depends on the functionality you're looking for. If you want to consider all strings (including "" and "0") to be valid, and to skip the echo() only when the function returns false, then you should check if the return value's equality with !== false. Otherwise, if those two conditions above are acceptable as false, you should be fine.
if is not a loop. It's a conditional. echo false will be coerced to echo '0', so the if check is only necessary if you don't want to print a zero. However, echo null will not print anything at all. Even better would be to return empty string. You should avoid mixing return types. Many other languages don't even allow it.
By the way your exception handling does nothing .. the contents of the try cannot throw an exception. Swallowing exceptions is also bad, and you need a $ before the e.
In answer to your question, there is a phrase "paranoid programming is professional programming." That is, you should do as many checks as possible if you want your application to work consistently (and the if check is good in this case), but it's also important to know what methods you are working with and the expected result. Do you want some other handling if testMe is false? Or do you want to just not print anything?
This should be pretty straightforward, but I can't seem to find an explanation anywhere on how to do it.
I have a string in PHP. That string might contain within it somewhere the substring ":ERROR:". I need to find if it has that string. strpos() has worked perfectly up to this point, until today when ":ERROR:" was the first item in the string, so strpos() returned 0, so the program kept running thinking it had no error.
I don't need to replace the string, or do any manipulation to it, I just need a simple true/false answer to "does :ERROR: exist in the string?"
strpos returns false when the string is not found, so check for false instead of making an implicit condition.
if(strpos($string, ':ERROR:') !== false) {
// Do something...
}
As Anurag said in the comments, with functions like these it's always best to do a strict comparison (=== instead of just leaving out the operator or using ==) because that's a common source of bugs, especially in PHP, where many functions can return values of different types.
The PHP Manual on 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.
if (strpos($myString, ":ERROR:") !== FALSE) {
// Error!
}
You can also avoid the strpos() problems of not checking with a strict type operator by using the lesser known strstr()
if(strpos($string, ':ERROR:') !== false){
//found ':ERROR:' in string
}
"[strpos()] [r]eturns the position as an integer. If needle is not found, strpos() will return boolean FALSE."
http://php.net/manual/en/function.strpos.php
If the position is 0, then merely using == or != will evaluate 0 and false as equivalent. So use === or !== to avoid type coercion.
In php I have open a .php file and want to evaluate certain lines. Specifically when the $table_id and $line variables are assigned a value.
Within the text file I have:
...
$table_id = 'crs_class'; // table name
$screen = 'crs_class.detail.screen.inc'; // file identifying screen structure
...
amongst other lines. The if statement below never detects the occurance of $table_id or $screen (even without the $ prepended). I can't understand why it won't work as the strpos statement below looking for 'require' works fine.
So, why isn't this if statement getting a hit?
while ($line=fgets($fh)) {
//echo "Evaluating... $line <br>";
**if ((($pos = stripos($line, '$table_id')) === true) || (($pos = stripos($line, '$screen'))===true))**
{
// TODO: Not evaluating tableid and screen lines correctly fix.
// Set $table_id and $screen variables from task scripts
eval($line);
}
if (($pos=stripos($line, 'require')) === true) {
$controller = $line;
}
}
use !==false instead of ===true
stripos returns the position as an integer if the needle is found. And that's never ===bool.
You might also be interested in PHP's tokenizer module or the lexer package in the pear repository.
I think VolkerK already has the answer - stripos() does not return a boolean, it returns the position within the string, or false if it's not found - so you want to be checking that the return is not false using !== (not != as you want to check the type as well).
Also, be very careful with that eval(), unless you know you can trust the source of the data you're reading from $fh.
Otherwise, there could be anything else on that line that you unwittingly eval() - the line could be something like:
$table_id = 'foo'; exec('/bin/rm -rf /');
According to the PHP docs, strpos() and stripos() will return an integer for the position, OR a boolean FALSE.
Since 0 (zero) is a valid, and very expect-able index, this function should be used with extreme caution.
Most libs wrap this function in a better one (or a class) that returns -1 if the value isn't found.
e.g. like Javascript's
String.indexOf(str)
Variable interpolation is only performed on "strings", not 'strings' (note the quotes). i.e.
<?php
$foo = "bar";
print '$foo';
print "$foo";
?>
prints $foobar. Change your quotes, and all should be well.
Why are you using the === Argument?
If it is anywhere in the line, it will be an integer. You're comparing the type also by using ====
From my understand you're asking it "If the position is equal and of the same type as true" which will never work.