eZ Community » Blogs » Core Development team » PHP 7.0: Why Scalar type hints with...

PHP 7.0: Why Scalar type hints with strict mode, and stricter weak mode

Thursday 12 March 2015 7:00:58 pm

  • Currently 3 out of 5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Upcoming PHP 7.0 is starting to shape up as a very exciting release in similar way as 5.0 and 5.3 was. Some of the biggest language improvements center around type handling. The type casting rules are being cleaned up, return types was recently accepted, nullable (argument) types are in draft, but scalar type hints for function/method arguments are once again causing  major  debates within the PHP (internals) community, this post is thus mainly targeted at PHP internals and others interested in what is going on currently around PHP.

PHP v7 "logo"

On the positive side, and unlike 3 years ago, it seems all parts of the debate are now aware of how much (increasing) demand there is for this feature. However there seems to still be some unclarity between what is best for PHP, who are the target users of this feature in the first place, and how to avoid hard to detect edge case by this new feature if the current v0.5 proposal is accepted. So lets try to clarify a few of those.

 

Background and original use case

eZ Systems/Ecosystem have for 15 years been a rather extensive user of PHP and kept on pushing its limits, which is why we have worked closely with several internals over the years.

However today we are far from alone doing this, while PHP might have started out as a “view language” on top of C, it has over the last 20 years gradually adopted the best of both weakly typed,  interpreted, strongly typed, compiled languages, and so on. Allowing it to truly become a “language for everyone and for everything”.

This, with the advent of PHP 5.3 and Composer, has resulted in a plethora of increasingly high quality libraries and frameworks, from prominent communities like Symfony, FriendsOfSymfony, Doctrine, FriendsOfPHP, ZF, and many many others. And what is common for these users; framework & library developers, is that we would like to make better software, and we would like to have access to the tools that allow us to do so. And ideally without having to migrate to Hack, a language extending PHP and available on HHVM side by side the PHP language.

 

The “original” use case

So after clarifying that target users of this feature is framework & library developers, how this is actually provided is possible in several ways. One way could be that PHP move towards an object model ala Javascript, this would as a bonus allow us to cleanup function naming. But lets not go down that road right now, lets rather focus on current  proposals which allows us to hint against PHP’s already existing scalar types.

 

Needed Scalar Type Hint features

The first two points below reflects what is already the case in current v0.5 proposal, and is explained in more depth in recent blog post by Pascal MARTIN.

 

Why weak mode by default is a must (for the PHP ecosystem)

Being a library developer, and having being exposed to other languages it is easy to come to the conclusion that scalar type hinting can only work if it is purely strict, as in only accepting the exact type specified. However as cleverly laid out in in scalar type hint rfc earlier this year, large portions of PHP’s user base are not used to having to care about type in PHP. It takes care about this for you, allowing you to very efficiently work with it.

So weak type handling is basically a feature for the consumers of interfaces/methods/API’s, it allows the use of a interface to not care so much about type. While the implementation, written by a library developer, gets the exact type it expects, and nothing else. This should thus technically please both sides of the interface(/fence).

 

Why opt in strict mode is a must (for the target users)

We might just stop here and say we are ok with just having weak types, being it interface wise pleases both sides. But there is one important part of the use case missing; as a framework/library developer we want to have as much paranoia checks as possible in our code to detect possible bugs long before they reach our users, and having this natively saves us a lot of time, effort, code, and potentially bugs in that code. Thus we would like to make sure a variable stays within the same type while passed along our maybe several hundred thousand lines of code. If it changes type we would like to be in control over why, and be made aware about it as early as possible.

This is also why strict mode should be used only for those who have a need for this, it puts more effort on the developer in exchange for being in full control.

 

Why weak mode & closures in strict mode should be improved

One of the most recent discussions over the current v0.5 proposal about to being accepted, is on how it behaves in edge cases, cases which can cause severe issues for applications.

Silent data loss on casting in weak mode

Considering string to int casting for instance, there is a risk for silent data loss or change of meaning of a variable in weak mode which can cause real issues in applications. And while these can make sense on explicit cast, type hinting should not allow these situations:

php> function varDumpInt(int $input){ var_dump($input); }
php> varDumpInt("3 dogs");
int(3)
 
php> varDumpInt("foo");
int(0)

There is work done on making this stricter, most of it can be found in a (unfortunately) competing proposal by Zeev, however the proposal removes strict mode completely as well.

Undetectable possibility for fatal error when combining closures and strict mode

Closures in combination with strict mode can lead to fatal errors in a running application that is not possible to detect up-front by the framework/library author.

> user_code_weak.php
$fn = function(int $input){ /* do something */ };
(new Foo())->bar($fn);
 
 
> library_code_strict.php
declare(strict_types=1);
 
class Foo
{
    public function bar(callable $fn) {
        $someString = $this->get('status');
        return $fn($someString);// catchable fatal error
    }
}

Since closures are a weak contract of what we will get, errors will not be detected if author of library/api expects callbacks to accept mixed type or string. 

So this combination should most likely be disallowed/tweaked in for instance favor of pushing framework/library developers to use interfaces when injecting callbacks into libraries that use strict mode.

Summary

The proposal (hopefully) being passed soon has most of the basics correct, it should be supported in the authors opinion. However some mandatory follow up RFCs to avoid WTFs are needed before PHP 7.0.0 release. Including but probably not limited to: stricter weak mode casting which does not allow data loss or change of meaning of data, and avoiding/disallowing closures combined with strict mode to take down an application.

So if you have PHP karma and can vote make sure you get over there and vote on the RFC: https://wiki.php.net/rfc/scalar_type_hints_v5.
If it is once again just barely not accepted, then someone probably need to bite the bullet and create a RFC that covers all the issues upfront, after all that is what keeps some of the voters to keep voting it down.

Update: Proposal was accepted on March 16th with what is maybe the largest voting round in PHP's history so far.

Either way we (at eZ) can't wait for getting our hands dirty with PHP 7.0, giving us much better performance and possibility to write better software. Including using scalar and return type hints in some form, and if we are lucky maybe also named arguments..

Printable

Printer Friendly version of the full article on one page with plain styles

Author(s)

Proudly Developed with from