Tip of the Day -- Casting and Datatypes

[thread=729156]Previous Tip: Boolean storage[/thread]

Forgive me for the delay - work and life interfered. I’ll try to remember to get these out on weekdays as intended. PM me for suggestions, reminders to make a post and suggestions.

Anyway, the subject of datatypes is one of those arcane necessities of programming that makes life difficult when you first start programming. At the beginning conceptualizing a variable as a “box” you can put stuff in is tricky, and advanced programmers forget how tricky. Worrying about datatype, well that’s right out.

PHP tries to help by being a “loosely-typed” language. What this means is that, as a language PHP doesn’t enforce datatype matching and casting until you ask it to. This has the effect of making life a little more difficult for experienced programmers, but the trade off is that the language is easier to learn.

In PHP all variables are prefixed with $. I once read or was told that the $ stood for scalar. What’s a scalar? Well, it’s a variable construct that can be anything.

You see, while PHP can handle any datatype in any variable, most languages can’t. C++ certainly can’t, and the PHP engine deals with this.

The main reason for the $ is speed - when looking up a variable for the current scope the engine does not have to traverse the constants, function and class names. This is important in an interpreted language, and less so for a compiled one - but I digress.

Eventually you will need to know the type of data you are working with, or insure that a variable is of a certain type. The most frequent time you will need to do this is with the database because the database fields are set up to deal with data by type. A varchar(20) field is meant for string data between 0 and 20 characters. An int(11) field is for 11 digit integers, and so on.

When you cast a variable, you force it’s datatype to become the type specified. There are two ways to do it. The older way


$a = '003';
echo $a; // '003';
$a = intval($a);
echo $a; // '3';

There are strval, boolval, and so on functions. The newer way is to set the type with a casting operator


$a = '003';
$a = (int) $a;
echo $a; // '3';

The current casting operators are:

[list]* or (integer) to cast to an integer
* or (real) to cast to a floating-point number
* to cast to a string
* or (boolean) to cast to a boolean
* to cast to an array
* to cast to an object
[/list]

With PHP 5.4 this will become more important as type hinting becomes more prevalent. Right now a function can require that its arguments match a certain datatype. The catch is the types supported in 5.3 are user defined objects and the array type, like so.


function ( myClass $a, array $b ) {}

If you pass an object (or anything) that isn’t an instance of myClass as the first argument to the function above it will throw a catchable fatal error. In PHP 5.4 the primitive datatypes will be type hintable (This is a pending feature addition and might be removed before final).


function ( bool $a, int $b ) {}

Now you might be wondering why you’d want to do that. Well, knowing the datatype makes the code easier to test and easier to write once you are used to it. It also opens the door to function overloading in future versions of PHP, at least at a syntax level. Function overloading allows different functions to be called depending on the datatype of the arguments. Example


// Theoretical code - will not run.
function validate ( int $a ) {}
function validate ( string $a) {}
function validate ( array $a ) {}
function validate ( $a ) {}

Here we have 4 functions with the exact same name - impossible under current PHP. In function overloading though the datatype determines the function that gets used - if the argument is a string the 2nd function is invoked. If the datatype isn’t an int, string or array the final function with the unspecified datatype is invoked.

C++ and several other languages already allow this sort of behavior.

Well, that’s enough for a simple tips post. Hope this is useful.

Thanks for this second “tip” post, Michael. I do have some minor questions and points, and some I’ll keep quiet for now!

First, given the title of the thread, I was expecting a little something more focussed on the actual job of casting variables (why do it? practical [every-day] examples, and so on) and something of a paragraph or two about the available data types themselves.

Secondly, forgive me if this sounds out of place (far from us to comment on writing style when you’re taking your own time out to write these!) but the post as a whole just feels wandering and a little lost.

Off Topic:

Is there perhaps some place for peer review of this kind of thing? Of course not in the same manner as academia, rather in the sense of putting heads together to get more than the sum of the parts. Hmm, I wonder.

Back to being positive; a little note is that (double) is also available (to cast to a float value) and (unset) is a special case which in essence just sets the value to NULL. And finally, I believe that being loosely typed is one of PHP’s awesome strengths. Being able to throw variables/values around and have them (mostly) just work is a really good thing in a language like PHP!

Yes, sometimes incorrect type can make a big difference, causing hard to trace bugs. For example, if you insert an integer value in Mongo database but then search for it using the string, for example ‘4’ instead of (int)4, you will not find anything. Mongo will allow storing string ‘4’ or int 4 in the same collection, unlike MySQL where type of column is defined and enforced by mysql driver.

So, I see it useful to have a type hint in classes that use Mongo or purhaps other types of NoSQL databases where database does not enforce type. It will just make it easier to catch an error by php at runtime.

I think this should make it into php.

Yes, it turned out that loosely typed is not a bad thing. Scala language is a proof. A major contributor to Java, creator of everything that’s great in Java 5 basically realized that having very strict type check was in his own words a mistake. He then created this new language Scala that is similar to Java but has support for procedual programming (unlike Java) as well as support for Closures. This really is a great confirmation that php is a good language because it already had everything that Scala was set to “fix” in Java, and on top of that it does not even need a compiler to run.

Here is the video of that Scala into: http://www.youtube.com/watch?v=J85F2C13r4Q

By the way, casting is not unique to php, in fact in Java casting is more powerful - you can cast an object of one type to become (not really become but pretend to be) an object of its’ sub-class. This is important and sometimes the only way to do certain things.

This is not possible in php currently. I don’t think it’s even being considered in php, probably because there is no real need for it in php.

Off Topic:

Many people think that, but 11 does not stand for how many digits you can store in the int. It stands for how many positions must be shown when using ZEROFILL.
For example the number 52 stored in and int(6) ZEROFILL will show as 000052.
The number of digits that can be stored in an int is fixed and has nothing to that with that number :slight_smile:

Hey Salathe, I suppose I’ll throw in a day to day experience I had at my job the other day that involved casting variables. Specifically dollar amounts.

I can’t say a ton due to confidentiality, but pretty straight forward I was working on a website that calculated prices for quotes, the site was considered to be 100% done and just needed some modifications. Me being silly and naive, assumed that some form of typecasting was being used. Until I got a call that the prices weren’t being calculated correctly, and couldn’t figure it out for the life of me. What ended up happening was all the prices were stored in different formats, such as:
int - 500 (Means $500.00)
string - 4,000 (Means $4,000.00)
float - 4.50 (Means $4.50)

This was such a mess, because what happened was the calculated price was forced as an integer using typecasting, which is wrong in the first place assuming no cents would be used. So in the end it was taking 4,000 and translating it to 4. Resulting in a $3,996 loss.

Overall I made it uniform, every price was run through a function that returned it in float format of for example 4503.12. Afterwards it was run to format how it looked on output, all in all, this was a place where typecasting was necessary.

All the while I had to ignore one of our developers yelling at PHP for not being more strict. :stuck_out_tongue:

@Michael Morris – Looking forward to more tips! Should be indexing them on your own blog or something, learned a bit here even though I knew the basics.

I sorta ran out of time - these are a bit off the cuff and I think I’ll end up doing most of them on my lunch break or in the morning before leaving for work, like today’s. Besides, I know I’m going to get a few things wrong eventually, and the thread itself can clarify things.

Like the zerofill thing. Didn’t know that.

Also, this particular tip touches on a subject beyond the scope of any one post. But let the thread itself expand upon and clarify the topic.