This post is archived and probably outdated.

Scalar type hints in PHP trunk

2010-08-07 23:00:00

So in my blog series I try to cover all additions to PHP trunk so I have to mention scalar type hints.

<?php
function print_float(float $f) {
    echo $f."\n";
}

for ($i = 1; $i < 5; $i++) {
    print_float( $i / 3 );
}
?>
	
0.33333333333333
0.66666666666667

Catchable fatal error: Argument 1 passed to print_float() must be of the type double, integer given, called in typehints.php on line 7 and defined in typehints.php on line 2

Is expected behavior in PHP's trunk. If you want such a thing to work please use the numeric type hint.

In case that wasn't enought fun: There's more!

<?php
function handle_result(int $i) {
    echo $i."\n";
}

$pdo = new PDO("mysql:host=localhost;dbname=test", "user", "pass");
$pdo->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, false);
$result = $pdo->query("SELECT 42 AS id");
$row = $result->fetch();
handle_result($row['id']);

$pdo = new PDO("mysql:host=localhost;dbname=test", "user", "pass");
$pdo->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, true);
$result = $pdo->query("SELECT 42 AS id");
$row = $result->fetch();
handle_result($row['id']);
?>
	
42

Catchable fatal error: Argument 1 passed to handle_result() must be of the type integer, string given, called in typehints.php on line 16 and defined in typehints.php on line 2

So what happens here? - Depending on the PDO::MYSQL_ATTR_DIRECT_QUERY option PDO will either emulate prepared statements (which would be irrelevant here, but that's another story) or use native prepared statements. When using prepared statements MySQL switches over to its "binary" protocol which returns the native types, else it always returns strings. When using PDO_mysql linked against mysqlnd the native type is returned to PHP. If I would use libmysql both times a string would be returned. In other words: The behavior is system dependent. The default behavior for other drivers isn't defined either. As PHP is a dynamically typed language this shouldn't matter, so depending on your driver the results vary. Great. Oh and did I mention that the types aren't specified, so a later version of a driver might change it. And PDO is just a simple example for this ...

The key point of this all is that as soon as you mix strong typing - by using type hints - with PHP's weak type system you open a can of worms.

And to be overly clear: I can understand the need for strict type systems and see where such a thing helps. But adding a strong type system, stricter than most other languages (hey, you can't pass an integer where a float is expected!), makes little sense to me. But that's just me.

As in my previous posts in the series of blog posts about features in PHP trunk. Please try the snapshots. Mind that these features might (not) end up in the next release of PHP, feedback is welcome.