Tony Marston's Blog About software development, PHP and OOP

The PHP core developers are lazy, incompetent idiots

Posted on 13th February 2023 by Tony Marston

Amended on 4th March 2023

The cause of my anger
PHP's type system
Why is strict type checking problematic?
The history of changes to the type system
Strict Typing is supposed to be optional
The real inconsistency
The new inconsistency
Breaking Backwards Compatibility (BC) is EVIL!
Response to Sitepoint post
Conclusion
Links
Amendment History
Comments

The cause of my anger

While some people may regard the title of this blog post to be over the top, an insult to the core developers which could have been expressed in a more diplomatic way, I'm afraid that using genteel language would not adequately express what I feel about this particular issue. If the words are true then they should accept them whether they like it or not, or as the saying goes: If the cap fits, wear it. I could have used a more subdued form of expression so as not to upset their delicate sensibilities, such "Their behaviour was sub-optimal", but that would have been so weak and feeble it would have gone unnoticed. Using big-boy words has the effect of grabbing their attention.

The cause of my anger is that I have recently upgraded my PHP version from 8.0 to 8.2 and my code is now disgorging huge volumes of deprecation notices as if it was suffering from a bad case of dysentery. The particular notices in question are:

Passing null to parameter #1 ($string) of type string is deprecated
Passing null to parameter #1 ($num) of type int|float is deprecated

I looked for the source of this decision and found this in the deprecation notices for migrating from 8.0 to 8.1:

Scalar types for built-in functions are nullable by default, this behaviour is deprecated to align with the behaviour of user-defined functions, where scalar types need to be marked as nullable explicitly.

I looked for the source of this horrendous decision and found it in PHP RFC: Deprecate passing null to non-nullable arguments of internal functions:

Internal functions (defined by PHP or PHP extensions) currently silently accept null values for non-nullable arguments in coercive typing mode.

Just because the function signatures in the PHP manual did not indicate that the parameters were nullable does NOT mean that they were always supposed to be non-nullable. At the time the manual was written there was no method of indicating this behaviour. This did not change until the release of version 7.1. However, all these functions behaved as if the parameters were nullable, and this behaviour was documented in:

Converting to string
String conversion is automatically done in the scope of an expression where a string is needed.
null is always converted to an empty string.
Converting to integer
To explicitly convert a value to int, use either the (int) or (integer) casts. However, in most cases the cast is not needed, since a value will be automatically converted if an operator, function or control structure requires an int argument.
null is always converted to zero (0).

This meant that as soon as the type system had been amended in version 7.1 to allow nullable type hints for scalars then the type hints for all internal functions in the manual could have been amended to make their nullability explicit. Yet the core developers took no action.

The RFC also states the following:

This is contrary to the behavior of user-defined functions, which only accept null for nullable arguments. This RFC aims to resolve this inconsistency.

Considering the fact that the arguments of all internal functions HAVE been nullable for the past 20 years, as stated in the manual, the ONLY inconsistency was the fact that when version 7.1 was released the function signatures in the manual were not updated to explicitly state that they were nullable. It was the manual which became inconsistent with the way that the functions had been behaving for the last 20 years, not the other way around.

After the changes in PHP 8.0, this is the only remaining fundamental difference in behavior between user-defined and internal functions.

This is a blatant misrepresentation of the facts. Before type hinting for scalars was introduced in version 7.0 it was possible for all user-defined functions to have nullable arguments, just like the internal functions had always had. It was just a matter of how they were coded. With the release of version 7.1, which added nullable type hints to the type system, it then became possible to make user-defined functions behave exactly the same as internal functions.

Historically, the reason for this discrepancy is that internal functions have supported a concept of scalar types (bool, int, float, string) long before they were introduced for user-defined functions in PHP 7.0, and the existing implementation silently accepted null values. For the new scalar type declarations introduced in PHP 7.0 an explicit choice was made to not accept null values to non-nullable arguments, but changing the existing behavior of internal functions would have been too disruptive at the time.

The fact that the original implementation silently accepted null values was not an accident, it was a deliberate act on the part of PHP's founders. While not accepting null for a non-nullable argument is perfectly valid stance, this did NOT require changing any internal functions as they had never in the previous 20 years behaved as if their arguments had been non-nullable. The documentation did not show any nullable type hints because type hints in the language did not exist until version 7.0. Instead of changing the documentation to become consistent with this long-standing behaviour they changed the functions so that their behaviour matched the documentation - they removed the ability to have nullable arguments. The change made in version 8.1 therefore broke the way in which the language had behaved for the previous 20 years. This fits the description of a Backwards Compatible (BC) break.

I consider that deprecating a feature that has existed in the language since its inception to be a completely insane decision which is going to cause enormous amounts of grief for thousands of developers and millions of websites. According to the W3Techs survey PHP is used on over 77.6% of the world's websites, so that is a HUGE number.

PHP's type system

Since it was first released PHP has always been dynamically typed and not statically typed, as well as weakly typed and not strictly typed. This is described in the PHP manual under Types as follows:

PHP is a dynamically typed language, which means that by default there is no need to specify the type of a variable, as this will be determined at runtime. However, it is possible to statically type some aspect of the language [from version 7.0 onwards] via the use of type declarations.

Types restrict the kind of operations that can be performed on them. However, if an expression/variable is used in an operation which its type does not support, PHP will attempt to type juggle the value into a type that supports the operation.

The manual at Converting to string and Converting to Integer had this to say about dealing with variables containing NULL values:

If an expression expects a string then NULL will be converted into '', an empty string.
If an expression expects an int or a float then NULL will be converted into the value zero.

For user-defined functions if any extra type checking was required it was up to the developer to include the necessary code.

For internal functions the manual contained informal type hints on all the parameters, which meant that variables of a different type would be silently juggled into the expected type. When I use the word informal I mean that it used in the manual for documentation purposes, but is not used in the language itself.

Why was this behaviour built into the language? Simply because it was designed to provide a link between HTML forms and relational databases, and both of these support nullable values.

This means that data coming into a PHP script, whether it be from an HTML form or a database, is not typed as everything is either a string or NULL. The fact that PHP could silently deal with this mixture without programmer intervention was one of the reasons why PHP became so popular. This pragmatic approach allowed programmers to write code to get the job done with the minimum of effort. Thus the following code would work:

$quantity = '2';                // this is a string
$price    = '9.99';             // this is a string
$value    = $quantity * price;  // $result is a number

Notice here that it was not necessary to convert each variable into the correct type before using it in an expression or as an argument in a call to an internal function. This also allowed code such as this:

$price    = 9.99;            // this is a number
$lenth    = strlen($price);  // this will treat the number as a string and return the value 4

Why is strict type checking problematic?

While doing some more research I came across RFC: Strict and weak parameter type checking, written by Lukas Smith and Zeev Suraski in 2009 which states the following:

PHP's type system was designed from the ground up so that scalars auto-convert depending on the context. That feature became an inherent property of the language, and other than a couple of exceptions - the internal type of a scalar value is not exposed to end users. The most important exception is the === operator - however, this operator is used in very specific situations, and obviously only in the context of comparisons. While there are other exceptions (e.g. gettype()) - in the vast majority of scenarios in PHP, scalar types auto-convert to the necessary type depending on the context.

For that reason, developers - even seasoned ones - will feel very comfortable sending the string "123" to a function that semantically expects an integer. If they know how PHP works internally - they rely on the fact the function will auto-convert the type to an integer. If they don't (and many don't) - they don't even think about the fact that their "123" is a string. It's a meaningless implementation detail.

For these reasons - strict type checking is an alien concept to PHP. It goes against PHP's type system by making the implementation detail (zval.type) become much more of a front-stage actor.

In addition, strict type checking puts the burden of validating input on the callers of an API, instead of the API itself. Since typically functions are designed so that they're called numerous times - requiring the user to do necessary conversions on the input before calling the function is counterintuitive and inefficient. It makes much more sense, and it's also much more efficient - to move the conversions to be the responsibility of the called function instead. It's also more likely that the author of the function, the one choosing to use scalar type hints in the first place - would be more knowledgeable about PHP's types than those using his API.

Finally, strict type checking is inconsistent with the way internal (C-based) functions typically behave. For example, strlen(123) returns 3, exactly like strlen('123'). sqrt('9') also return 3, exactly like sqrt(9). Why would userland functions (PHP-based) behave any different?

Proponents of strict type hinting often argue that input coming from end users (forms) should be filtered and sanitized anyway, and that this makes for a great opportunity to do necessary type conversions. While that may be true, it covers a small subset of type checking scenarios. For example, it doesn't cover input coming from 'trusted' sources like a database or files. It also doesn't account for the many developers who are simply unaware of PHP's internal type system, or that presently don't see the need to explicitly do type conversions even if they do sanitize their input. Not to mention those that don't sanitize their input at all...

Note these statements:

Anyone who tries to remove an inherent feature of the language cannot be said to be "improving" it in any way, they are destroying it. Anyone who converts an inherent feature of the language into something which is counterintuitive and inefficient should be required to come up with some serious justification. Note that this should exclude such things as "code purity" and "to be consistent with X".

The last statement which says that input coming from end users should be filtered and sanitized is simply stating a personal preference which has never been either proposed or recommended in the PHP manual. It is quite possible to check that a string value in the $_POST array is consistent with its type in the database WITHOUT actually changing its type. There has never been any rule which says that it should or must be converted, so anyone who says otherwise is overstepping the mark. On the contrary, since its inception the language has been able to use its Type Jugging capabilities to deal automatically with values of different types, which includes NULL. This is a well documented feature that is used by millions of application developers, so its removal would be a huge barrier to sites wanting to upgrade to this version. If they can't upgrade without rewriting their code some may chose to rewrite their code in a different language altogether, one where the developers behave in an adult and professional manner when it comes to maintaining backwards compatibility. Even the Python language has a basic policy for backwards compatibility which states:

incompatibilities should have a large benefit to breakage ratio

The history of changes to the type system

Below is a history of the changes made to the type system since version 4 (the earliest version that I used):

Strict Typing is supposed to be optional

This RFC has the effect of implementing strict typing, which enforces type hinting, on all internal functions without using the declare(strict_types = 1); directive. This to me is wrong. According the manual at Strict typing PHP will, by default, implement "weak" typing in which values of the wrong type will be coerced into the expected scalar type declaration if possible, which means that nulls should not be rejected. This has been the default behaviour since day 1.

This RFC has the effect of overriding the statement included in the earlier PHP RFC: Scalar Type Declarations v5 where it states the following:

Behaviour of weak type checks
A weakly type-checked call to an extension or built-in PHP function has exactly the same behaviour as it did in previous PHP versions.
Behaviour of strict type checks
These strict type checking rules are used for userland scalar type hints, and for extension and built-in PHP functions.
Backward Incompatible Changes
Since the strict type-checking mode is off by default and must be explicitly used, it does not break backwards-compatibility.
Unaffected PHP Functionality
When the strict type-checking mode isn't in use (which is the default), function calls to built-in and extension PHP functions behave identically to previous PHP versions.

This means that both forms of type checking, either "weak" or "strict", are supposed to operate on a user-defined function, extension or internal function in the same way at the same time. This RFC has the effect of overriding those statements and implementing "strict" typing for internal functions even though the option has not been turned on.

NOTE: I have just discovered that internal functions that deal with numeric values now throw an exception if the parameter which they are given is not of the correct type. The message that was generated was:

Uncaught exception from TypeError, message = abs(): Argument #1 ($num) must be of type int|float, string given

This again is the exact opposite of what was proposed. Weak type-checking should continue on all internal functions, just as it has done for the past 20+years, UNLESS strict type-checking has been explicitly turned ON - which I never do.

The function signature in the documentation used to read as follows

number abs ( mixed number )

but with version 8 it was changed to:

abs(int|float $num): int|float
This fatal error has never been mentioned in the backwards incompatible changes for any release. Was this even subject to an RFC, or did some villain sneak it in under the radar hoping that nobody would notice?

The real inconsistency

In the RFC the logic behind the decision was given as:

This is contrary to the behavior of user-defined functions, which only accept null for nullable arguments. This RFC aims to resolve this inconsistency.

There is a glaring mistake in this statement because it is comparing internal functions, which have always had nullable parameters in practice, with user-defined functions which have non-nullable arguments. But what about comparing them with user-defined functions which DON'T have non-nullable arguments? Type hinting for scalars was not available until version 7.0, and the option to make them nullable was added in version 7.1. This meant that it was possible to build user-defined functions which had the same behaviour that internal functions had always had.

It was recognised in PHP RFC: Scalar Type Declarations v5, which was implemented in version 7.0, that type checking would apply equally to userland, extension and built-in PHP functions and be either "weak" for all or "strict" for all. It specifically stated the following:

Behaviour of weak type checks
A weakly type-checked call to an extension or built-in PHP function has exactly the same behaviour as it did in previous PHP versions.

The only "inconsistency" which arose at this point was that the informal type hints used in the manual for the parameters of internal functions then became out of step with the actual behaviour of those functions which allowed the parameters to be nullable. The type hinting system was altered to allow nullable types in version 7.1 following the approval of this RFC.

When there is an inconsistency between the documentation and the language there are two ways in which this can be resolved:

  1. Change the documentation to match the current behaviour (ie: change the parameter hints to be nullable).
  2. Change the code to match the documentation (ie: change the parameters in the code to be non-nullable).

Option #1 could have been completed in December 2016 with the minimum of effort to the documentation team, zero effort to the core developers, and zero pain for all userland developers. Instead they waited until November 2021 to inflict option #2 on the world with zero effort on their part but MAXIMUM pain for all userland developers.

Which of these options would a sane person have chosen? Answers on a postcard to .....

The new inconsistency

Because the core developers chose to fix the wrong consistency all they did was create a totally new inconsistency. The way that internal functions work now is totally inconsistent with the main factor which made the language so popular - the fact that it was dynamically/loosely typed but now is not.

All code written prior to version 8.1 will now sh*t its pants like an incontinent child. This release will not improve the language in any way as instead of adding something new and shiny it takes away something old and much-loved, which is sh*tty. This will slow down the adoption rate for the new version to such an extent that the majority of the world's users simply won't be able to afford to rewrite their code. If they DO choose to rewrite it they may as well move to a different language, preferably one which offers backwards compatibility as a feature and not something which can be discarded on a whim.

Breaking Backwards Compatibility (BC) is EVIL!

Backwards compatibility is a feature, not an inconvenience which can be discarded on a whim. It should ALWAYS be maintained unless there is an overwhelming case for its removal. This would include a security issue but would exclude "to be consistent", especially when it concerns being consistent with a user-defined function created by any random developer working with userland code. User-defined functions are the sole responsibility of the developer who created them and have no impact on anyone except those who use his code. Parameters on these functions can easily be switched from non-nullable to nullable with the addition of a single '?' character in front of the parameter's type, so forcing the core functions to be consistent with just one of these userland options seems to me to be the worst possible choice. As the default behaviour of all core functions has always been to accept nullable parameters then why wasn't it possible to change those parameter definitions in the manual to nullable in order to make them consistent with user-defined functions with nullable parameters?

Proposed changes to standard functions in PHP core should always take into consideration the impact they would have on every developer who uses the PHP language, and breaking backwards compatibility should not be allowed unless there is no other option. In this particular case there was another option which involved nothing more complicated than changing the function definitions in core to include the nullable option on the relevant arguments. That's not exactly rocket science, is it!

I have written similar articles on the subject of BC in the past which you can find at:

  1. Breaking Backwards Compatibility is EVIL
  2. Please do not break our language
  3. BC break in 7.2 caused by undocumented and unauthorised change
  4. Changing fundamental language behaviors
  5. Is PHP too verbose?
  6. RE: Improving PHP's Object Ergonomics

Response to Sitepoint post

I started a thread on sitepoint.com to discuss this article, but a moderator closed it prematurely simply because he didn't like what was being said, which meant that I did not have the opportunity to reply to this comment. I am including it here instead.

the advice you are being given by @m_hutley and others have been spot on.

As far as I am concerned their "advice" is not worth the toilet paper on which it was written. If I were to follow their "advice" I would not be standing on the shoulders of giants, I would be paddling in the poo of pygmies.

PHP has, for several years now, been moving the language away from its more problematic roots

What problematic roots? It was designed from the outset to be dynamically/weakly typed, and programmers like myself have been using it for decades without any problems. If you look at RFC: Strict and weak parameter type checking you will see the following statements:

PHP's type system was designed from the ground up so that scalars auto-convert depending on the context. That feature became an inherent property of the language.

Strict type checking is an alien concept to PHP. It goes against PHP's type system by making the implementation detail (zval.type) become much more of a front-stage actor.

In addition, strict type checking puts the burden of validating input on the callers of an API, instead of the API itself. Since typically functions are designed so that they're called numerous times - requiring the user to do necessary conversions on the input before calling the function is counterintuitive and inefficient. It makes much more sense, and it's also much more efficient - to move the conversions to be the responsibility of the called function instead. It's also more likely that the author of the function, the one choosing to use scalar type hints in the first place - would be more knowledgeable about PHP's types than those using his API.

Finally, strict type checking is inconsistent with the way internal (C-based) functions typically behave. For example, strlen(123) returns 3, exactly like strlen('123'). sqrt('9') also return 3, exactly like sqrt(9). Why would userland functions (PHP-based) behave any different?

So you see, the pioneers of PHP made it weakly typed for very good reasons, which include practicality, efficiency and ease of use. They chose pragmatism over dogmatism.

They are "evolving it".

Evolving means "growing" not "shrinking", it means "adding to" not "subtracting from", it means "becoming more advanced" not "retarded". The only GOOD reason to remove something from the language is if it no longer works, and weak typing DOES NOT fit into this category.

Evolving can certainly mean taking away some features to increase the usability and enhance the language.

How does obliterating PHP's weak typing nature increase its usability? Removing a fundamental feature of the language is decreasing its usability. Evolving does NOT mean removing something that has been in the language since its inception and still works as advertised. The language is being devolved and degraded.

m_hutley came up with the perfect example with the mysql_ functions.

That is a rubbish example. The ability to access a MySQL database was not removed from the language, but when MySQL version 4.1 was released it had additional features which required a new interface, so in July 2004 they released an additional "improved" extension. It was then up to the developer to decide which extension they used. Being a competent professional I had designed my framework from the outset to be based on the 3 Tier Architecture which meant that all DBMS access was performed in a single Data Access Object (DAO). In order to accommodate the switch between the old and new MySQL extensions I created a new class to call the new APIs, and the framework would automatically use the "improved" extension if it was loaded. There were NO code changes required by any of my users. The fact that the old mysql extension is no longer available in PHP 8 does not affect me in the least as I had already dealt with its future demise in 2004.

Every language deprecates and removes features as it introduces and changes others.

Languages being maintained by professional and competent developers do not break backwards compatibility on a whim. They do not remove working features because a group of dogmatists doesn't like them. They listen to their users, they do not ignore them.

you should NEVER be relying on a language to duck type your intentions as a regular rule.

Duck typing was never an accidental feature of the language, it was a fundamental feature that was used by hordes of programmers to good effect over several decades. Relying on a fundamental and well documented feature can never be regarded as poor programming practice.

This leaves the interpreter to "guess" what you want to be done on its context

I have been using PHP for 20 years, and it has never made a wrong guess. I also have a standard routine in my framework which will validate all user input to ensure that each value is compatible with the datatype of its column in the database. This does not require any code to be written by the application developer. Note that all data coming from either the browser or the database is presented as an array of strings, and NULL has always been considered to be a valid value in both.

while this can be leveraged in spots, you are leaving yourself open to bugs

It has been my experience that the number of bugs created by weak typing is inversely proportional to the competence of the individual programmer.

in any programming language, you should know your types and be as explicit as possible.

That is just a personal preference, not a rule that was carved in stone and handed down from the mountain top. PHP, like all other dynamic languages, was not designed to be strictly typed, so if that is not to your liking you shouldn't be using the language.

I am not saying duck typing is essentially bad, but if you are leaving user input or input from a database to determine what happens in an operation, you are playing with serious fire.

I disagree, and so would all the millions of developers who have written successful applications without the crutch of strict typing. I never have to validate data from the database because it could not have been written to the database if it was invalid.

It is half the reason other languages have chosen to be strongly typed to begin with.

If you compare a list of languages by type you will see that 40% are strictly typed whereas 60% are dynamically typed. That refutes your claim that dynamically typed languages are losing their popularity.

Do you know of any dynamically typed language that switched to being statically typed? It just doesn't happen. It's up to each programmer to choose a language that supports his preferred programming style. Only a bad programmer chooses the wrong language and then complains about it. That would be as foolish as visiting a Chinese restaurant and then complaining that they don't serve pizza.

The PHP working group communicates and discusses changes regularly

Only amongst themselves. They never solicit input from the millions of userland developers, the people who actually use the language for a living. They simply don't care what the userland developers think.

we know you are frustrated with having to make a lot of changes for features you think are just wacko or doesn't fit with the spirit of the language.

It does not bother me that new features are added to the language provided that I am not forced to use them. I don't use a feature "because it is there" or "because it is fashionable", I only use those features for which I can find a use. To do otherwise would be foolish.

You will still find out that other languages introduce as many breaking changes regularly.

The good languages regard backwards compatibility as a feature, not an obstacle. If anything is removed at all, it is because it no longer works, or has been replaced with a superior version. It is NEVER removed because of a change in fashion. The benefits of any BC break should always outweigh its costs. If a BC break does not have any benefits for the userland developers then it cannot possibly be justified.

Conclusion

Which of the following statements is correct?

The answer is that they are BOTH correct as it all depends on how the argument is marked in the function definition.

Which of the following statements is correct?

The first statement is correct for all versions of PHP up until version 8.1. This gradually changed over a period of time when type hinting was first introduced as an option for classes and arrays in version 5, for scalars in version 7.0 (but only for a single type), for nullable types in version 7.1, and mixed/union types in version 8.0. This meant that you could describe an argument's type as int|string|null and it would accept any of those types, with a null being interpreted as zero and a string value being cast to a number.

This change constitutes a change in behaviour, and because it breaks scripts that have worked perfectly since the language first appeared it is a breaking change which, as far as I am concerned, cannot be justified on any grounds. Saying that it was done to align them with the behaviour of user-defined functions where scalar types need to be marked as nullable explicitly is completely bogus as any argument can easily be switched between being non-nullable and nullable by adding/removing just five characters from the argument definition (or just one if you use '?'). You could just as easily mark every numeric argument as accepting strings as that would also have maintained the existing behaviour.

You had a simple choice - maintain the existing and long-standing behaviour of the language with zero impact on the legions of application developers out there in userland, or break the language for everyone simply because you couldn't be bothered to do the right thing. Claiming that it would have been too disruptive at the time is a shocking excuse. Too disruptive for whom? One lone core developer for half a day or legions of application developers at numerous hours each? This would not have meant changing the existing behavior of internal functions as that is precisely how those functions have worked for the past 20 years. This is a change in how you think that PHP ought to behave based on your twisted ideas on what constitutes a "proper" OO language.

The core developers do not own PHP, they are merely its custodians. They are supposed to look after the language for the benefit of its customers, the legions of developers like me who use the language to create libraries, frameworks and applications. They are supposed to build on the work created by pioneers such as Rasmus_Lerdorf, Andi Gutmans and Zeev Suraski. These men were giants, but the current group of core developers are nothing but pygmies who are not fit to lick their boots. They are supposed to maintain the language by fixing bugs and adding new features, not by removing the features which made it the most popular language in the world for building dynamic websites.

New features should always be optional and not mandatory otherwise this would also break existing userland code. These breaks cause legions of developers to spend enormous amounts of time in coding around artificially-induced "errors" which did not previously exist, which is the main factor behind the slow adoption rate for new releases. That's why, according to these usage statistics, less than 10% of websites have upgraded to version 8, and 22.5% haven't even upgraded to version 7. That low adoption rate is down to nothing more than the incompetence and intransigence of the core developers.

PHP became popular because of its simplicity, its dynamic and pragmatic nature. Eroding away at those very things which made it popular will make it less popular. Instead of building on PHP's foundations these pygmies are trampling it into the dust with their jackboot approach by insisting that it be changed so that it behaves like a "proper" language which professionals can use. It may become more "pure" in the eyes of a few dogmatists, but what's the point in a language which is only used by purists and shunned by the greater community of application developers who simply want to write code that works with the minimum of effort? Fixing bugs and adding new features is acceptable, but removing long-standing features and thus breaking backwards compatibility is definitely not acceptable.

The reasons given for this enormous BC break were:

  1. To make them consistent with user-defined functions which have non-nullable parameters.
  2. Changing the existing behavior of internal functions would have been too disruptive.

Point #1 is bogus as the inconsistency appeared when version 7.1 was released. Comparing the behaviour with user-defined functions is a red herring as user-defined functions can have parameters which are either nullable or non-nullable while parameters for internal functions have always been nullable.

Point #2 is bogus as they did NOT have to change the behaviour of any existing internal functions as they already accepted nullable parameters, as they had always done since the language was first released over 20 years ago. All they had to do was update the documentation for each function where the hints did not explicitly say that the parameters were nullable. This was no more difficult than prefixing each parameter's type with the '?' character.

When there is an inconsistency between the documentation and the language there are two ways in which this can be resolved:

  1. Change the documentation to match the current behaviour (ie: change the parameter hints to be nullable).
  2. Change the behavior to match the documentation (ie: change the parameters in the code to be non-nullable).

Choice #1 would require a small amount of effort from a single core developer working on a single codebase, would maintain the status quo and would not cause a massive BC break. This would be consistent with the statement made in this RFC which said that it does not break backwards-compatibility.

Choice #2 would require untold amounts of effort from untold numbers of developers working on untold numbers of applications to fix a problem which did not exist until it was created by a bunch of tyrannical elitists. They do not care for the opinions of the millions of userland developers, instead they have this "we know best" attitude and seek to impose their view of code purity on the rest of the world.

It is quite obvious, to me at least, that they chose the wrong option. I say "wrong" because it has caused huge amounts of disruption among the millions of userland developers. If you don't believe me then consider the following search results from Google:

Do you think that those 2.7+ million developers who have suddenly found out that their code, which has worked for decades without any issues, is now broken and needs to be fixed are happy about having to spend enormous amounts of time in fixing that which was broken, not by them by the core developers? Which of these options would be more cost-effective?

  1. 2.7+ million developers spending time fixing code which they didn't break. I personally spent several days working through my large codebase, so imagine 2 days multiplied by 2.7 million!
  2. 1 core developer spending 1 hour updating the manual to correct the type hints for the internal functions to reflect the way they have operated for the past 20+ years.

If you are one of those 2.7+ million developers what your YOUR choice be? Answers on a postcard to .....

I have legitimate reasons for calling the core developers lazy, incompetent idiots:

  1. I call them lazy because they could have resolved this issue with a small amount of effort on their part, but instead they decided to shift the burden onto millions of userland developers. It should be up to the core developers to fix what they broke.
  2. I call them incompetent idiots because:

Because of this I want to see this BC break reverted. It does not add to or improve the language in any way, all it does is remove behaviour which has existed without any problems whatsoever for the last 20 years.

It's about time that changes to the language were put to a proper democratic vote, which involves the community of userland developers. The tyrannical attitude of these elitists who don't care for the opinions of us plebs, who are trampling all over the language with their jackboots, needs to come to an end. A "good enough" language used my millions will always be better than a "perfect" language used by a few purists. If other languages are already deemed to be better than PHP then these saboteurs should switch to one of those languages and leave PHP alone.

To avoid a repetition of this SNAFU I would like the following change made to the RFC process:

The reason that these rules were not originally stated when the RFC process was created was because none of the pioneering developers ever believed that anyone would be stupid enough to break the language. This is what happens when you replace intellectual giants with people of lesser ability.


Links


Amendment History

09 Mar 2023 Added Response to Sitepoint post
04 Mar 2023 Added Why is strict type checking problematic?
02 Mar 2023 Amended Strict Typing is supposed to be optional to include a new complaint.

Comments

This article has been discussed on Reddit where you will see that a large number of people are of the opinion that the pre-8.1 behavior was wrong and simply should not have been allowed in the first place. That is a cock-eyed opinion. Down here in the real world we do not call something wrong unless it causes a problem. If the only "problem" caused by allowing a long-standing feature to continue to exist is to upset the delicate sensibilities of those purists who insist that it should not be allowed, then all I can say is Aw Diddums! These people should stop throwing their toys out of the pram and grow up! Mind you, this could be difficult for pygmies as they have been genetically stunted since birth.

counter