Behavior of Weak Type Checking and Type Conversion

Behavior of Strict Type Checking

A bit of History about Type Hinting

Personal Opinion

Coherence to Maintain Old Code

Conclusion

What is Scalar Type Hinting?

Scalar type hinting consists of declaring the types of function parameters and return values that can be of the types int, float, string and bool.

This allows the PHP runtime engine to check if the types of values passed to parameter functions and return values are of the expected types in order to detect eventual programming mistakes.

Type hinting for objects, arrays and callables was already allowed in past PHP versions. This proposal extends the type hinting support for types of values known as scalar because they contain only one primitive value, as opposed to non-scalar types which are those that may contain complex values like objects and arrays.

The Scalar Type Checking Proposals

This proposal was approved on March 16 with 108 votes and 48 votes against. It was one of the highest vote counts, if not the highest vote count so far. This reflects the interest of this matter for the PHP community that wants PHP to evolve and become a better language.

This proposal by Anthony Ferrara derived from another proposal by Andrea Faulds submitted on December 2014.

Other proposals for the similar purposes were already submitted and debated intensively in the past. Here is a list of some of those other proposals:

Explicit Declaration of Scalar Types: int, float, string and bool

This new possibility will allow PHP 7 function declarations to look like this:

function increment(int $a): int {...}

This new form of function declaration can coexist with the previous form that did not allow scalar type hinting. Lets
see how.

You can add the statement declare(strict_types=1); in the source file on which you intend to allow scalar
type hinting. Note that this declaration has to be on the first line of the PHP file and can not be declared elsewhere in the same file.

Another aspect to note is whether or not the function being called was declared in a file that
uses strict or weak type checking is irrelevant. The type checking mode depends on the file where the function is
called. That makes sense, right?

In other words, I expect that all the files in a given project will use either weak or strict mode. The only problem will be
with the third-party libraries, as I comment ahead.

Examples of Declarations and Usage

Once we have declared at the beginning of a PHP file to use strict_types=1, we can explicitly declare the types of scalar arguments and return of functions inside this file, so they can be strictly checked.

This reminds me the "use strict"; declaration at the beginning of JavaScript files. As a matter of
fact some people suggested a similar option for strict declaration.

At runtime, when the PHP engine tries to return a value, it will check if it matches the declared type and
will throw a fatal error if does not match.

Fatal error: Argument 1 passed to increment() must be of the type integer, string given

With this new feature we can declare scalar types: int, float, string and bool. Until PHP 5.x we could only
"pseudo-declare" these types using PHPdoc or comments, but those are declarations that do not have any implication at runtime.

With this new form declaration, we can write more robust applications by detecting early programming mistakes caused by passing values of the wrong types to and from functions.

Notice: The aliases of integer for int and
boolean for bool are not admitted.

Automatic promotion of types may also happen. For instance, int types can
be promoted to float type parameters automatically:

function foo(float $a): float {...}foot(10); // works fine

Declaring the Return Type

Using a Delphi-like flavor syntax, we can declare the return types adding a colon
followed by the expected type between the last parenthesis and the first bracket in the function declaration.

For functions that do not return any value, nothing should be added in the return type declaration section.

Behavior of Weak Type Checking and Type Conversion

The weak type checking mode can be used with the statement declare(strict_types=0); or the absence of the strict types
declaration. There are a few of points to take into account:

Weak type checked calls to an extension or built-in PHP function have the same behaviour as in previous PHP
versions

The weak type checking rules for new scalar type declarations are mostly the same as those of extension or
built-in PHP functions.

NULL is a special case in order to be consistent with the current type declarations for classes,
callables and arrays. NULL is not accepted by default, unless it is a parameter and is explictly given a default
value of NULL, for instance: function sample(int $a = NULL);

The following table summarizes the implicit scalar type conversion in weak mode. In any case NULL, arrays and
resources are never accepted for scalar type declarations.

2) Non-numeric strings not accepted. Numeric strings with trailing characters are accepted, but produce a notice.

3) Only if it has a __toString method.

Behavior of Strict Type Checking

The strict type check mode corresponds with the use of
declare(strict_types=1)
at the beginning of the PHP file.

A strictly type-checked call to an extension or built-in PHP function will produce catchable error rather than E_WARNING on failure, and it follows strict type
checking rules for scalar typed parameters, rather than the traditional weak type checking rules.

The strict type checking rules are quite straightforward: when the type of the value matches the one specified in the
type declaration, it is accepted, otherwise it is not.

These strict type checking rules are used for "userland" scalar type declarations, and for extension functions and built-in PHP
functions.

Note: The only exception is that scalar type conversion is allowed for int to float. This
means that parameters that declare float can also accept int.

A bit of History about Type Hinting

Extending this support to scalar types (int, float, bool and string) has been debated many times over the last
years, each time with a bit more support, and finally, last March 16 type hinting for scalar types was approved.

A portion of the community wants strict only types. So that if you
declare function foo(int $abc) and pass in a non-integer, it will raise an error.

There are a ton of advantages to this approach. You get type safety. Which
means that you can finally statically analyze code! You can detect bugs where you accidentally take a string
from one function and pass it as an integer to another.

That may not seem like a big deal to you at first. The reason is that while
it may be appropriate in some cases, in many it isn't. So computers can't reason about that code ahead of
time (statically) and therefore can't be sure that the operation will work.

As I mentioned at the beginning of this post, this subject has been debated for a long time in several occasions. I am really not sure why this time it has finally been approved because many people voted with explaining their reasons. I suspect that the reasons can be:

The RFC was presented in a very simple way.

The options were reduced to the minimum.

The opportunity of RFC in time was perfect because there were a lot of similar
RFC proposals recently, sooner or later one would be approved a scalar type hinting RFC.

Respect for previous behavior in order to maintain the backwards compatibility.

Having it disabled by default will not hurt the performance of code that does not use type checking.

Personal Opinion

Personally I cannot wait for this new improvement. I want to forget the past years that I had to use my intuition to figure what types of arguments a function expects or what can I expect as a return value.

Every day I write hundred of lines of PHP code and try to apply the best practices that I know: PSR, naming
conventions, programming principles. Years ago I embraced Symfony as my professional development framework. Quickly I felt fine using it because it allows me to control things that legacy code does not.

For me, a developer that uses PHP on a daily basis and sees Java as a reference for OOP languages, this is great progress for PHP.

Coherence to Maintain Old Code

Of course, weak mode can be used by "legacy" or skeptical developers. The default behavior of PHP when this
feature be implemented will be the weak mode, ensuring that the old code works fine.

Authors of code and
libraries will decide if they will adapt their code or not, and the users of these libraries
can decide if they use or not the new mode.

Remember that the new behavior of strict mode is applied in the PHP where the function is invoked.

Conclusion

Good job for the developers that voted in this proposal, specially to Andrea Faulds and Anthony Ferrara that created a proposal that was finally accepted by the majority of the voters.

What do you think of this proposal? Do you agree with it or not? Do you think it will contribute to develop better PHP code? Post a comment here to let us know your opinion.