I’m posting this here before I actually put this up on the PHP RFC forum, to get feedback on it and whether or not it should even be pursued, bothering the devs of PHP. Also, a co-sponsor or two wouldn’t hurt.
This is a draft
PHP RFC: Strict and Tolerant Variables
Introduction
The vast majority of PHP program bugs and security exploits are due to the language’s loose data typing. While such is a strength for the language in terms of ease of use and especially helping novice programmers along by removing yet another thing to worry about and learn, it can create headaches, especially when PHP needs to interface with other programs that do not support loose data types, especially databases.
Proposal
Allow programmers to explicitly set the data type in one of two fashions: tolerant or strict. The only difference between them is how they behave when values of the wrong datatype are assigned to them. Tolerant variables silently cast any incoming data to their own data type. Strict variables throw a catchable fatal error when an attempt is made to assign a variable of the wrong type to them. Both types must be explicitly declared - for backwards compatibility PHP must assume any variable declared on the fly is a scalar.
Here is the syntax of declaring these variables.
/*
* Tolerant variable creation looks like casting and allows many of the same
* casts: int, integer, bool, boolean, float, double, real, string, array,
* object
*/
var (int) $a;
var (float) $a = 3.14;
/*
* Strict variables use brackets as well.
*/
var ([int]) $c = 9;
var ([bool]) $toggle = false;
Syntax within array and class declarations is similar
$b = [
([int]) 6,
(bool) true,
([string]) hello
];
class A {
public (int) $z = 9;
protected ([string]) $y = "up";
}
In addition to the type casts, specific objects can be required. To satisfy the requirement the incoming value must either be the class specified, inherit from it, or implement it.
var ([PDO]) $db;
Strict and tolerant variables that haven’t been given a value yet are null.
These variables affect type juggling in the following ways. First when compared to a scalar, the scalar must change type to match them. This makes comparison operations somewhat more predictable. When compared to each other their datatypes must match or the condition is false. Hence comparing these variables is always a strict comparison.
var ([int]) $a = 3;
var ([int]) $b = 6;
$c = '6';
($b == $c); // true - $c is forced to convert to integer.
($b === $c); // false - scalars cannot change datatypes during strict comparison.
($a < $b); // true - further this is a strict lesser than comparison, something PHP cannot currently do.
Function arguments can be made strict or tolerant as well on a per argument basis…
function( (int) $a, ([float]) $b) { ... }
And the return can be strict or tolerant…
public function myMethod( ([int]) $a, ([int]) $b)([int]) { ... }
Interfaces can be made useful this way by forcing their implementers to return a certain type!
interface myInterface {
protected function foo ( ([int]) $a, ([int]) $b )([bool]);
}
Cause right now the usefulness of PHP interfaces is somewhat dubious precisely because of this lack.
Backward Incompatible Changes
None I think. Even if someone foolishly named a class “string” the \ operator can be used to allow casting of variables to that object, as distinct from the string type.
Proposed PHP Version(s)
As far reaching as this would be a major version change is the only one suitable, so PHP 7.
Ok, that’s it I think. I’m not trying to make PHP something it is not - this is an “opt in” strong data typing system, so those who prefer loose data typing can continue to use it.
One thing this opens the door to that isn’t included in this proposal is overloading functions - functions who’s names are the same but are distinguished by their data types. Given that scalars will still be around and likely the most common variable type, I think including that functionality is just asking for trouble.
Thoughts and comments welcome.