Some concerns about where PHP is heading

Anton Levitsky
6 min readMay 5, 2021
Photo by Ben on Unsplash

Before I begin, I would like to briefly introduce myself and explain why I think I am entitled to make this statement.

  • I have been programming professionally in PHP since 2014 and continue to do so on a daily basis.
  • I have used PHP for various large-scale applications in different industries.
  • I have always been an advocate of PHP and have loved all major versions from 5.x onwards.

And yet, I don’t like what PHP has become.

Almost every RFC that has been passed since PHP 8 causes me confusion. And I am ready to explain and justify my position.

Fundamental language concepts are changing

How do you usually start learning a new language? With values, expressions, variables and functions. Learning PHP is also the natural order.

During mentoring of junior engineers, when we start going through functions, I draw special attention to the fact that in PHP the context of functions is closed, “sealed”. This is very simple and completely logical — you just need to clearly remember what variables the function sees: its arguments and its internal variables.

As we get to the basics of OOP and learn the concept of “method”, we go back to the concept of a function and add another item to the context: “$this” for dynamic methods. Does anything else change? No. The functions are still closed, their context ceases to exist after the call, nothing flows into the function from outside, and nothing flows out of it.

We come to anonymous functions — and here, too, the rules of the game do not change. Arguments? Yes. Internal variables? Yes.

Next we add the concept of “closure”. Even with this, everything is logical, a separate keyword, a closing list of variables from the creation context, the basic principles are not violated. The functions are still “sealed”. Nothing from the outside enters, nothing leaks out.

Do you know what happens next?

Next we have arrow functions. And that breaks everything.

I am forced to explain that arrow functions violate fundamental principles because they lock up the ENTIRE content at the moment of their creation.

But what about the principle of “tightness”? It was neglected for the sake of simplification of writing, having saved 6 characters — now we have “fn” instead of “function”.

Bad. Inconsistent

Do you think this is the only example? You would hope so.

Ask any beginner a question — what character do names start with in PHP? That’s right, with the “$”.

  • variable names
  • object property names
  • class property names
  • argument names
  • even “variable variables” are also “$”!

Is it logical? Yes. Consistent? Yes. You just need to remember about the constants that don’t need $.

What do we have now? Named arguments: wiki.php.net/rfc/named_params

array_fill(value: 50, num: 100, start_index: 0);

Where is the “dollar”? Disappeared.

This is a problem.

Now you have to remember to write “dollar” in the signature of the function, but not when you call it. And this is a very serious problem that violates the integrity of the language. This is bad and inconsistent.

And why? Just because someone wanted to port syntax sugar from Python to PHP without thinking. Anyway, Python at least uses the same “=” symbol to connect name and value, both in the assignment and named arguments, and now we will have two, the usual “=” and “:” in the new construction.

Almost every RFC discussed for PHP 8 carries the same problem — a violation of the language’s previously established system. And this is bad. It bothers those who have been writing in PHP for a long time and those who are just starting to learn it.

Lets have a look at wiki.php.net/rfc/match_expression_v2

echo match (1) {
0 => 'Foo',
1 => 'Bar',
2 => 'Baz',
};

These are new match expressions. Can you explain why they use the “=>” symbol and not the usual switch case “:”? I can’t either.

This is again a violation of an already established system. The “=>” symbol has always (before the damn arrow functions) denoted the separator of a key-value pair. Now it also denotes the separator of the argument list and return value in the “arrow”, and the selector character in the match statement.

This is bad. This is very bad. This is highly inconsistent.

Natural language unreadability

Show this text to a native English speaker

SELECT * 
FROM users
WHERE age>=18 AND name LIKE 'J%'

and if his IQ is above 60, he will easily explain what this text is about and what is done when implementing this text as a program.

Show a genius unfamiliar with JS this text

const f = () => 42;

and he will understand nothing. Constant? f are these parentheses? Are the parentheses going to a number? What is this?

I was always glad that PHP is far from sacrificing code readability for the sake of brevity. I was glad that it was far from JS, where the principle of code readability has been abandoned in favour of “write fewer characters, no one will read this code anyway.”

Now I realised that PHP 8 will break the principle of natural code readability. And apparently irrevocably.

Just look at these examples (wiki.php.net/rfc/constructor_promotion) :

class Point {
public function __construct(
public float $x = 0.0,
public float $y = 0.0,
public float $z = 0.0,
) {}
}

Now, instead of the constructor arguments, we immediately declare properties and set their values from the arguments.

Guess what comes after the “=” characters? The initial property values? Or the default values of the constructor arguments? It’s impossible to guess. Find out by reading the code — too. This is bad. Another place to memorise

(wiki.php.net/rfc/property_write_visibility)

class User {
public:private int $id;
public:protected string $name;
}

Public-private property? Seriously? How is it to be understood from this code that it is a readable and a writable property?

(wiki.php.net/rfc/conditional_break_continue_return)

function divide($dividend, $divisor = null) {
return if ($divisor === null || $divisor === 0): 0;
return $dividend / $divisor;
}

Seriously, does anyone need this? Has anyone used PHP for years and suffered from not being able to use “return … if” instead of “if … return”? Do we really need a new master Yoda syntax for the mundane if and return?

Too many ways to do the same thing

PHP has always violated the famous principle “There must be one and only one way …”. But it has done it intelligently, gradually and sensibly.

Now that principle has been trampled on and destroyed. Every RFC we get says, “Let’s add another way to write “if” because I’ve seen this in Perl / Python / Ruby!” — and justifications other than “I’ve seen it” are generally not given.

We had three ways of doing the following:

if ($y == 0)
return 0;
if ($y == 0) {
return 0;
}
if ($y == 0):
return 0;
endif;

Not very good, you need to explain: why there are three of them, why you shouldn’t write code without operator brackets, and why you need an alternative syntax.

But this is not enough! Wait a little more and you will see:

// revolutionary Yoda-If
return if ($y == 0): 0;

This is how the functions were called:

foo(bar($baz));

You will soon see this:

$baz |> 'bar' |> 'foo'

brilliant, isn’t it? It is immediately clear that this is a function call!

Conclusion

PHP is evolving. This is an important process that affects a huge number of people and affects the entire programming community.

However, the feeling begins to emerge that development is going somewhere wrong. I fear that the changes being adopted will lead to shorter and less readable code, providing more and more ways to do the same thing in different ways, and taking more and more time to learn all these methods.

I don’t want to see a new Perl in place of PHP in a year. And you?

--

--