68

I'm currently migrating my website from PHP5 to PHP7, and I've started using the strict typing feature that was added. However this requires me to begin all files with the following line:

<?php declare(strict_types=1);

// All other code here
// ...

So I was wondering, is there any way to enable strict_types globally using something like php.ini or the apache configuration file so I don't have to write this line every time, and if so how could I enable this?

apaderno
  • 28,547
  • 16
  • 75
  • 90
Paradoxis
  • 4,471
  • 7
  • 32
  • 66
  • 3
    No, this is not possible. – u_mulder May 09 '16 at 08:57
  • 5
    You can enable strict_types globally by using `sed`, `awk` or another tool of your choice to replace all ` – NikiC May 09 '16 at 17:29
  • @NikiC I'm pretty sure a simple find-replace in any IDE would do the same, I was just wondering if it was possible to do this at runtime as a standard feature as I couldn't find anything about it – Paradoxis May 09 '16 at 18:29
  • 1
    You could always have a git hook that checks to make sure all PHP files have ` – Cruncher Apr 18 '17 at 10:00
  • The declare_strict_types option in PHP CS Fixer can force strict types in all files. Better than a string replace, if for example you have multiple opening tags. It can be integrated and run automatically in IDEs. – Mark Fisher Apr 15 '19 at 16:44

3 Answers3

82

This is deliberately not possible, because the implementation adopted after an extremely long discussion of scalar type hints was this one: https://wiki.php.net/rfc/scalar_type_hints_v5

It introduces two modes for scalar type parameters, which both guarantee that the function receiving the parameters gets the types that it requires in its signature. However, it provides two modes for how calling code can achieve that:

  • in mode 0, it automatically validates and casts certain scalar types (e.g. int parameter will convert '123' to 123, but error on 'hello')
  • in mode 1, it requires the caller to do that validation and casting before-hand, and rejects any parameter not of the correct type (e.g. both '123' and 'hello' are rejected for an int parameter)

The choice of mode is per-file, and based on the caller of the function, because:

  • the setting needs to affect built-in functions as well as user-defined ones
  • all code that calls functions needs to be checked or updated to work correctly in mode 1, but most old code will run fine in mode 0
  • with a global setting, you could only use libraries which had been tested with both modes, or the same mode you prefer
  • files that don't declare their preferred mode need to continue to work similarly to PHP 5.x to allow existing code to run; that is only possible if the default is mode 0

From the point of view of someone writing a reusable library:

  • regardless of the setting, your functions are guaranteed to receive the parameter types requested
  • if you want to receive errors when you call functions with the wrong types, you can use mode 1 without forcing other applications and libraries to be on the same setting
  • if you want to have the automatic checks and casts of mode 0, you can do that, but still interact with other libraries and applications which run in mode 1
  • old libraries which were written before PHP 7.0 (or which needed to support both when it came out) will continue to work roughly as before, because the default mode 0 is similar to existing behaviour for built-in functions

It's therefore up to you to tell PHP which files have been written to use strict type mode, and which haven't; and the way to do this is using the declare statement.

IMSoP
  • 89,526
  • 13
  • 117
  • 169
  • That wiki entry is an interesting read to say the least. It seems to me that it would be a good thing for packages to start using it throughout and move towards better type checking. – Dave Jun 19 '19 at 13:28
  • It's not impossible to add a php.ini directive for turning strict types on globally. If PHP devs won't do it you can [patch it yourself](https://gist.github.com/sorpigal/700d6aca635578d39c87c4a2ff340d77). Build with the linked patch and set `strict_types=1` in php.ini. – sorpigal Jun 12 '20 at 16:01
  • 1
    @sorpigal I never said it was impossible to implement; I said after a long (and incidentally often heated) debate, it was decided that leaving it in the control of the caller was the best idea. If you're going to patch PHP, you could patch it to halt-and-catch-fire whenever someone used an incorrect type if you wanted, but that wouldn't be the same feature. – IMSoP Jun 12 '20 at 16:39
  • @IMSoP Thank you, nice explanation, but it ensured me there should be such option, although I worry the libraries' compatibility would be the downfall of this ideal. That is a very valid argument indeed (dltdcmmnt2rdcspc) – jave.web Mar 07 '22 at 19:11
  • 1
    @jave.web Maybe it would have been ideal if PHP had worked the `strict_types=1` way 20 years ago, along with some better cast behaviour so that `(int)'hello'` was an error, not `0`. But adding a global setting, either now or back when 7.0 was released, would solve very little, and damage a lot. – IMSoP Mar 07 '22 at 19:17
  • @IMSoP I meant ideal as a noun - that's why I called it ideal (like ideology). Otherwise I agree it supports what I said. (and yes, ideals can have bad consequences) – jave.web Mar 07 '22 at 19:21
  • I get the concerns about supporting older libraries, but they can just make it default to no use strict types so that the people writing stuff that has no such issues aren't impeded by it. – C Miller Jul 08 '22 at 23:47
  • @hanshenrik I've rolled back your edit, because there's nothing special about `array_filter` itself there; rather, the gotcha is that the callback function is called from _a different context_ than you might at first glance assume. Imagine you defined your own function `my_array_filter`, which executes a callback passed to it; the mode that matters is the file _where `my_array_filter` is defined_, not where the callback is defined, or where it's passed to `my_array_filter`. Built-in functions act as though they were *defined* in files with `strict_types=0` mode in effect. – IMSoP Aug 26 '23 at 13:40
17

PHPStorm has an inspection to help you with this:

enter image description here

jawira
  • 3,668
  • 2
  • 17
  • 27
7

Essentially no.

Because if you only require libraries that used strict mode you will cause an unnecessary separation of packages. Also consider the strict/weak types option is just an extra in PHP.

danilonet
  • 1,757
  • 16
  • 33