This question already has answers here:
PHP is confused when adding and concatenating
(3 answers)
Closed 6 years ago.
Today i am working on a small PHP code to plus/minus and multiply, but i end up found something which i wasn't knew before.
I was Plus 2 value, 123456+123456=24690 and my code is this:
<?php
$value1=12345;
$value2=12345;
$output=$value1+$value2;
echo $output;
?>
Which return a correct value:
So than i have to print this value with string Like this:
Total Value: 24690
I use this code:
echo 'Total Value:'.$value1+$value2;
Its return: 12345 instead of
Total Value: 24690
I know that "." isn't a Arithmetic operators, so i need small explanation why is this doing that.
But when i do
echo 'Total Value:'.($value1+$value2);
Its work fine!
Little Confused!
It first concatenates the $value1 with the string and then tries to add it to a string and number can't be added to string and hence you get that output.
While using braces, it just concatenates the contents of the brace and performs the mathematical operation inside the brace.
It follows BODMAS
When you
echo 'Total Value:'.$value1+$value2;
code execution will be like this actually:
echo ('Total Value: ' . $value1) + $value2;
This behavior is called Type Juggling. From the manual it states:
a variable's type is determined by the context in which the variable is used. That is to say, if a string value is assigned to variable $var, $var becomes a string. If an integer value is then assigned to $var, it becomes an integer.
Example:
$foo = "1"; // $foo is string (ASCII 49)
$foo *= 2; // $foo is now an integer (2)
More examples on the link.
Related
Firstly, let's say for the sake of argument, the reasons why I want to do this is arbitrary and not solution specific.
I would like to explicitly cast a variable, regardless of input, and increment it after typecasting, not with the original variable. For example, not like this:
$num = "47 downvotes";
(int) ++$num;
I am looking for something similar to this psuedo-coded version, or a variation thereof:
$num = "value";
++((int) $num);
For PHP being loose, I was really hoping this to work, but I can't use the Pre-increment operator without creating another variable first.
$num = "value";
$cast = (int) $num;
echo ++$cast;
While testing, I found that PHP is loose enough for it to work by adding a digit however:
$num = "47 dogs";
echo ((int) $num) + 1;
I also understand my first example, isn't wrong, but again, for arbitrary reasons, I need to make sure it has been casted prior to incrementing/decrementing.
So the question is, why is PHP loose enough for the latter to compile?
If you could provide resources or links to any reputable reading material I would appreciate that as well.
With explicit typecasting you have to assign the result to a variable. In your examples, you are trying to increment variables when they are strings, which fails or doesn't produce the result you expect in combination with typecasting.
Look at your original example:
<?php
$num = "47 downvotes";
echo $num . PHP_EOL;
echo ++$num;
The result of incrementing a string isn't what you expect it to be:
47 downvotes
47 downvotet
So your original supposition is that PHP doesn't work when in fact it does.
$num = "47 downvotes";
echo (int) ++$num . PHP_EOL;
$num2 = "47";
echo (int) ++$num2;
Output:
47
48
The process of typecasting is inherently complicated, and has all sorts of behavior that can produce unexpected results, and just isn't the catchall dependable "fix your input" that will let you find the numeric portion of any string available to you in a single line of code, but that doesn't mean that PHP is flawed.
I understand that, with a sting assigned to a variable, individual characters can be expressed by using the variable as an indexed array, but why does the code below, using an associative array, not just die with missing required? Why does 'isset' not throw FALSE on an array key that definitely doesn't exist?
unset($a);
$a = 'TESTSTRING';
if(!isset($a['anystring'])){
die('MISSING REQUIRED');
}else{
var_dump($a['anystring']);
}
The above example will output:
string(1) "T"
EDIT:
As indicated by Jelle Keiser, this is probably the safer thing to do:
if(!array_key_exists('required',$_POST)){
die('MISSING REQUIRED');
}else{
echo $_POST['required'];
}
What PHP is doing is using your string as a numeric index. In this case, 'anystring' is the equivalent of 0. You can test this by doing
<?php
echo (int)'anystring';
// 0
var_dump('anystring' == 0);
// bool(true)
PHP does a lot of type juggling, which can lead to "interesting" results.
$a is a string not an associative array.
If you want to access it that way you have to do something like this.
$a['anystring'] = 'TESTSTRING';
You need to use array_key_exists() to test if a key exists
The working of isset is correct in your case.
Because $a is a string, the index-operator will give you the specified char in the string at the declared position. (like a "Char-Array")
A small example:
$a = 'TESTSTRING';
echo $a[0]; // Output: T
echo $a[1]; // Output: E
// ...
This will output the first and the second character at index 0 and 1 of the string.
And because the index-operator always expects an integer value on strings. The given value will be automatically casted to an integer. You can see this, when you cast the string to an integer, like this:
echo (int) 'TESTSTRING'; // Output: 0
For char-access on strings, also see the PHP-Manual.
Try enabling PHP to show all errors by using error_reporting(E_ALL);
This should give you a warning saying you are using an illegal offset. PHP therefore automatically assumes you are looking for the first element in the array or letter in this case.
it works as expected for... it returned false... but when I force it to return true ... itz throws an error saying illegal offset somekind.... but still output the first string.... as anystring casted as int equals to 0.. check the version of php you are using bro... I used notepad++ to create the php file... no special ide...
a single line of code :
echo eval("return 011");
the output is 9 because PHP think 011 is an octal value : Ok.
Now, how to force php to evaluate "011" as "11" ?
Just use the + operator to turn a string into a regular number; its operation is similar to doing an (int) type cast or by calling intval().
$x = '011';
echo +$x; // 11
The real question is why your code has an eval() in the first place. Apart from modifying the string before it's evaluated, there's nothing much you could do about that.
Update
If you're evaluating a mathematical expression, you could remove any leading zeroes before integer values like so:
$x = '5 * 011';
$x = preg_replace('/(?<=[^\d.]|^)0(?=\d+)/', '', $x); // "5 * 11"
Did you mean intval() ?
<?php echo intval('011');// will return 11?>
Add the (int) to change the data type to integer.
echo (int)'011';
echo eval("return (int)'011';");
Or what about changing it to:
echo eval("return 11;");
But if you want it to return 9 without changing the code itself, no this is not possible.
I was working on some data parsing code while I came across the following.
$line = "100 something is amazingly cool";
$key = 100;
var_dump($line == $key);
Well most of us would expect the dump to produce a false, but to my surprise the dump was a true!
I do understand that in PHP there is type conversion like that:
$x = 5 + "10 is a cool number"; // as documented on PHP manual
var_dump($x); // int(15) as documented.
But why does a comparison like how I mentioned in the first example converts my string to integer instead of converting the integer to string.
I do understand that you can do a === strict-comparison to my example, but I just want to know:
Is there any part of the PHP documentation mentioning on this behaviour?
Can anyone give an explanation why is happening in PHP?
How can programmers prevent such problem?
If I recal correcly PHP 'casts' the two variables to lowest possible type.
They call it type juggling.
try: var_dump("something" == 0);
for example, that'll give you true . . had that bite me once before.
More info: http://php.net/manual/en/language.operators.comparison.php
I know this is already answered and accepted, but I wanted to add something that may help others who find this via search.
I had this same problem when I was comparing a post array vs. keys in a PHP array where in my post array, I had an extra string value.
$_POST["bar"] = array("other");
$foo = array(array("name"=>"foobar"));
foreach($foo as $key=>$data){
$foo[$key]["bar"]="0";
foreach($_POST["bar"] as $bar){
if($bar==$key){
$foo[$key]["bar"]="1";
}
}
}
From this you would think that at the end $foo[0]["bar"] would be equal to "0" but what was happening is that when $key = int 0 was loosely compared against $bar = string "other" the result was true to fix this, I strictly compared, but then needed to convert the $key = int 0 into a $key = string "0" for when the POST array was defined as array("other","0"); The following worked:
$_POST["bar"] = array("other");
$foo = array(array("name"=>"foobar"));
foreach($foo as $key=>$data){
$foo[$key]["bar"]="0";
foreach($_POST["bar"] as $bar){
if($bar==="$key"){
$foo[$key]["bar"]="1";
}
}
}
The result was $foo[0]["bar"]="1" if "0" was in the POST bar array and $foo[0]["bar"]="0" if "0" was not in the POST bar array.
Remember that when comparing variables that your variables may not being compared as you think due to PHP's loose variable typing.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
PHP String in Array Only Returns First Character
I've got following problem. When I run script below I got string(1) "F" as an output. How is that possible? No error, notice displayed.. nothing. Key whatever doesn't exist in $c. Can you explain that?
<?php
$c = 'FEEDBACK_REGISTER_ACTIVATION_COMPLETED_MSG';
var_dump ($c['whatever']);
?>
I'm having this issue on PHP 5.3.3. (LINUX)
PHP lets you index on strings:
$str = "Hello, world!";
echo $str[0]; // H
echo $str[3]; // l
PHP also converts strings to integers implicitly, but when it fails, uses zero:
$str = "1";
echo $str + 1; // 2
$str = "invalid";
echo $str + 1; // 1
So what it's trying to do is index on the string, but the index is not an integer, so it tries to convert the string to an integer, yielding zero, and then it's accessing the first character of the string, which happens to be F.
Through Magic type casting of PHP when an associative array can not find the index, index itself is converted to int 0 and hence it is like
if
$sample = 'Sample';
$sample['anystring'] = $sample[0];
so if o/p is 'S';