My favourite PHP product at the moment is BookStack (https://www.bookstackapp.com/), a really good wiki. I run an instance for my family and it's great.
But there are loads of things. And I notice that many of the sites I like using...are built on well maintained PHP stacks.
I think the danger with PHP is more its ability to easily cause *very bad things*.
This would partially be poor training (my University literally taught PHP with SQL-injectable examples), and I think the language itself making it very easy, such that less-experienced developers using it - most of them, early on - don't realise what's wrong until it's gone wrong.
With PHP being such an early tool online, and the above properties existing, it earned a reputation for being insecure and bad.
The new array_first() and array_last() functions are nice, everything else is either reimplantation of existing features or "features"which will make maintainability more difficult. The pipe operator is one such example. I don't need it - these nested methods are not really an issue in any codebase I've seen. The new syntax only works for unary functions, so higher arity functions must be wrapped in an arrow function. It's a mess and more bug prone than just nesting the functions.
Or as Bjarne Stroustrup put it: There's two types of languages: The ones people complain about and the ones noone uses
For the longest time the language had been developed with this mentality that it's okay to continue running if something broke, that it's better to print out something than to do nothing and bail out.
Which means that for things to run reliably, you have to write very defensive code that checks everything you can think of. Which is probably a good idea with any language, but I find that old PHP requires much more of this.
Thankfully, they've been changing that over the past decade while still maintaining decent compatibility with old code. I just recently finished porting a pretty large project (~2 mil SLoC) from the ten year old 5.6 to the currently latest 8.4, and it's been pretty painless. The only things that broke were those that were never actually properly implemented and worked by pure chance.
I think these days you could change "You can write Fortran in any language" to "You can structure your code like Spring in any language"…
Still, even if it was "just" the web, why wouldn't it evolve? It's a great language, with a big user base, and there's always room for improvements and to increase the developer experience
$output = $input
|> trim(...)
|> (fn (string $string) => str_replace(' ', '-', $string))
|> (fn (string $string) => str_replace(['.', '/', '…'], '', $string))
|> strtolower(...);
... I think why not just something like the following? $output = $input
|> trim($)
|> str_replace(' ', '-', $)
|> str_replace(['.', '/', '…'], '', $)
|> strtolower($);As for the partial function application, there is already an RFC to add that, but it's not decided on as of now. [2]
1: https://www.php.net/manual/en/functions.first_class_callable...
During that same period, there were a lot of mediocre tutorials and documentation online, including on the PHP website itself which allowed people in comments to post code examples, but as far as I know there wasn't a lot of moderation on those.
And finally, a lot of people ended up writing their own frameworks and the like, because they could. But also because there weren't any or not many good and widely adopted frameworks out there, that came later with first Zend Framework and then Laravel, the latter being the de-facto standard nowadays.
I suspect this affects many developers who cut their teeth on PHP but haven't kept up. The language has become a different beast, which is a strength for the community but a barrier to re-entry.
The only issues I have. is that this is a 'double edged sword' in that PHP has become far more complex since the launch of PHP 5 and so it isn't as easy to understand from scratch as it used to be
Its still so annoying that you have to use mb_real_uppercase($name) for unicode. The other gripe is that the stdlib is SO messy. With PHP 5.3 they had a once in a lifetime opportunity to cleanup the stdlib and introduce a new namespaced API for builtins, and optionally introduce a uniform function call syntax:
"foo"->strtoupper();
Whenever doing PHP the time for concurrency will come sooner or later. Having no way of doing ANY concurrency is a letdown. The Fiber API does nothing on its own, and you are forced to use some third party runtime, that is usually a non-starter for legacy projects.PHP has come a long way from the PHP 4.0 era, but is still lacking in multiple areas, and i dont see it being a pick for greenfield projects in 2025.
String a = new String();
String b = new String();
a = "test";
b = a + "";
if (a == "test")
{
// true
}
if (b == "test")
{
// false
}
if (a == b)
{
// false
}
Just like PHP, you have to read the docs to use it properly.PHP has an operator for something you should never do in a sane codebase.
You know that python wants good good to look good?
PHP was written in a way that makes bad code look good. And if we want Software Engineering to be a serious field that evolves, we have to be able to be honest with ourselves. It is a bad tool. Good programmers can even write good programs with bad tools. Doesn't mean you shouldn't avoid bad tools given the option.
There probably is a "PHP the good parts". But Javascript actually had a pretty nice core, and an utility of being in all web browsers that no other language could replicate. What niche does PHP have where it brings more value there other nicer languages can't be used instead?
It's coming - but to get PHP RFCs to pass they have to be salami-sliced, otherwise they're voted down.
That version 1-latest is understandingly highly different, but these are all decades old languages, which barely changed for some time, but are now all introducing new syntax.
Which I think makes sense, but it's obviously going to leave 9-5 devs behind that don't particularly care for coding and want to invest as little time as possible into their language knowledge.
No, I'm not bitter.
As for concurrency/async, it's possible to do requests in parallel with curl_multi_*. Other async/prallel things are also possible, but tend to be more complicated compared to JS or other languages with promise and async support.
Note though that @ was already neutered in some earlier recent PHP releases.
(no, I don't want my IDE to babysit me, and ideally I don't want to use IDE at all)
If you pull out examples of the earliest C, sure, it looks weird. But that C was already obsolete in 1989. Since then, it’s had a minor iteration (e.g. five-eight additions/modifications) every decade-ish (99, 11, 17, 23). Has it changed? Sure. Can it be compared to the iteration and speed of things like C#, Java, C++, etc? No way.
TLDR: The PHP compiler isn't really suited for the job, it would introduce a lot of complexity to an already complex codebase and the memory/performance hit would be substantial.
Adding generics to PHP would make CS fundamentalists somewhat happy, but do nothing to change the fundamental design of PHP nor offer any of the traditional benefits that generics offer to strongly-typed and compiled languages. And would be a massive headache to implement, while bulking an already heavy VM implementation.
Although there is a proposal for adding "methods" but I don't remember the link.
I'm not a blind PHP hater, but it seems like PHP community members sometimes celebrate new PHP features when their equivalents have been there for many years in other programming languages. https://waspdev.com/articles/2025-06-12/my-honest-opinion-ab...
One common use case for the @ operator, is when "destructuring" array members into variables. In some cases, you can't know if the member will be available, but it's not important if it's missing. In that case, you can silence the warning.
$array = ['apple', 'pear']; @list($mainFruit, $secondaryFruit, $tertiaryFruit);
Since I suppress the warning that would occur due to the third member not being present, the program will continue executing instead of halting.
AzuraCast because I like learning by looking at code and hosting my own radio/music
People pointing fingers to "outdated" languages for not having some of the most trendy constructs.
The pipe operator is definitely one of the feature that create more ways to do the same thing while providing unclear benefit.
Never in my life I was in a situation like "with the pipe operator this I would have saved me hours of debugging/reading/creating code".
Imagine I want to AfD a custom string function for a feature which uPpErCaSeS every second letter as I need that for some purpose: I can't do in OOP style.
In OOP I could extend the string class, but most other parts of the code won't magically use my string type now.
Thus I have to create a free standing function for this (which probably also is better as I don't need internal state of thee object, thus livingnoutisde is good for encapsulation)
And thus my string function works different from other string functions.
my_casing($string->trim())->substr(3);
(The example of course is non sensical and could be reordered, but we argue syntax)Having them all be simple functions makes it equal.
Of course there are alternative approaches. C++ argues for years about "uniform call syntax" which would always allow "object style" function calls, which could also find non-memwbr functions where the first argument is of compatible type, but such a thing requires stricter (or even static) typing, this won't work in PHP.
Such a change makes it a completely different language with no compatibility. Thus all previous code is lost, no easy migration paths (especially for libraries which would like to support both during transition)
What else to say, good luck.
You didn't get the anecdote, that's probably because you haven't worked with PHP (long enough).
I will give hint: inconsistency.
Exactly. The type system was never built for anything even slightly more complex. Its basically annotations for primitive types and classes. PHP has always had an weak type system, so adding generics will most likely never happen.
> Adding generics to PHP would make CS fundamentalists somewhat happy
PHP has really only one collection datatype (the infamous array), so having generics would be tremendously useful, as an example you cant return an typed array from a function, witch is just really bad.
For an counter example, Python managed to do this, while also being a dynamic language, although having a stronger typing than PHP.
Another wiki that uses php is Wikipedia.
People like to shit on php but it powers some of the largest sites in the world.
At the end of the day, programming language doesn't matter much. You can be a good programmer in any language and a bad programmer in any language.
“Actually, one of the most notoriously conservative and simple (in feature set) languages is really super complex and has evolved a ton because it has _Generic and varargs now, and __packed__ exists as a compiler feature.”
And to further double down, that minor evolution is over 36 years (arguably a decade longer, but I’m being generous with your argument). Not the 12-16 years (depending which 5 point release you wanna start with) that PHP has morphed into an entirely different language.
PHP doesn't prioritize stability, but language features and cleanup. It's an impressive technical endeavor that has its merits, but comes with a tradeoff.
Within the last 10 years, the language itself broke twice. And that's not counting the ecosystem on top of it. Common frameworks, libraries etc. tend to break relatively often as well.
There are languages that are _much_ more stable and reliable than that.
The @ operator doesn't get rid of exceptions it get rids of "warnings" which are basically built in log messages.
It used to get a bad wrap for also silencing fatal errors, but it stopped doing that a while ago.
The @ operator is something that should only be rarely used, but it is no way comparable to catching exceptions and doing nothing with them. There are sane uses for it.
Meanwhile it seemingly abandoned features and unique selling points, like the in-built templating, associative arrays with value semantics and the fact that it integrates well with C or the simple fact that it can be used to write web server scripts very easily. To me, many of these cool features have been largely ignored or even moved away from.
The url parse example is not being compared to the builtin parse_url function that is just as easy to use.
Not everything will always update flawlessly but with Composer and a popular framework with planned depreciations and releases the ecosystem tends to sync fairly well.
Probably because compile/interpret is one way street. There is no way to lets say view/transform a part of the code in functional or imperative depending on what you need to do with it.
Reading modern php or even worse mixed generations code base feels like another full time job on top of the regular one - coding with it.
#[SkipDiscovery(static function (Container $container): bool {
return ! $container->get(Application::class) instanceof ConsoleApplication;
})]
final class BlogPostEventHandlers
{ /\* … \*/ }I remember when escaping SQL input data was "the correct way" to use your mysql database. Parametrization? Nah, just use mysql_escape_string or whatever it was called.
So I guess it depends on what you mean by unhelpful. PHP as a language makes it pretty easy to do bad stuff. PHP as a community makes it easy to Do The Right Thing.
And let's be real - most handwritten SQL code in existence in most languages just builds queries from concatenated strings, even when more secure options exist. A lot of code doesn't even bother to escape anything. That's not a language problem so much as a developer laziness and assumption that "simplicity always equals correctness and frameworks are always wrong" problem.
The pipe operator is indeed just syntactical sugar (and the article links to another article specifically about it which does cover the case of temporary variables), but with the coming partial function application feature it (in my opinion) will make easier to read/reason chains of code than temporary variables or nested function calls.
---
Books:
* PHP & MySQL: Novice to Ninja by Tom Butler
* PHP 8 - Quick Scripting Reference by Mikael Olsson
* PHP 8 Objects, Patterns, and Practice by Matt Zandstra
* Programming PHP (2020) by Kevin Tatroe and Peter MacIntyre
I personally found them to be really good. I learned a lot from the first book especially.
You can find the code from the first book here: https://github.com/spbooks/phpmysql7
I hope this helps.
If you're purposefully fiddling with undefined behavior, it's because you're A) an advanced developer and you know exactly what you're trying to achieve (and inspecting the generated code) and/or B) you're using a specific compiler and don't plan on porting your code elsewhere.
That being said, it's moot to the aforementioned point. Undefined behavior wasn't introduced as a new language "feature" between C89 and C23; it's existed the whole time. We're talking about language deltas, not the entire corpus.