My PHP function thinks my variable ($type) that I am passing to it is empty, but when I tell the function to return that variable ($ype), it returns exactly what I pasted to it.
function getData($result, $player = 0, $type = 0){
// This is here for me to test the bug and it prints $type ok, how when its == 0 ?
if ($type == 0){ return $type; }
if (!empty($result) AND $type != 0){
return $result[$player]->$type;
}elseif (!empty($result) AND $type == 0){
return $result[$player];
}else{
return FALSE;
}
}
This is how I call that function in the code:
$map_type = getData($replay, 1, "name");
Can there be a problem that the file with functions is included? I think nope, as other files and even functions within that file work ok.
I checked it multiple times and I do not see a typos there and I actually tested it and it worked OK.
Is there some bug with setting variables to 0 when they are not sent to function? Again, I dont think so, as the $player works and similar code works on my other functions too.
A loose-typed comparison such as if ($type == 0){ where $type is a string value can lead to unexpected results.
$type will be cast to a numeric for the comparison according to the rules defined here.
So while a string value like "13 Monkeys" will be loose cast to 13, and "13 Monkeys" == 0 will return a false; but a value without any leading digits such as "name" will be cast to a 0, so "name" == 0 is true.
A useful page detailing all the different type comparisons (both loose and strict comparisons) can be found in the PHP docs
Related
This is a crazy one...
I have a var coming in from a $_GET request. It echo's out fine but no matter what I do I can't pass it into a function without hard coding the value.
$txAmount = strip_tags($_GET['amt']);
Echoing $txAmount returns the following : 23.28684804 (as it should)
// Running some validation to ensure it's only digits and a period
if(preg_match_all('/^[0-9,.]*$/', $txAmount) && strpos($txAmount, '.') !== false) {
// then some other functions run, nothing that uses or affects $txAmount
// Then I call a class to run the function, all other variables being passed in are working fine
$findTX = $client->findTx($payment_address, $txAmount, $listTransactions);
// This is the function
function findTx($address, $txAmount, $array)
{
foreach ($array as $key => $val) {
if ($val['address'] === $address && $val['amount'] === $txAmount) {
return $val['txid'];
}
}
return null;
}
And this is where it goes tits up...
It is just refusing match the $txAmount to the $val['amount'] even though they are exactly the same and should return true.
The only way I can make it work is by hard coding the value (anywhere else in the script) All of these will work just fine :
$txAmount = 23.28684804;
$findTX = $client->findTx($payment_address, 23.28684804, $listTransactions);
if ($val['address'] === $address && $val['amount'] === 23.28684804)
I've even tried trimming the variable just in case there's some hidden white space there but still no joy :
$txAmount = trim($txAmount);
Am I just going mad here or is there some crazy quirk where PHP just hates this variable? Something to do with the 8 decimal places maybe?
Simple answer, in the findTx function if condition, use $val['amount'] == $txAmount instead of $val['amount'] === $txAmount.
Reason: In PHP, the === requires that the two values being compared are of the same type, whereas == will try and ignore the type difference. You can use gettype() to inspect the types of txAmount and $val['amount']. When $txAmount is derived from $_GET, the types can differ and comparison with === would require that you find a way of casting them to the same type - as indicated in the comments or by use of type casting operators such as $txAmount = (float) $txAmount,etc.
However, with ==, PHP will make sense of what is being compared, and changing from === to == will be easier in this case than going into details of working with the different data types, since this is just a comparison operation that is not changing the data in any way.
You may find the following reference on PHP data type juggling interesting: http://php.net/manual/en/language.types.type-juggling.php
The point is to validate, only when,
$this->data[$this->alias]['enabled']
It's equal to one. So, if $this->data[$this->alias]['enabled'] == 1, validate.
I was expecting that this peace of code, would do the job:
public function compareDates() {
if ($this->data[$this->alias]['enabled'] == 1) {
return $this->data[$this->alias]['firstPageEnterDate'] < $this->data[$this->alias]['firstPageLeaveDate'];
}
}
However it seems that that doesn't work as I expected. Instead, it gets always validated, regardless the value of $this->data[$this->alias]['enabled']
This code, however, seems to do the job just fine:
public function compareDates() {
if ($this->data[$this->alias]['enabled'] != 1) return true; // we don't want to check
return $this->data[$this->alias]['firstPageEnterDate'] < $this->data[$this->alias]['firstPageLeaveDate'];
}
What is, in your understanding, the meaning of "we don't want to check"?
Why: if ($this->data[$this->alias]['enabled'] == 1) is not enough?
Can anyone care to explain?
Update:
If I do:
public function compareDates()
{
if ($this->data[$this->alias]['enabled'] === "1") {
return $this->data[$this->alias]['firstPageEnterDate'] < $this->data[$this->alias]['firstPageLeaveDate'];
} else {
return true;
}
}
It works as well. My question is:
Why do I need to explicitly declare the return true?;
You're doing a simple comparison (==) so PHP is looking for "truthy" statements. So ANY value that is not "falsey" will evaluate your statement (i.e. 0, false, empty strings, NULL). You can find a complete list here.
The best way around this is to use equivalency to ensure it's the exact value you want
if ($this->data[$this->alias]['enabled'] === 1)
That will force PHP to look for an integer of 1. Be aware, though, that your value MUST be the same. In other words
if('1' === 1)
Is always false because string 1 is not the same as integer 1
I have encountered a very weird and concerning problem in some of my PHP code. A variable that I have returns true in an IF statement when it clearly should return false.
$pr = $_SESSION['fin_print_printer']; //this should equal 0
print $pr; //this returns 0, as it should
if($pr == "L"){
print "local";
} else {
print "serve";
}
print $pr; //this returns 0 again, as it should
This prints "local" in my script (in between the two zeros) and does not print "serve". With over 100,000 lines of code in my project, I've not experienced this issue yet, and now I can't figure out what is going on.
If I do if($pr === "L"), then it works as expected, but the above does not.
PHP is trying to typecast 'L' into an int, which results in 0.
intval('L'); // 0
Change your code into the following so it will take types into account:
if($pr === "L")
{
print "local";
}
else
{
print "serve";
}
Or manually typecast $pr to a string.
// You can also to (string)$pr ("0" instead of 0)
if(strval($pr) == "L")
{
print "local";
}
else
{
print "serve";
}
Maybe if you use typecasting (I did't check it):
if ( (string)$pr == "L" ) {
print "local";
} else {
print "serve";
}
Little known approach: You can also do the casting like
if ("L" == $pr) {
Because with loose comparisons, PHP casts the right value to the left value's type, and as you've already been made aware, while string(1)"L" is casted to int(0), int(0) is casted to string(1)"0".
Im currently testing a simple PHP function.
I want to to return the currently value of a field if the function is called without any parameter passed or set a new value if a parameter is passed.
Strange thing is: if I pass 0 (var_dump is showing correct value int(1) 0), the function goes into the if branch like i called the function without any value and i just don't get why.
function:
public function u_strasse($u_strasse = 'asdjfklhqwef'){
if($u_strasse == 'asdjfklhqwef'){
return $this->u_strasse;
} else {
// set new value here
}
}
either u_strasse() or u_strasse(0) gets me in the if branch.
You should use null as the default value:
public function u_strasse($u_strasse = null)
{
if ($u_strasse === null) { $u_strasse = 'asdjfklhqwef'; }
// rest of function
}
When comparing variables of different types (specifically strings and numbers), both values will be converted to a number. Therefore, your 'asdjfklhqwef' converts to 0 (number), the comparison is true.
http://www.php.net/manual/en/language.operators.comparison.php
Use === instead of ==:
public function u_strasse($u_strasse = 'asdjfklhqwef'){
if($u_strasse === 'asdjfklhqwef'){
return $this->u_strasse;
} else {
// set new value here
}
}
In case of == php tries to convert 'asdjfklhqwef' to number (because you pass $u_strasse as a number) and (int)'asdjfklhqwef' equals 0. To avoid this behavior you need to compare strictly (===)
Read more about difference in == and === here
Pass '0' instead of 0. The former will be a string.
You can cast it like this:
$myvar = 0;
u_strasse((string)$myvar);
Since PHP is a dynamic language what's the best way of checking to see if a provided field is empty?
I want to ensure that:
null is considered an empty string
a white space only string is considered empty
that "0" is not considered empty
This is what I've got so far:
$question = trim($_POST['question']);
if ("" === "$question") {
// Handle error here
}
There must be a simpler way of doing this?
// Function for basic field validation (present and neither empty nor only white space
function IsNullOrEmptyString($str){
return ($str === null || trim($str) === '');
}
Old post but someone might need it as I did ;)
if (strlen($str) == 0){
do what ever
}
replace $str with your variable.
NULL and "" both return 0 when using strlen.
Use PHP's empty() function. The following things are considered to be empty
"" (an empty string)
0 (0 as an integer)
0.0 (0 as a float)
"0" (0 as a string)
NULL
FALSE
array() (an empty array)
$var; (a variable declared, but without a value)
For more details check empty function
I'll humbly accept if I'm wrong, but I tested on my own end and found that the following works for testing both string(0) "" and NULL valued variables:
if ( $question ) {
// Handle success here
}
Which could also be reversed to test for success as such:
if ( !$question ) {
// Handle error here
}
Beware false negatives from the trim() function — it performs a cast-to-string before trimming, and thus will return e.g. "Array" if you pass it an empty array. That may not be an issue, depending on how you process your data, but with the code you supply, a field named question[] could be supplied in the POST data and appear to be a non-empty string. Instead, I would suggest:
$question = $_POST['question'];
if (!is_string || ($question = trim($question))) {
// Handle error here
}
// If $question was a string, it will have been trimmed by this point
There is no better way but since it's an operation you usually do quite often, you'd better automatize the process.
Most frameworks offer a way to make arguments parsing an easy task. You can build you own object for that. Quick and dirty example :
class Request
{
// This is the spirit but you may want to make that cleaner :-)
function get($key, $default=null, $from=null)
{
if ($from) :
if (isset(${'_'.$from}[$key]));
return sanitize(${'_'.strtoupper($from)}[$key]); // didn't test that but it should work
else
if isset($_REQUEST[$key])
return sanitize($_REQUEST[$key]);
return $default;
}
// basics. Enforce it with filters according to your needs
function sanitize($data)
{
return addslashes(trim($data));
}
// your rules here
function isEmptyString($data)
{
return (trim($data) === "" or $data === null);
}
function exists($key) {}
function setFlash($name, $value) {}
[...]
}
$request = new Request();
$question= $request->get('question', '', 'post');
print $request->isEmptyString($question);
Symfony use that kind of sugar massively.
But you are talking about more than that, with your "// Handle error here
". You are mixing 2 jobs : getting the data and processing it. This is not the same at all.
There are other mechanisms you can use to validate data. Again, frameworks can show you best pratices.
Create objects that represent the data of your form, then attach processses and fall back to it. It sounds far more work that hacking a quick PHP script (and it is the first time), but it's reusable, flexible, and much less error prone since form validation with usual PHP tends to quickly become spaguetti code.
This one checks arrays and strings:
function is_set($val) {
if(is_array($val)) return !empty($val);
return strlen(trim($val)) ? true : false;
}
to be more robust (tabulation, return…), I define:
function is_not_empty_string($str) {
if (is_string($str) && trim($str, " \t\n\r\0") !== '')
return true;
else
return false;
}
// code to test
$values = array(false, true, null, 'abc', '23', 23, '23.5', 23.5, '', ' ', '0', 0);
foreach ($values as $value) {
var_export($value);
if (is_not_empty_string($value))
print(" is a none empty string!\n");
else
print(" is not a string or is an empty string\n");
}
sources:
https://www.php.net/manual/en/function.is-string.php
https://www.php.net/manual/en/function.trim.php
When you want to check if a value is provided for a field, that field may be a string , an array, or undifined. So, the following is enough
function isSet($param)
{
return (is_array($param) && count($param)) || trim($param) !== '';
}
use this :
// check for null or empty
if (empty($var)) {
...
}
else {
...
}
empty() used to work for this, but the behavior of empty() has changed several times. As always, the php docs are always the best source for exact behavior and the comments on those pages usually provide a good history of the changes over time. If you want to check for a lack of object properties, a very defensive method at the moment is:
if (is_object($theObject) && (count(get_object_vars($theObject)) > 0)) {