I like to program object oriented so I want to make my own IntegerObject class. But when I try to execute the following code:
$x = new IntegerObject(3)
echo $x / 3;
I get the error:
Object of class IntegerObject could not be converted to int
Is there a magic function like __toString() to cast an object to an integer?
Workaround
As PHP is dynamically type casting language you can magically cast to string and the PHP will cast it to integer:
$x = new IntegerObject(3);
echo "$x" / 3;
You can cast to an integer using the (int) operator:
$x = new IntegerObject(3);
var_dump((int) "$x" / 3);
That should show you that the result is an int.
Related
I've seen some code written like this, and I'm really curious what it does and what it's for. Sorry for the unclear title, I appreciate all answers!
Edit: In particular I'm curious about the (string) $variable part
It's called type casting
Type casting in PHP works much as it does in C: the name of the desired type is written in parentheses before the variable which is to be cast.
<?php
$foo = 10; // $foo is an integer
$bar = (boolean) $foo; // $bar is a boolean
?>
The casts allowed are:
(int), (integer) - cast to integer
(bool), (boolean) - cast to boolean
(float), (double), (real) - cast to float
(string) - cast to string
(array) - cast to array
(object) - cast to object
(unset) - cast to NULL (PHP 5)
In your specific example a variable was being cast to a string before being passed as a parameter to testFunction()
It is a function call with an argument. In this case, a variable $variable has been cast to a string for the argument.
class wat
{
public $a = 3.14;
public $x = 9;
public $y = 2;
}
$a = new wat();
var_dump(1000 + $a);
var_dump($a + 1000);
The output is:
int(1001)
int(1001)
Well, adding the wat* object to an integer is obviously not the right thing to do, since PHP complains about it with "Object of class wat could not be converted to int", but still, what does it do?
(I also have a practical reason for asking this, I want to refactor a function to get rid of the "PHP Notice", while still keeping behaviour completely unchanged.)
*: http://img.youtube.com/vi/kXEgk1Hdze0/1.jpg
Addition (+) implicitly casts both operands to float if either one of them is float, otherwise both operands are cast to int (See paragraph #2.)
It seems that, at least for now, an object cast to int results in the value 1, hence the result 1000 + 1 = 1001 or 1 + 1000 = 1001, however, per the documentation, the behavior is undefined and should not be relied upon.
If you've turned on E_NOTICE error reporting, a notice should also be produced, saying that object could not be converted to int.
You're right that you shouldn't cast an Object to an Integer and you can't!
Than's why PHP assigns the integer 1 to the variable and should give you a notice which looks like this:
Notice: Object of class foo could not be converted to int in /path/to/file.php on line 1
$foo is now 1
int(1)
to be sure I get the code which actually do the cast:
from Zend/zend_operators.c:
case IS_OBJECT:
{
int retval = 1;
/* some other code */
ZVAL_LONG(op, retval); // < This sets the 1 you see.
return;
}
so it is not like i said before a internal cast ((int)(boolean)$object)
by doing this they preserve semantics of 0,"",NULL,false = false and !0,"...",Object = true
I was reading PHP manual and I came across type juggling
I was confused, because I've never came across such thing.
$foo = 5 + "10 Little Piggies"; // $foo is integer (15)
When I used this code it returns me 15, it adds up 10 + 5 and when I use is_int() it returns me true ie. 1 where I was expecting an error, it later referenced me to String conversion to numbers where I read If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero)
$foo = 1 + "bob3"; /* $foo is int though this doesn't add up 3+1
but as stated this adds 1+0 */
now what should I do if I want to treat 10 Little Piggies OR bob3 as a string and not as an int. Using settype() doesn't work either. I want an error that I cannot add 5 to a string.
If you want an error, you need to trigger an error:
$string = "bob3";
if (is_string($string))
{
trigger_error('Does not work on a string.');
}
$foo = 1 + $string;
Or if you like to have some interface:
class IntegerAddition
{
private $a, $b;
public function __construct($a, $b) {
if (!is_int($a)) throw new InvalidArgumentException('$a needs to be integer');
if (!is_int($b)) throw new InvalidArgumentException('$b needs to be integer');
$this->a = $a; $this->b = $b;
}
public function calculate() {
return $this->a + $this->b;
}
}
$add = new IntegerAddition(1, 'bob3');
echo $add->calculate();
This is by design as a result of PHP's dynamically typed nature and of course lack of an explicit type declaration requirement. Variable types are determined based on context.
Based on your example, when you do:
$a = 10;
$b = "10 Pigs";
$c = $a + $b // $c == (int) 20;
Calling is_int($c) will of course always evaluate to a boolean true because PHP has decided to convert the result of the statement to an integer.
If you're looking for an error by the interpreter, you won't get it since this is, like I mentioned, something built into the language. You might have to write a lot of ugly conditional code to test your data types.
Or, if you want to do that for testing arguments passed to your functions - that's the only scenario which I can think of where you might want to do this - you can trust the client invoking your function to know what they are doing. Otherwise, the return value can simply be documented to be undefined.
I know coming from other platforms and languages, that might be hard to accept, but believe it or not a lot of great libraries written in PHP follow that same approach.
In PHP you can typecast something as an object like this; (object) or you can use settype($var, "object") - but my question is what is the difference between the two?
Which one is more efficient / better to use? At the moment I find using (object) does the job, but wondering why there is a settype function as well.
Casting changes what the variable is being treated as in the current context, settype changes it permanently.
$value = "100"; //Value is a string
echo 5 + (int)$value; //Value is treated like an integer for this line
settype($value,'int'); //Value is now an integer
Basically settype is a shortcut for:
$value = (type)$value;
settype() alters the actual variable it was passed, the parenthetical casting does not.
If you use settype on $var to change it to an integer, it will permanently lose the decimal portion:
$var = 1.2;
settype($var, "integer");
echo $var; // prints 1, because $var is now an integer, not a float
If you just do a cast, the original variable is unchanged.
$var = 1.2;
$var2 = (integer) $var;
echo $var; // prints 1.2, because $var didn't change type and is still a float
echo $var2; // prints 1
It's worth mentioning that settype does NOT change the variable type permanently. The next time you set the value of the variable, PHP will change its type as well.
$value = "100"; //Value is a string
echo 5 + (int)$value; //Value is treated like an integer for this line
settype($value,'int'); //Value is now an integer
$value = "Hello World"; //Now value is a string
$value = 7; // Now value is an integer
Type Juggling can be frustrating but if you understand what's happening and know your options it can be managed. Use var_dump to get the variables type and other useful info.
The value of $total_results = 10
$total_results in an object, according to gettype()
I cannot use mathematical operators on $total_results because it's not numeric
Tried $total_results = intval($total_results) to convert to an integer, but no luck
The notice I get is: Object of class Zend_Gdata_Extension_OpenSearchTotalResults could not be converted to int
How can I convert to an integer?
Does this work?
$val = intval($total_results->getText());
$results_numeric = (int) $total_results;
or maybe this:
$results_numeric = $total_results->count();
perhaps the object has a build in method to get it as an integer?
Otherwise try this very hacky approach (relys on __toString() returning that 10)
$total_results = $total_results->__toString();
$total_results = intval($total_results);
However if the object has a build in non-magic method, you should use that!
You can see the methods of the class here. Then you can try out the different methods yourself. There is a getText() method for example.
try
class toValue {
function __toString()
{
return '3'; // you must return a string
}
}
$a = new toValue;
var_dump("$a" + 2);
result:
int(5)