I am having an issue - I am unable to get a td cell when my $v value is 0. For all other numbers it is fine, but with zero value I just don't get then td.. What could be wrong? I am using $_GET array with a foreach loop, taking data from two inputs, one for name, one for value.
<table border = "1" >
<?php
print_r($_GET);
foreach ($_GET as $k=>$v){
if($v){
if ($rowFinished) echo "<tr>";
if (preg_match("/{$inputVardas}/i", $k))
{
echo "<td>$v</td>";
$rowFinished = false;
}
else if (preg_match("/{$inputSkaicius}/i", $k) and is_numeric($v))
{
if ($v < 10)
{
$color="green";
}
else if ($v > 10)
{
$color="red";
}
else if( $v == 10){
$color="yellow";
}
echo "<td style='color: $color'>$v</td>";
$rowFinished = true;
}
if ($rowFinished) echo "</tr>";
}
}?></table>
I've tried to do some print_r of an array, there I can see a value, but in my loop it just doesn't work. Maybe it has to do something with the case that php treats it as empty, but I am unable to find a way to use it.
[vardas0] => jonas [value0] => 0
Directly after the foreach you have a if ($v), and if the value is 0, it will not run.
I've found a way by improving the following line from
if($v){
to
if($v or (is_numeric($v) and $v == 0)){
It looks like you're using this
if ($v) {
to check that $v has a value. You can use
if (strlen($v)) {
instead.
Everything in $_GET will be a string, but a string '0' will evaluate as false just like an int 0 as you have discovered. Checking the length of the string instead will tell you whether or not that URL parameter has any value, including '0'.
You may also want to consider trimming the value before checking it if you want to exclude values containing only whitespace.
$v = trim($v);
if (strlen($v)) {
I honestly would suggest using isset()instead of all the provided suggestions so far. The reason is that to me it is best practice to have your conditionals be a boolean expression or something that explicitly evaluates to true or false. This avoids ambiguity and unintended side effects as evidenced by this question.
I would personally use:
if(isset($v)){
I'm trying to get the value of if condition that make the condition TRUE, I have the following example:
(code.php)
<?php
$a = 'USERNAME';
$b = 'LASTNAME';
if(substr($a, 0, strlen("<SCRIPT"))=== "<SCRIPT Abdalla $a " ) {
}
?>
in the above example, I'm trying to get the value <SCRIPT without double quotations. I tried some steps, but it still get the double quotation with the value (<SCRIPT). I plan then to assign the value <SCRIPT to another variable. Next code shows my code to get the result, where it still not working properly:
(test.php)
<?php
$file='';
$handle = fopen('code.php','r+');
if ($handle) {
while (($buffer=fgets($handle, 4096)) !== false) {
$file.=$buffer."\n";
}
if (!feof($handle)) {
die('error');
}
fclose($handle);
}
//take note of the use of single quotes to wrap this regex, as we do not want PHP parser to eval the $ in the regex string
preg_match_all('/\s*?(\$[\S]+?)\s*?\=(\"?[\S]+?\"?);/',$file,$matches, PREG_SET_ORDER);
$varval=array();
foreach($matches as $match){
$tmp=$match[2];
if(substr($tmp,0,1)=='"' && substr($tmp,-1,1)=='"'){
//evaluate variables in string. we can evaluate with the current object as the variable should be declared first as of proper PHP syntax
$tmp=substr($tmp, 1,-1); //remove quotes
$tmp=replaceFromObject($tmp, $varval);
}
$varval[$match[1]]=$tmp; //we do not need to check if exists, because we should replace with the latest value.
}
/*
The below stores all quoted text and replace them with our own special variable %var0%, %var1%, %var2%.... %varN%.
This is because there could be cases like if("test == 3" == $a) or even worse if("if(test=3)" == $a), which will make regex/parsing tricky if we do not substitute these quoted text out just like a parser/compiler would.
Note: Something I didn't do. We should really first scan the whole text using preg_match to find if there are any text using this format of variables as well, to prevent collisions!
If there are, we can set a loop to check and append some character to our own special variable like %varrN%, %varrrN%, %varrrrN%...
until we find no collisions and it is safe to use. I will leave this simple regex exercise for you to do on your own. Create the regex to find the file for %varN%...
*/
preg_match_all("/\"([\s\S]*?)\"/", $file, $matches, PREG_SET_ORDER);
$stringvars=array();
$key="%var";
$count=0;
foreach($matches as $match){
if(!in_array($match[1], $stringvars)){
$stringvars[$key.$count.'%']=$match[1];
$file=preg_replace("/\"".preg_quote($match[1])."\"/", $key.$count.'%', $file); //take note of the change to preg_quote
$count++;
}
}
// now we parse the whole text for if(subject anycomparator value)
preg_match_all("/if\s*?\(([\s\S]*?)([\=|\>|\<][\=]{0,2})\s*?([\S\s]*?)\s*?\)/", $file, $matches,PREG_SET_ORDER);
$conditionals=array();
foreach($matches as $match){
$conditionals[]=array(
'subject'=>replaceFromObject(replaceFromObject(trim($match[1]),$stringvars),$varval),
//the order does matter, we replace the string first, then the variables, as there might be variables in the double quoted strings which we should evaluate
'comparator'=>$match[2],
'value'=>replaceFromObject(replaceFromObject(trim($match[3]),$stringvars),$varval),
);
}
foreach ($conditionals as $c){
// echo htmlspecialchars($c['subject']).' ';
// echo htmlspecialchars($c['comparator']).' ';
echo htmlspecialchars($c['value']);
echo "<br/>";
}
/* now this function can be used to replace both the quoted strings AND the variables */
function replaceFromObject($s, $obj){
foreach($obj as $key=>$value){
$s=preg_replace('/'.preg_quote($key).'/', $value, $s); //take note of the preg_quote as the string may contain regex keywords
}
return $s;
}
?>
I want a way to print the value that make the if condition be TRUE, which is (
Note: I know the condition here is not TRUE, so that I want to get the value that make the condition TRUE which is <SCRIPT
The purpose is I want to know what is the value that make the condition TRUE, then later will use this value to do test cases on the code based on this value.
Your goal seems oddly specific, but here's a go at addressing your question.
You should not be using file_get_contents to read the actual source code of the php file. You will be getting the generated html equivalent instead. If you are getting the source code, it means you have your allow_url_fopen set to true. This opens your web application up to potential pretty damaging script injection possibilities, unless you know what you are doing and are careful and consistent with your code. You should try using fgets instead. This code will basically do the same as your file_get_contents.
$file='';
$handle = fopen('code.php','r+');
if ($handle) {
while (($buffer=fgets($handle, 4096)) !== false) {
$file.=$buffer."\n";
}
if (!feof($handle)) {
die('error');
}
fclose($handle);
}
There is a bug in your code. if(strpos($value, 'if') != false) will render position 0 as false, which should be true in your case as if is at position 0. The comparator should be strict if(strpos($value, 'if') !== false).
It is returning the quotation because that is what your code is telling it to. $pos1 = strpos($value, '==') + 2 is pointing to 2 characters after the first =, which is technically your last = in your ===. In fact, with your current code, you would be getting = "<SCRIPT" as the result.
Now for the Solution
To solve it just for your case, you can just adjust the position to substr with. After making the amendments mentioned above (especially 2), you will get your condition without the quotes by changing these 2 lines
$pos1 = strpos($value, '===') + 5; // 5 includes the 3 equal signs, a space and the quote
$pos2 = strrpos($value, ')') - 2; // 2 includes the space and the quote
Although this will get the result you want, it might not work for all use cases, as sometimes you might add a space, sometimes you might not. A more robust solution will be to use regex. In your case, it will be something along this line:
foreach ($lines as $line) {
if(preg_match("/if\s*?\([\s\S]*?\=\=\s*?[\"|']([\S\s]*?)[\"|']\s*?\)/", $line, $matches)){
echo htmlspecialchars($matches[1]);
}
}
This regex string /if\s*?\([\s\S]*?\=\=\s*?[\"|']([\S\s]*?)[\"|']\s*?\)/ does what your code aims to do, but in a more robust manner = finds a string with if possibly a space, a (, some text, a comparator == and whatever is in between the quotes - either ' or ".
To have it even more robust to pick up other conditions, strict equal, < or > or <=, >=, you can do something like this.
$conditionals=array();
foreach ($lines as $line) {
if(preg_match("/if\s*?\([\s\S]*?([\=|\>|\<][\=]{0,2})\s*?[\"|']([\S\s]*?)[\"|']\s*?\)/", $line, $matches)){
$conditionals[]=array(
'comparator'=>$matches[1],
'value'=>$matches[2]
);
}
}
foreach ($conditionals as $c){
echo htmlspecialchars($c['comparator']).' ';
echo htmlspecialchars($c['value']);
echo "<br/>";
}
This will work for a file of code.php that might look like this:
//code.php
<?php
$a = 'Data';
if(substr($a, 0, strlen("<SCRIPT"))=== "<SCRIPT" ) {
echo TRUE;
}
if(substr($a, 0, strlen("<SCRIPT"))== "equal" ) {
echo TRUE;
}
if(substr($a, 0, strlen("<SCRIPT"))<= "lesser or equal" ) {
echo TRUE;
}
if(substr($a, 0, strlen("<SCRIPT"))>= "greater or equal" ) {
echo TRUE;
}
if(substr($a, 0, strlen("<SCRIPT"))< "lesser" ) {
echo TRUE;
}
if(substr($a, 0, strlen("<SCRIPT"))>"greater" ) {
echo TRUE;
}
and will return
=== <SCRIPT
== equal
<= lesser or equal
>= greater or equal
< lesser
> greater
Edit to provide even more robust code for non-quoted values...
Another edit to capture variable values and dump them back in.
Another edit for single quotes variables and space between variables
Note:
The order of capturing strings or variables first matters, as if we are not careful we might be caught in a viscous cycle -> there is string in the variable, there is variable in the string, there is a string in the variable in the string of a variable, etc...
The idea is we should capture the variable first, evaluate whatever variables within these variables (if they are a double quoted string), and we do not need to worry about that string-var inception problem.
We then capture the strings -> and then replace the strings THEN replace the variables.
More Notes
What we should really also check for:
Since PHP only evaluates variables in double quotes, we should check if the string was enclosed in double and single quotes before making the decision to evaluate. I have done it for the variables. It could be easily translated to the strings as well - by capturing the quotes as well, then testing the quotes if it is single or double (or any at all). I will leave this to you as a regex exercise.
The other note is that I did this on purpose. :p The current regex for capturing variables works for $a=3;, $a =3; but not $a = 3; or $a = 3 ; or $a= 3 ;, so on. It is easy to add it in, I left it this way so you have a chance to practice your regex skills by adding this simple conditions in. (Edited to add this in) Hope this helps..
$file='';
$handle = fopen('code.php','r+');
if ($handle) {
while (($buffer=fgets($handle, 4096)) !== false) {
$file.=$buffer."\n";
}
if (!feof($handle)) {
die('error');
}
fclose($handle);
}
//take note of the use of single quotes to wrap this regex, as we do not want PHP parser to eval the $ in the regex string
preg_match_all('/\s*?(\$[\S]+?)\s*?\=\s*?(\"?[\S]+?\"?);/',$file,$matches, PREG_SET_ORDER);
$varval=array();
foreach($matches as $match){
$tmp=trim($match[2]);
if(substr($tmp,0,1)=='"' && substr($tmp,-1,1)=='"'){
//evaluate variables in string. we can evaluate with the current object as the variable should be declared first as of proper PHP syntax
$tmp=substr($tmp, 1,-1); //remove quotes
$tmp=replaceFromObject($tmp, $varval);
}else if(substr($tmp,0,1)=='\'' && substr($tmp,-1,1)=='\''){ // remove single quotes
$tmp=substr($tmp, 1,-1);
//no substitution of variables in single quotes just as PHP syntax
}
$varval[$match[1]]=$tmp; //we do not need to check if exists, because we should replace with the latest value.
}
/*
The below stores all quoted text and replace them with our own special variable %var0%, %var1%, %var2%.... %varN%.
This is because there could be cases like if("test == 3" == $a) or even worse if("if(test=3)" == $a), which will make regex/parsing tricky if we do not substitute these quoted text out just like a parser/compiler would.
Note: Something I didn't do. We should really first scan the whole text using preg_match to find if there are any text using this format of variables as well, to prevent collisions!
If there are, we can set a loop to check and append some character to our own special variable like %varrN%, %varrrN%, %varrrrN%...
until we find no collisions and it is safe to use. I will leave this simple regex exercise for you to do on your own. Create the regex to find the file for %varN%...
*/
preg_match_all("/\"([\s\S]*?)\"/", $file, $matches, PREG_SET_ORDER);
$stringvars=array();
$key="%var";
$count=0;
foreach($matches as $match){
if(!in_array($match[1], $stringvars)){
$stringvars[$key.$count.'%']=$match[1];
$file=preg_replace("/\"".preg_quote($match[1])."\"/", $key.$count.'%', $file); //take note of the change to preg_quote
$count++;
}
}
// now we parse the whole text for if(subject anycomparator value)
preg_match_all("/if\s*?\(([\s\S]*?)([\=|\>|\<][\=]{0,2})\s*?([\S\s]*?)\s*?\)/", $file, $matches,PREG_SET_ORDER);
$conditionals=array();
foreach($matches as $match){
$conditionals[]=array(
'subject'=>replaceFromObject(replaceFromObject(trim($match[1]),$stringvars),$varval),
//the order does matter, we replace the string first, then the variables, as there might be variables in the double quoted strings which we should evaluate
'comparator'=>$match[2],
'value'=>replaceFromObject(replaceFromObject(trim($match[3]),$stringvars),$varval),
);
}
foreach ($conditionals as $c){
echo htmlspecialchars($c['subject']).' ';
echo htmlspecialchars($c['comparator']).' ';
echo htmlspecialchars($c['value']);
echo "<br/>";
}
/* now this function can be used to replace both the quoted strings AND the variables */
function replaceFromObject($s, $obj){
foreach($obj as $key=>$value){
$s=preg_replace('/'.preg_quote($key).'/', $value, $s); //take note of the preg_quote as the string may contain regex keywords
}
return $s;
}
So actually your code doesn't output anything (test.php) on my server. Therefore I've tried another approach which at least works for your code.php, but however, it is not very stable like your own code since it doesn't take a few things into account which would be the following.
Logical operators which weren't thought of:
<, <=, >, >=, ===
No multiline if support
My approch actually doesn't split the string nor does it strip anything, the only thing which it is doing however, is to replace the string literal.
<?php
$file = file_get_contents("test.php");
$curIdx = 0;
while($curIdx < strlen($file))
{
$ifIndex = strpos($file,"if", $curIdx);
if($ifIndex === false)
{
break;
}
$curIdx = $ifIndex+1;
$equalsIdx = strpos($file,"=",$curIdx);
if($equalsIdx === false)
{
break;
}
$curIdx = $equalsIdx+1;
for($i = $curIdx; $i<strlen($file); $i++)
{
if($file[$i] !== "=" && $file[$i] !== " ")
{
$curIdx = $i;
break;
}
}
$condition = substr($file,$curIdx,strpos($file,")",$curIdx)-$curIdx);
$condition = str_replace('"','',$condition);
echo htmlspecialchars($condition);
}
This outputs: <SCRIPT
For your script, I found several issues:
if(strpos($value, 'if') !== false)
has to have a double ==
with that out of the way, you're getting the following output:
= "<SCRIPT"
To get rid of this, simply check if the char after pos1 is another =
if($value[$pos1] === "=")
{
$pos1++;
}
Then we can actually remove the call to sanitize_recursive completely, because substr never returns an array.
Now to get rid, simply call str_replace on the between string:
$between = substr($value, $startIndex, $length);
$between = str_replace('"','',$between);
echo htmlspecialchars($between);
And we're having an output of <SCRIPT- the call to htmlspecialchars is needed because otherwise your browser would start to interpret this tag.
This leaves us with the following file:
<?php
$file = file_get_contents("test.php"); // Code.php the page that include the if condition
$lines = explode("\n", $file); // get each line of source code and store it in array ($lines)
foreach ($lines as $key => &$value) {
if(strpos($value, 'if') !== false) // check if the line have if statement
{
if(strpos($value, '==') !== false ) // check if the line compare two values
{
$pos1 = strpos($value, '==') + 2; // get the existence position of '==' + 2
if($value[$pos1] === "=")
{
$pos1++;
}
$pos2 = strrpos($value, ')'); // get the position of last ) in the line
$startIndex = min($pos1, $pos2);
$length = abs($pos1 - $pos2);
$between = substr($value, $startIndex, $length);
$between = str_replace('"','',$between);
echo htmlspecialchars($between); // will print: "<SCRIPT" with double quotation
}
}
}
Can anyone figure out why this might happen in PHP (am using v5.4):
$value = 0;
$existing_value = "Unknown";
if ($value == $existing_value) {
echo "$value == $existing_value";
} else {
echo "$value != $existing_value";
}
This outputs as 0 == Unknown
Interestingly, $value = "0" (i.e. set as a string), evaluates to be false
Is this a known behaviour? Have I missed something in the documentation on this? Debugging this was driving me crazy earlier today!
Thanks for your help in advance...
This is caused by the automatic type casting, PHP uses.
When comparing an int value with a string using just ==, the string will be casted to an int, which in your case results in a 0 and hence a true evaluation.
See the respective PHP documentation for more information.
To circumvent this, you could use === instead of ==. The former includes a type check, which will make your condition evaluate to false:
$value = 0;
$existing_value = "Unknown";
if ($value === $existing_value) {
echo "$value === $existing_value";
} else {
echo "$value !== $existing_value";
}
When you compare a number with a string in PHP, as you do here, the string is converted to a number. Since the string "Unknown" is not numeric, it's converted to the number 0.
If you check for equality with the === operator, it won't perform type conversion and it'll evaluate as false.
http://php.net/manual/en/language.operators.comparison.php
You should have a look at the comparison tables in PHP Especially the loose comparison (using ==) section as compared to the strict comparison (using ===) section.
I am tring this method to find the common characters in two strings namely, $a and $r, but the first character isn't getting printed . Moreover the $already collects the common characters and prevents them from being printed for multiple times( I need each character to be printed once only) but it isn't doing so. Please tell me what errors I am making.
<?php
$a="BNJUBCI CBDIDIBO";
$r="SBKJOJLBOU";
$already="";
for($i=0;$i<strlen($r);$i++)
{
if (stripos($a,$r[$i])!=FALSE)
{
if (stripos($already,$r[$i])==FALSE)
{
$already=$already.$r[$i];
echo "already=".$already."<br>";
echo $r[$i]."<br>";
}
}
}
?>
Use !==FALSE instead of !=FALSE. The problem is that stripos returns 0 if the needle is at the start of the haystack, and 0 is falsy. By using !== you are forcing it to ensure the result is actually false, and not just 0.
This is actually listed in the docs. An "RTM" might be appropriate here.
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.
The simplest way to find the intersection of the two strings in PHP is to turn them into arrays and use the built-in functions for that purpose.
The following will show all the unique and common characters between the two strings.
<?php
$a="BNJUBCI CBDIDIBO";
$r="SBKJOJLBOU";
$a_arr = str_split($a);
$r_arr = str_split($r);
$common = implode(array_unique(array_intersect($a_arr, $r_arr)));
echo "'$common'";
?>
I would think a much simpler solution to this would be to make the strings into arrays and compare those no?
Something like:
<?php
$a="BNJUBCI CBDIDIBO";
$r="SBKJOJLBOU";
$shared = implode( '' , array_intersect( str_split($a) , str_split($r) ) );
?>
That should return you a string of all the characters in $a that are present in $r
I've seen a lot of php code that does the following to check whether a string is valid by doing:
$str is a string variable.
if (!isset($str) || $str !== '') {
// do something
}
I prefer to just do
if (strlen($str) > 0) {
// something
}
Is there any thing that can go wrong with the second method? Are there any casting issues I should be aware of?
Since PHP will treat a string containing a zero ('0') as empty, it makes the empty() function an unsuitable solution.
Instead, test that the variable is explicitly not equal to an empty string:
$stringvar !== ''
As the OP and Gras Double and others have shown, the variable should also be checked for initialization to avoid a warning or error (depending on settings):
isset($stringvar)
This results in the more acceptable:
if (isset($stringvar) && $stringvar !== '') {
}
PHP has a lot of bad conventions. I originally answered this (over 9 years ago) using the empty() function, as seen below. I've long since abandoned PHP, but since this answer attracts downvotes and comments every few years, I've updated it. Should the OP wish to change the accepted answer, please do so.
Original Answer:
if(empty($stringvar))
{
// do something
}
You could also add trim() to eliminate whitespace if that is to be considered.
Edit:
Note that for a string like '0', this will return true, while strlen() will not.
You need isset() in case $str is possibly undefined:
if (isset($str) && $str !== '') {
// variable set, not empty string
}
Using !empty() would have an important caveat: the string '0' evaluates to false.
Also, sometimes one wants to check, in addition, that $str is not something falsy, like false or null[1]. The previous code doesn't handle this. It's one of the rare situations where loose comparison may be useful:
if (isset($str) && $str != '') {
// variable set, not empty string, not falsy
}
The above method is interesting as it remains concise and doesn't filter out '0'. But make sure to document your code if you use it.
Otherwise you can use this equivalent but more verbose version:
if (isset($str) && (string) $str !== '') {
// variable set, not empty string, not falsy
}
Of course, if you are sure $str is defined, you can omit the isset($str) from the above codes.
Finally, considering that '' == false, '0' == false, but '' != '0', you may have guessed it: PHP comparisons aren't transitive (fun graphs included).
[1] Note that isset() already filters out null.
This will safely check for a string containing only whitespace:
// Determines if the supplied string is an empty string.
// Empty is defined as null or containing only whitespace.
// '0' is NOT an empty string!
function isEmptyString($str) {
return !(isset($str) && (strlen(trim($str)) > 0));
}
What about this:
if( !isset($str[0]) )
echo "str is NULL or an empty string";
I found it on PHP manual in a comment by Antone Roundy
I posted it here, because I did some tests and it seems to work well, but I'm wondering if there is some side effect I'm not considering. Any suggestions in comments here would be appreciated.
According to PHP empty() doc (http://ca1.php.net/empty):
Prior to PHP 5.5, empty() only supports variables; anything else will result in a parse error. In other words, the following will not work: empty(trim($name)). Instead, use trim($name) == false.
This simple old question is still tricky.
strlen($var) works perfectly ONLY if you're absolutely sure the $var is a string.
isset($var) and empty($var) result are based on type of the variable, and could be tricky at some cases (like empty string ""). View the table in this page for more details.
UPDATE
There are actually 2 cases for this question:
Case 1: You're sure that your variable is always going to be a "string":
In this case, just test the length:
if(strlen($str) > 0) {
// do something..
}
Case 2: Your variable may and may not be a "string":
In this case, it depends on what you want to do. For me (most of the time), if it's not a string then I validate it as "false". You can do it this way:
if(is_string($var) && $var !== '') {// true only if it's a string AND is not empty
// do something ...
}
And to make it shorter and in 1 condition instead of 2 (specially useful if you're testing more than 1 string in same if condition), I made it into function:
function isNonEmptyString($var) {
return is_string($var) && $var !== '';
}
// Somewhere else..
// Reducing conditions to half
if(isNonEmptyString($var1) && isNonEmptyString($var2) && isNonEmptyString($var3)) {
// do something
}
If your variable $str is not defined then your strlen() method will throw an exception. That is the whole purpose of using isset() first.
trimming the string will also help if there are string with white spaces.
if (isset($str) && trim($str) !== '') {
// code
}
I think not, because strlen (string lenght) returns the lenght (integer) of your $str variable.
So if the variable is empty i would return 0. Is 0 greater then 0. Don't think so.
But i think the first method might be a little more safer. Because it checks if the variable is init, and if its not empty.