Related
I'm a little unclear about the rule for integer and string variables in php.
If I am dealing with counters (simple integers starting with 1 and counting upwards), do I need to specify variables as integers and then convert to strings when I use or can I leave them as strings and conversions will happen automatically in php at run time?
Or are there too many specific cases that have different rules? Some thoughts would be appreciated...
PHP automatically converts valriables when needed. you just have to be careful when you are going to compare them.
If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically. These rules also apply to the switch statement. The type conversion does not take place when the comparison is === or !== as this involves comparing the type as well as the value.
take a look at this
There's no variable declaration in PHP the variable will take the type appropiate to the data you assign to it.
$var = 1; //here $var is an int
$var = '1'; // now is a string
$var = true; //and now a boolean
I have been doing some research online and it appears that the answer to my question is no, but I realize there are times when I might miss something or search for something incorrectly. I know in languages like C++, when a variable is declared it can be declared as int or string. Is it possible to force this in PHP?
For Example:
<?php
(int)$var = 5;
?>
will be validated and not cause an error in PHP, but:
<?php
$var = 5;
?>
will cause an error because it was not cast as a type string, int, object, etc...
I know PHP is loosely typed so this may not be an option, however I would like to use it that way I ensure that I sanitize data appropriately and improve readability by letting others know exactly what is going on with the code. I am hoping there is a way to enforce this in the php.ini file or to load it in a script that will always be executed by my program.
Thank you for any help you can offer!
PHP is loosely typed and does not require you to declare a variable type when declaring a variable. You can’t change that behavior with a magic php.ini directive.
The benefit of having “loose typing” is that it allows for flexibility. It allows you to create dynamic applications without having to worry about the type of the variable – PHP makes this possible by not enforcing variable types.
However, if you must convert a variable into a particular format, just cast it:
$int = (int) $foo;
$str = (string) $foo;
$bool = (bool) $foo;
$float = (float) $foo;
...
There are functions to do the same, e.g. intval(), strval(), boolval() – all of them do the same task, but a function is very useful when you want to use it as a callback to another function.
After some work in C and Java I've been more and more annoyed by the wild west laws in PHP. What I really feel that PHP lacks is strict data types. The fact that string('0') == (int)0 == (boolean)false is one example.
You cannot rely on what the data type a function returns is. You can neither force arguments of a function to be of a specific type, which might lead to a non strict compare resulting in something unexpected. Everything can be taken care of, but it still opens up for unexpected bugs.
Is it good or bad practice to typecast arguments received for a method? And is it good to typecast the return?
IE
public function doo($foo, $bar) {
$foo = (int)$foo;
$bar = (float)$bar;
$result = $bar + $foo;
return (array)$result;
}
The example is quite stupid and I haven't tested it, but I think everyone gets the idea. Is there any reason for the PHP-god to convert data type as he wants, beside letting people that don't know of data types use PHP?
For better or worse, loose-typing is "The PHP Way". Many of the built-ins, and most of the language constructs, will operate on whatever types you give them -- silently (and often dangerously) casting them behind the scenes to make things (sort of) fit together.
Coming from a Java/C/C++ background myself, PHP's loose-typing model has always been a source of frustration for me. But through the years I've found that, if I have to write PHP I can do a better job of it (i.e. cleaner, safer, more testable code) by embracing PHP's "looseness", rather than fighting it; and I end up a happier monkey because of it.
Casting really is fundamental to my technique -- and (IMHO) it's the only way to consistently build clean, readable PHP code that handles mixed-type arguments in a well-understood, testable, deterministic way.
The main point (which you clearly understand as well) is that, in PHP, you can not simply assume that an argument is the type you expect it to be. Doing so, can have serious consequences that you are not likely to catch until after your app has gone to production.
To illustrate this point:
<?php
function displayRoomCount( $numBoys, $numGirls ) {
// we'll assume both args are int
// check boundary conditions
if( ($numBoys < 0) || ($numGirls < 0) ) throw new Exception('argument out of range');
// perform the specified logic
$total = $numBoys + $numGirls;
print( "{$total} people: {$numBoys} boys, and {$numGirls} girls \n" );
}
displayRoomCount(0, 0); // (ok) prints: "0 people: 0 boys, and 0 girls"
displayRoomCount(-10, 20); // (ok) throws an exception
displayRoomCount("asdf", 10); // (wrong!) prints: "10 people: asdf boys, and 10 girls"
One approach to solving this is to restrict the types that the function can accept, throwing an exception when an invalid type is detected. Others have mentioned this approach already. It appeals well to my Java/C/C++ aesthetics, and I followed this approach in PHP for years and years. In short, there's nothing wrong with it, but it does go against "The PHP Way", and after a while, that starts to feel like swimming up-stream.
As an alternative, casting provides a simple and clean way to ensure that the function behaves deterministically for all possible inputs, without having to write specific logic to handle each different type.
Using casting, our example now becomes:
<?php
function displayRoomCount( $numBoys, $numGirls ) {
// we cast to ensure that we have the types we expect
$numBoys = (int)$numBoys;
$numGirls = (int)$numGirls;
// check boundary conditions
if( ($numBoys < 0) || ($numGirls < 0) ) throw new Exception('argument out of range');
// perform the specified logic
$total = $numBoys + $numGirls;
print( "{$total} people: {$numBoys} boys, and {$numGirls} girls \n" );
}
displayRoomCount("asdf", 10); // (ok now!) prints: "10 people: 0 boys, and 10 girls"
The function now behaves as expected. In fact, it's easy to show that the function's behavior is now well-defined for all possible inputs. This is because the the cast operation is well-defined for all possible inputs; the casts ensure that we're always working with integers; and the rest of the function is written so as to be well-defined for all possible integers.
Rules for type-casting in PHP are documented here, (see the type-specific links mid-way down the page - eg: "Converting to integer").
This approach has the added benefit that the function will now behave in a way that is consistent with other PHP built-ins, and language constructs. For example:
// assume $db_row read from a database of some sort
displayRoomCount( $db_row['boys'], $db_row['girls'] );
will work just fine, despite the fact that $db_row['boys'] and $db_row['girls'] are actually strings that contain numeric values. This is consistent with the way that the average PHP developer (who does not know C, C++, or Java) will expect it to work.
As for casting return values: there is very little point in doing so, unless you know that you have a potentially mixed-type variable, and you want to always ensure that the return value is a specific type. This is more often the case at intermediate points in the code, rather than at the point where you're returning from a function.
A practical example:
<?php
function getParam( $name, $idx=0 ) {
$name = (string)$name;
$idx = (int)$idx;
if($name==='') return null;
if($idx<0) $idx=0;
// $_REQUEST[$name] could be null, or string, or array
// this depends on the web request that came in. Our use of
// the array cast here, lets us write generic logic to deal with them all
//
$param = (array)$_REQUEST[$name];
if( count($param) <= $idx) return null;
return $param[$idx];
}
// here, the cast is used to ensure that we always get a string
// even if "fullName" was missing from the request, the cast will convert
// the returned NULL value into an empty string.
$full_name = (string)getParam("fullName");
You get the idea.
There are a couple of gotcha's to be aware of
PHP's casting mechanism is not smart enough to optimize the "no-op" cast. So casting always causes a copy of the variable to be made. In most cases, this not a problem, but if you regularly use this approach, you should keep it in the back of your mind. Because of this, casting can cause unexpected issues with references and large arrays. See PHP Bug Report #50894 for more details.
In php, a whole number that is too large (or too small) to represent as an integer type, will automatically be represented as a float (or a double, if necessary). This means that the result of ($big_int + $big_int) can actually be a float, and if you cast it to an int the resulting number will be gibberish. So, if you're building functions that need to operate on large whole numbers, you should keep this in mind, and probably consider some other approach.
Sorry for the long post, but it's a topic that I've considered in depth, and through the years, I've accumulated quite a bit of knowledge (and opinion) about it. By putting it out here, I hope someone will find it helpful.
The next version of PHP (probably 5.4) will support scalar type hinting in arguments.
But apart from that: Dynamic type conversion really isn't something you should hate and avoid. Mostly it will work as expected. And if it doesn't, fix it by checking it is_* of some type, by using strict comparison, ..., ...
You can use type hinting for complex types. If you need to compare value + type you can use "===" for comparison.
(0 === false) => results in false
(0 == false) => results in true
Also you write return (array)$result; which makes no sense. What you want in this case is return array($result) if you want the return type to be an array.
I don't think it's bad, but I would go one step further: Use type hinting for complex types, and throw an exception if a simple type isn't one you expect. This way you make clients aware of any costs/problems with the cast (such as loss of precision going from int -> float or float -> int).
Your cast to array in the above code there though is misleading -- you should just create a new array containing the one value.
That all said, your example above becomes:
public function doo($foo, $bar) {
if (!is_int($foo)) throw new InvalidArgumentException();
if (!is_float($bar)) throw new InvalidArgumentException();
$result = $bar + $foo;
return array($result);
}
No, it's not good to typecast because you don't know what you'll have in the end. I would personally suggest using functions such as intval(), floatval(), etc.
PHP:
$a = "0";
$b = "00";
var_dump(empty($a)); # True (wtf?)
var_dump($a == $b); # True... WTF???
var_dump(empty($b)); # False WWWTTTFFFF!!??
I've read the docs. But the docs don't give explanation as to why they designed it this way. I'm not looking for workarounds (I already know them), I'm looking for an explanation.
Why is it like this? Does this make certain things easier somehow?
As for "0" == "00" resolving to true, the answer lies in Comparison Operators:
If you compare an integer with a
string, the string is converted to a
number. If you compare two numerical
strings, they are compared as
integers. These rules also apply to
the switch statement.
(emphasis added)
Both "0" and "00" are numerical strings so a numerical comparison is performed and obviously 0 == 0.
I'd suggest using === instead if you don't want any implicit type conversion.
As for empty():
The following things are considered to
be empty:
"" (an empty string)
0 (0 as an integer)
"0" (0 as a string)
NULL
FALSE
array() (an empty array)
var $var; (a variable declared, but without a value in a class)
http://au2.php.net/empty
The following things are considered to be empty:
"0" (0 as a string)
but "00" will not be considered empty.
It all stems from the language designers goal of "doing the right thing".
That is a given piece of code should do what the niave programmer or casual viewer of a piece of code would expect it too. This was not an easy goal to acheive.
Php has avoided most of worst pitfalls of other languages (like C's if (a = b) { ... or perl' s if ( "xxxx" == 0) { print "True!"; }).
The 0 == 0000 and if ("000") { echo "True!"; } are two of the few cases where code might not do exactly what you expect, but in pracice it is seldom a problem. In my experience the "cure" using the exact comparison operator === is the one thing guarenteed to have novice php programmers scratching there heads and searching the manual.
It has do do with what PHP considers empty, and, as #Shadow imagined, it's a dynamic typing issue. 0 and 00 are equal in PHP's eyes. Consider using the strict equality instead:
($a === $b) // is a equal to b AND the same type (strings)
Check the docs for empty http://us.php.net/empty. That should take care of the first and third lines.
for the second, it's because PHP is dynamically typed. the interpreter is inferring the type of the variables for use in the context in which you have used them. In this case the interpreter is probably thinking that you are trying to compare numbers and converting the string to ints before comparing.
From the documentation one can assume that 0 can be either an int or a 1 char string to signify empty. 00 would be more of a formatting assumption since there's no such thing as 00, but there is 0. 00 would be implying a 2 integer format, but the empty() function is only written for 0.
FWIW IANA php developer.
How do I convert the value of a PHP variable to string?
I was looking for something better than concatenating with an empty string:
$myText = $myVar . '';
Like the ToString() method in Java or .NET.
You can use the casting operators:
$myText = (string)$myVar;
There are more details for string casting and conversion in the Strings section of the PHP manual, including special handling for booleans and nulls.
This is done with typecasting:
$strvar = (string) $var; // Casts to string
echo $var; // Will cast to string implicitly
var_dump($var); // Will show the true type of the variable
In a class you can define what is output by using the magical method __toString. An example is below:
class Bottles {
public function __toString()
{
return 'Ninety nine green bottles';
}
}
$ex = new Bottles;
var_dump($ex, (string) $ex);
// Returns: instance of Bottles and "Ninety nine green bottles"
Some more type casting examples:
$i = 1;
// int 1
var_dump((int) $i);
// bool true
var_dump((bool) $i);
// string "1"
var_dump((string) 1);
Use print_r:
$myText = print_r($myVar,true);
You can also use it like:
$myText = print_r($myVar,true)."foo bar";
This will set $myText to a string, like:
array (
0 => '11',
)foo bar
Use var_export to get a little bit more info (with types of variable,...):
$myText = var_export($myVar,true);
You can either use typecasting:
$var = (string)$varname;
or StringValue:
$var = strval($varname);
or SetType:
$success = settype($varname, 'string');
// $varname itself becomes a string
They all work for the same thing in terms of Type-Juggling.
How do I convert the value of a PHP
variable to string?
A value can be converted to a string using the (string) cast or the strval() function. (Edit: As Thomas also stated).
It also should be automatically casted for you when you use it as a string.
You are looking for strval:
string strval ( mixed $var )
Get the string value of a variable.
See the documentation on string for
more information on converting to
string.
This function performs no formatting
on the returned value. If you are
looking for a way to format a numeric
value as a string, please see
sprintf() or number_format().
For primitives just use (string)$var or print this variable straight away. PHP is dynamically typed language and variable will be casted to string on the fly.
If you want to convert objects to strings you will need to define __toString() method that returns string. This method is forbidden to throw exceptions.
Putting it in double quotes should work:
$myText = "$myVar";
I think it is worth mentioning that you can catch any output (like print_r, var_dump) in a variable by using output buffering:
<?php
ob_start();
var_dump($someVar);
$result = ob_get_clean();
?>
Thanks to:
How can I capture the result of var_dump to a string?
Another option is to use the built in settype function:
<?php
$foo = "5bar"; // string
$bar = true; // boolean
settype($foo, "integer"); // $foo is now 5 (integer)
settype($bar, "string"); // $bar is now "1" (string)
?>
This actually performs a conversion on the variable unlike typecasting and allows you to have a general way of converting to multiple types.
In addition to the answer given by Thomas G. Mayfield:
If you follow the link to the string casting manual, there is a special case which is quite important to understand:
(string) cast is preferable especially if your variable $a is an object, because PHP will follow the casting protocol according to its object model by calling __toString() magic method (if such is defined in the class of which $a is instantiated from).
PHP does something similar to
function castToString($instance)
{
if (is_object($instance) && method_exists($instance, '__toString')) {
return call_user_func_array(array($instance, '__toString'));
}
}
The (string) casting operation is a recommended technique for PHP5+ programming making code more Object-Oriented. IMO this is a nice example of design similarity (difference) to other OOP languages like Java/C#/etc., i.e. in its own special PHP way (whenever it's for the good or for the worth).
As others have mentioned, objects need a __toString method to be cast to a string. An object that doesn't define that method can still produce a string representation using the spl_object_hash function.
This function returns a unique identifier for the object. This id can be used as a hash key for storing objects, or for identifying an object, as long as the object is not destroyed. Once the object is destroyed, its hash may be reused for other objects.
I have a base Object class with a __toString method that defaults to calling md5(spl_object_hash($this)) to make the output clearly unique, since the output from spl_object_hash can look very similar between objects.
This is particularly helpful for debugging code where a variable initializes as an Object and later in the code it is suspected to have changed to a different Object. Simply echoing the variables to the log can reveal the change from the object hash (or not).
I think this question is a bit misleading since,
toString() in Java isn't just a way to cast something to a String. That is what casting via (string) does, and it works as well in PHP.
// Java
String myText = (string) myVar;
// PHP
$myText = (string) $myVar;
Note that this can be problematic as Java is type-safe (see here for more details).
But as I said, this is casting and therefore not the equivalent of Java's toString().
toString in Java doesn't just cast an object to a String. It instead will give you the String representation. And that's what __toString() in PHP does.
// Java
class SomeClass{
public String toString(){
return "some string representation";
}
}
// PHP
class SomeClass{
public function __toString()
{
return "some string representation";
}
}
And from the other side:
// Java
new SomeClass().toString(); // "Some string representation"
// PHP
strval(new SomeClass); // "Some string representation"
What do I mean by "giving the String representation"?
Imagine a class for a library with millions of books.
Casting that class to a String would (by default) convert the data, here all books, into a string so the String would be very long and most of the time not very useful.
To String instead will give you the String representation, i.e., only the library's name. This is shorter and therefore gives you less, but more important information.
These are both valid approaches but with very different goals, neither is a perfect solution for every case, and you have to choose wisely which fits your needs better.
Sure, there are even more options:
$no = 421337 // A number in PHP
$str = "$no"; // In PHP, the stuff inside "" is calculated and variables are replaced
$str = print_r($no, true); // Same as String.format();
$str = settype($no, 'string'); // Sets $no to the String Type
$str = strval($no); // Get the string value of $no
$str = $no . ''; // As you said concatenate an empty string works too
All of these methods will return a String, some of them using __toString internally and some others will fail on Objects. Take a look at the PHP documentation for more details.
Some, if not all, of the methods in the previous answers fail when the intended string variable has a leading zero, for example, 077543.
An attempt to convert such a variable fails to get the intended string, because the variable is converted to base 8 (octal).
All these will make $str have a value of 32611:
$no = 077543
$str = (string)$no;
$str = "$no";
$str = print_r($no,true);
$str = strval($no);
$str = settype($no, "integer");
The documentation says that you can also do:
$str = "$foo";
It's the same as cast, but I think it looks prettier.
Source:
Russian
English
Double quotes should work too... it should create a string, then it should APPEND/INSERT the casted STRING value of $myVar in between 2 empty strings.
You can always create a method named .ToString($in) that returns
$in . '';
If you're converting anything other than simple types like integers or booleans, you'd need to write your own function/method for the type that you're trying to convert, otherwise PHP will just print the type (such as array, GoogleSniffer, or Bidet).
PHP is dynamically typed, so like Chris Fournier said, "If you use it like a string it becomes a string". If you're looking for more control over the format of the string then printf is your answer.
You can also use the var_export PHP function.
$parent_category_name = "new clothes & shoes";
// To make it to string option one
$parent_category = strval($parent_category_name);
// Or make it a string by concatenating it with 'new clothes & shoes'
// It is useful for database queries
$parent_category = "'" . strval($parent_category_name) . "'";
For objects, you may not be able to use the cast operator. Instead, I use the json_encode() method.
For example, the following will output contents to the error log:
error_log(json_encode($args));
Try this little strange, but working, approach to convert the textual part of stdClass to string type:
$my_std_obj_result = $SomeResponse->return->data; // Specific to object/implementation
$my_string_result = implode ((array)$my_std_obj_result); // Do conversion
__toString method or (string) cast
$string=(string)$variable; //force make string
you can treat an object as a string
class Foo
{
public function __toString()
{
return "foo";
}
}
echo new Foo(); //foo
also, have another trick, ı assume ı have int variable ı want to make string it
$string=''.$intvariable;
This can be difficult in PHP because of the way data types are handled internally. Assuming that you don't mean complex types such as objects or resources, generic casting to strings may still result in incorrect conversion. In some cases pack/unpack may even be required, and then you still have the possibility of problems with string encoding. I know this might sound like a stretch but these are the type of cases where standard type juggling such as $myText = $my_var .''; and $myText = (string)$my_var; (and similar) may not work. Otherwise I would suggest a generic cast, or using serialize() or json_encode(), but again it depends on what you plan on doing with the string.
The primary difference is that Java and .NET have better facilities with handling binary data and primitive types, and converting to/from specific types and then to string from there, even if a specific case is abstracted away from the user. It's a different story with PHP where even handling hex can leave you scratching your head until you get the hang of it.
I can't think of a better way to answer this which is comparable to Java/.NET where _toString() and such methods are usually implemented in a way that's specific to the object or data type. In that way the magic methods __toString() and __serialize()/__unserialize() may be the best comparison.
Also keep in mind that PHP doesn't have the same concepts of primitive data types. In essence every data type in PHP can be considered an object, and their internal handlers try to make them somewhat universal, even if it means loosing accuracy such as when converting a float to int. You can't deal with types as you can in Java unless your working with their zvals within a native extension.
While PHP userspace doesn't define int, char, bool, or float as an objects, everything is stored in a zval structure which is as close to an object that you can find in C, with generic functions for handling the data within the zval. Every possible way to access data within PHP goes down to the zval structure and the way the zend vm allows you to handles them without converting them to native types and structures. With Java types you have finer grained access to their data and more ways to to manipulate them, but also greater complexity, hence the strong type vs weak type argument.
These links my be helpful:
https://www.php.net/manual/en/language.types.type-juggling.php
https://www.php.net/manual/en/language.oop5.magic.php
I use variableToString. It handles every PHP type and is flexible (you can extend it if you want).