I'd like to discuss the addition of the new directive `strict_operators`, which
can be used to disable type juggling when using operators.
---
MOTIVATION
A substantial part of the PHP dev community, including myself, have a strong
dislike of type juggling. It's a common source of issues, while the benefits
over explicit type casting are minimal.
The loose comparison equal (`==`) operator and not equal (`!=`) are a well
known causes of security issues. While to use of these two operators are
discouraged, the issues aren't limited to them but also present in all other
comparison operators as well as arithmetic operators.
Type juggling can be a source of frustration, as it may lead to unexpected
results. An example;
Universal rules of logic state that if `a > b` and `b > c` then `a > c`
<?php
$a = '42';
$b = 10;
$c = '9 dwarfs';
var_export($a > $b); // true
var_export($b > $c); // true
var_export($a > $c); // false ??
---
PROPOSAL
The `strict_operators` directive would work similar to `strict_types`. If
`strict_operators=1` is declared, operators will throw a `TypeError` when an
operator is used with incompatible types.
<?php
declare(strict_operators=1);
$b = 10;
$c = '9 dwarfs';
var_export($b > $c); // TypeError "Type mismatch for greater than ('>')
operator with integer and string"
Including the equals operator;
<?php
declare(strict_operators=1);
$q = 42;
$r = '42';
$s = '42 dwarfs';
var_export($q == $r); // TypeError "Type mismatch for equals ('==') operator
with integer and string"
var_export($q == $s); // TypeError "Type mismatch for equals ('==') operator
with integer and string"
var_export($r == $s); // false
var_export($q === $r); // false
var_export($q == (int)$r); // true
You'd still use `===` to compare values of different types.
The rule also applies to arithmetic operators;
<?php
declare(strict_operators=1);
$b = 10;
$c = '9 dwarfs';
var_export($b + $c); // TypeError "Type mismatch for addition ('+') operator
with integer and string"
var_export($b + (int)$c); // 19
Using operator on a type that doesn't support it, would also throw a
`TypeError`, rather than trigger a notice.
<?php
declare(strict_operators=1);
$s = "foo";
$arr = [];
$b = $s . $arr; // TypeError "Unsupported type for concatenation ('.')
operator, unexpected array"
Last, it would disable type conversion for numeric strings.
<?php
declare(strict_operators=1);
$a = "2.7e1";
$b = "27";
var_dump($a == $b); // false
var_dump((int)$a == (int)$b); // true
---
SCOPE
The directive should only apply to operators and not have other side effects.
For instance; Type casting can still cause similar issues to type juggling,
especially when casting a string to an integer. In other languages like Python,
casting "42 dwarfs" to an int throws a `ValueError`. However, this and similar
issues are outside the scope of this proposal.
---
I believe the directive `strict_operators` fits in the direction PHP is going
with better support for typing, while not affecting backwards compatibility.
Regards,
Arnold Daniels
[Arnold Daniels - Contact Using
Spike](https://www.spikenow.com/?ref=spike-organic-signature&_ts=prm5vi)