Reputation: 1156
Imagine having a StdClass
like this:
$foo = new stdClass();
$foo->bar = "baz";
$foo->baz = "1";
Now how could I cast $foo->baz
to an int? I know I can do the following:
$foo->baz = (int) $foo->baz;
However, this seems too long of a statement. Is there a shorter way to do this?
Upvotes: 0
Views: 443
Reputation: 4889
The standard "making operations shorter" happens with a user function. As short as it gets:
function as_int(&$var) {
$var = (int) $var;
}
as_int($foo->baz);
With this function, we pass in just the object's property by reference. A slightly longer form, useful if you may need access to the object inside the function, would be:
function prop_as_int(object $obj, string $prop) {
$obj->$prop = (int) $obj->$prop;
}
prop_as_int($foo, 'baz');
Either function results in:
var_dump($foo);
/*
object(stdClass)#2 (2) {
["bar"]=> string(3) "baz"
["baz"]=> int(1)
}
*/
There is no return
statement or referenced argument (&$obj
) here, since objects are passed by reference by default in PHP. You could add in some sanity checks, e.g. that the value is numeric/digits, that the property exists (in the second example), etc. into your function.
You could also use a custom class and an int-typed property instead of stdClass
; with a setter that handles type conformance, assuming you use strict types. If you don't use strict types, getting properties you add coerced into the correct datatype is really simple:
class Foo {
public int $baz;
}
$foo = new Foo();
$foo->baz = "1";
var_dump($foo);
/*
object(Foo)#2 (1) {
["baz"]=> int(1)
}
*/
As you can see, the value was automatically converted to the declared type of the property. If you had declare(strict_types = 1);
in use, it would however result in TypeError: Typed property Foo::$baz must be int, string used
, and the solution would be a type-confirming/coercing setter. Implementing that efficiently is however beyond the scope of this answer.
The downside of this approach is incurring the overhead of a function call, which is inconsequential if not called thousands of times. You'd want to do this if you find yourself frequently repeating an op in different contexts and want to cut down on typing. However if you do this in a loop iterating a large number of objects, spell it out. The performance gain is worth the trouble.
Finally, if your property names are unpredictable and you want to keep using stdClass
, but you know that any variable consisting of all digits/integers should be datatype int... Then, once the object has been saturated with data, iterate over the properties with a check for !is_int($prop) && ctype_digit($prop)
, which will match all non-int properties that consist of digits only, and cast them to int datatype. You'll want to turn that into a function, too: that's for homework.
Upvotes: 2
Reputation: 7703
This solution is shorter and uses a trick.
$foo->baz += 0;
However, this solution is difficult to understand and has only drawbacks in practice. It is therefore not recommended.
Upvotes: 1