PHP 8.4
464 points
2 days ago
| 30 comments
| php.net
| HN
idoubtit
2 days ago
[-]
I'm just a PHP programmer for work, but I worry about the orientation PHP has chosen. As French people say: better is the enemy of good (Le mieux est l'ennemi du bien). The two new language features bring a higher language complexity for dubious gains. I hope I won't have to work with these.

Property hooks mean that some language magic will turn a property access into a call to methods. It implies that `$this->x` has a different meaning if it's inside a hook or outside hooks. I've used this kind of feature (getters/setters) with JS code (and with Moose/Perl decades ago), and I wasn't convinced. Plain methods are more explicit, have less cognitive charge, and are easier to extend.

On the bright side, I'm glad that the language is still thriving. In 2021, I was worried when the foundation was created, especially as I read that Nikita Popov had left. He was the creator of PHP's JIT code, and at the time the only developer who could fully understand it. But it seems there was no need to worry. PHP is now longer "the elephant in the room" of web programming, but it's still a good language, with many active developers at its core.

reply
ok123456
2 days ago
[-]
This feature has been in C# since about 2.0, and it's been an overall positive. It reduces boilerplate and inconsistencies in different programmers doing the boiler-plate differently.

It also gives static analysis tools semantic information about the structure of your classes. It can group pairs of methods that deal with the encapsulation of fields.

reply
jug
6 hours ago
[-]
My favorite feature about properties is that I can set a breakpoint on the setter. It'll now break on anything that sets it with a single breakpoint. Or use "Go to calls" on the setter and I instantly get everything that sets the variable. Of course also works with the getter. Being able to do this, yet only use it as a field is so nice. Other than this, I find properties indispensable in MVVM scenarios so that the view reacts when you set a property. Using getter and setter methods would litter my code so bad that I can't see a "clarity of intent" net positive.
reply
crowcroft
2 days ago
[-]
I am also in favour of the change. I would argue though that because it's been in C# for so long, then yes it reduces inconsistencies across programmers/codebases, but introducing it to a language as mature as PHP is now though, might not have the same outcome.
reply
ok123456
2 days ago
[-]
I used it immediately in my C# code at the time. It was a breath of fresh air not to have code that looked like "enterprise" java.
reply
signal11
2 days ago
[-]
It’s interesting to consider the “magic” criticism in the context of languages like Zig, where devs actively want no hidden control flow. And Properties beyond simple { get; set; } are definitely hidden control flow.

But as you said — it’s been there in C# for a while and imho it’s a good abstraction over getters and setters. Even 2005-era IDEs could manage it fine, making it easy to access the property’s get/set code, so that it wasn’t really magical.

Maybe it’s a culture thing — most C# devs use IDEs. Not sure what PHP devs use, but I suspect tools like PhpStorm will make this easy to work with somehow. Devs using no-LSP editors will likely have a different view.

reply
amerkhalid
1 day ago
[-]
> Maybe it’s a culture thing — most C# devs use IDEs. Not sure what PHP devs use, but I suspect tools like PhpStorm will make this easy to work with somehow. Devs using no-LSP editors will likely have a different view.

This is probably one of the big factors. I am also not a huge fan of “magic” even though I use IDE (vscode). I started off as a PHP dev, directly editing files on production server using vi. Any “magic” simply slowed me down.

Years later, now I can simply cmd+click to anywhere in code but it feels a bit off to me. Perhaps, I still miss my old days of dev.

reply
hakfoo
17 hours ago
[-]
At my first job, I largely used Notepad++ and grep, and the result tended away from object-oriented code and code paths tended to be not much more than `require_once("common.php");`

The second job introduced PHPStorm, and a single page load can bounce through dozens of files and classes; it would probably be untenable without modern tooling.

reply
neonsunset
1 day ago
[-]
How do you expect properties to interact with IDEs?

The argument that C# choosing to offer features that lead to terser implementation seems orthogonal to where you write it. Behavior in property getters and setters may as well be completely hidden from the caller. But the standard expectation is that accessing and/or setting a property should be cheap and not involve much logic, which most of the code out there adheres to.

(and personally I'm finding it to be a more productive experience than any dynamically typed language which always feels like stone age regardless of the environment)

reply
lmm
1 day ago
[-]
> How do you expect properties to interact with IDEs?

An IDE can highlight non-basic properties in a different colour from basic properties, or underline them or something. That would be difficult for an editor to do as part of normal syntax highlighting.

reply
rwmj
1 day ago
[-]
This is also a problem when reviewing changes through github-like workflows, and even more with patch-based workflows. It's probably either impossible or very difficult to fix that ever.
reply
int_19h
1 day ago
[-]
Properties have been in C# since the very first version. And those, in turn, were largely inspired by Delphi, with the honorable mention of Visual Basic.
reply
brtkdotse
2 days ago
[-]
My experience is that 99% of the work related to geters and seters is handled by the IDE
reply
ok123456
2 days ago
[-]
This encapsulation style for OOP is standard; the language should support it and not require additional design patterns or IDE tools.

An argument could be made for adding a sigil so the class user knows this isn't a dumb field, but then if someone wants to upgrade a dumb field to this, as Python encourages, they would need to modify every use.

reply
James_K
2 days ago
[-]
Every step on the path to bloat is justified.
reply
munk-a
1 day ago
[-]
And yet in this wonderful laboratory of a multitude of languages the growth of a language doesn't destroy as much as it offers a larger variety of choice - with good features being stolen by other languages and less good features remaining niche and unique.
reply
James_K
1 day ago
[-]
Look at C++ or Perl, languages with many features that are quite frequently hated. When you add features, you force users to learn those features. It is not just a "variety of choice" because you know that other people will also take some of those choices and you'll probably have to edit their code at some point. Features are not just added to the language, but imposed on its users. The need to add features to a language is a sign that what you already have is insufficient. Features should be added to the bottom of a language, increasing its expressive power, rather than to the top of the language forming cruft around the edges. It would be much more productive for us to collectively abandon PHP in favour of sane languages, ones which don't require the continual addition of more features to cover their foundational shortcomings.
reply
theendisney
1 day ago
[-]
The imposed part was funny. I hope I wont have to use anything new. I only had a mild panic attack reading they changed exit() but it was a false alarm.

Why is it that after the human life span expires all of the code should be thrown away?

I remember when my host updated and php could no longer be opened with <? and my websites spilled their guts all over the screen.

reply
Shorel
2 days ago
[-]
I just checked the code samples from the article/post.

Property hooks look awesome, they fix something that's my main pain point in PHP nowadays.

All these getters and setters manually coded make it feel like Java. Just completely boring and unusable without some fancy IDE that types all that boilerplate.

It is one great feature of C# that I'm glad PHP is adopting. This code is also easier to extend than the Java-like sea of getters and setters.

(I don't consider any mention of JS code as a valid comparison, if anything we are better ignoring JS existence unless forced to do some frontend)

reply
manarth
1 day ago
[-]

  "All these getters and setters manually coded make it feel like Java."
Project Lombok has solved that issue of manual boiler-plate getters and setters in Java. If you program regularly in Java it's worth having in your toolbox.

https://projectlombok.org/

reply
brazzy
1 day ago
[-]
Or, for immutable entities, just use records. Part of the language since 2020: https://docs.oracle.com/en/java/javase/14/language/records.h...

Admittedly they come with some restrictions, but also some additional benefits.

reply
munk-a
1 day ago
[-]
While these are certainly a better option automatically generated default getters and setters have been pretty do-able through magic methods for a while now - and with the more robust reflection we now have access to they can be implemented in a safe manner. I'm still pretty happy to hear we're getting it as a baked in feature.
reply
klaussilveira
2 days ago
[-]
I feel the opposite: this brings simplicity and pragmatism back to PHP. Gone are the years of bowing to the verbosity of Java, sacrificing a dynamic powerful language at the altar of 1995's OOP paradigms.
reply
cutler
2 days ago
[-]
Seriously? Since 5.3 PHP has worshiped at the alter of Java OOP to the extent that writing PHP code is now an exercise in pseudo-Java.
reply
klaussilveira
2 days ago
[-]
Yes, that is correct. And this release marks a point where the language is officially moving away from that.
reply
thrw42A8N
1 day ago
[-]
How? It just got way more invested into OOP... It's now much harder to understand my code at a glance. The Java feeling isn't because I have to write a lot of code, it's how the code works.
reply
stephenr
1 day ago
[-]
> It's now much harder to understand my code at a glance.

Why? Property hooks aren't mandatory. If you want to keep using explicit getter/setter methods, you can do that. If you want to keep using implicit getter/setter hooks via __get/__set, you can do that. If you want to keep using plain property access, you can do that.

All this does, is allow features that previously relied on the black box of __get/__set to be exposed as real properties. This massively improves the scenario for anything that works via reflection, and makes a whole suite of bugs related to unintended behaviour, simply impossible.

reply
thrw42A8N
1 day ago
[-]
Others will use them and I will need to use their libraries. Get and set magic methods were a mistake too. Same with reflection. Again and again, deeper into the Java 6-land, while Java itself went away a decade ago.
reply
stephenr
1 day ago
[-]
> Others will use them and I will need to use their libraries.

From the outside it's just a property access. The whole point is you don't need to worry about whether it's a direct access or a getter/setter with logic, even if it changes from one to the other between versions.

> Get and set magic methods were a mistake too.

They're definitely not ideal, and thanks to this change they're no longer required for the vast majority of cases.

> Same with reflection.

Reflection is a mistake?

reply
thrw42A8N
1 day ago
[-]
I need to worry about it if I'm using it in an app. In what job you don't need to worry about what code are you executing? This is the whole point. It makes my job much harder to do, much more hidden and arcane - not worth it to save few characters.

Yes, reflection is a mistake. It's a hotfix for problems caused by OOP. It's not actually necessary.

TypeScript is a good example. Some people write it like Java/C#, with classes, inheritance, reflection, dependency injection. Usually I can get that code down to 20-30% of original size after I cut out the last class (then I forbid the keyword in linter), and none of that is actually necessary or improved the situation.

reply
stephenr
1 day ago
[-]
> In what job you don't need to worry about what code are you executing?

Worry about? Or understand the fine minutia of how every property you fetch or store is handled?

> It makes my job much harder to do, much more hidden and arcane

I don't know how you do your job, but seeing a real (i.e. not a faux property handled by __get/__set) class member's implementation is literally 1 click away in any decent IDE. Clicking to see the potential hooks of a field vs clicking to see the getter or setter (which may or may not even be defined in the same class) is no different.

> Yes, reflection is a mistake. It's a hotfix for problems caused by OOP. It's not actually necessary.

Right. I guess that's why it's applicable to functional programming. To be a hotfix for OOP?

https://www-master.ufr-info-p6.jussieu.fr/2007/Ajouts/Master...

reply
thrw42A8N
1 day ago
[-]
Of course it's applicable, it means "I read the data out of my runtime". Doesn't mean it's what you should do. Like GOTO, mutable variables in global namespace, and so on.
reply
chx
2 days ago
[-]
> Property hooks mean that some language magic will turn a property access into a call to methods.

__get / __set was doing that already and some frameworks very heavily rely on those.

> It implies that `$this->x` has a different meaning if it's inside a hook or outside hooks.

this is a valid critique but hopefully hooks will be super short and this won't be a major issue. Indeed, if your get is not an arrow function -- which only allows one statement -- then it needs a good thinking over whether this is indeed the best solution. Ie if your get is so complicated then perhaps a helper method is best and then you have get => $this->foo($this->thing) and that's the only place where $this->thing is special.

reply
idoubtit
2 days ago
[-]
> hopefully hooks will be super short and this won't be a major issue.

Even if a PHP project has a policy of short hooks, I think hooks impede clarity.

    public string $countryCode
    {
        set (string $countryCode) {
            $this->countryCode = strtoupper($countryCode);
            $this->country = nameCountry($this->countryCode);
        }
        get => ...

In this short hook, the first line of the setter obviously uses the underlying property. But the second line of the setter...

Does `$this->country =` use the setter even if it's in a hook (but not a `country` hook)?

Does reading `$this->countryCode` use the getter hook, even it's from a `countryCode` hook?

If not, is there a way to call the `countryCode` getter from this setter?

If quickly parsed the doc and the RFC, so I don't have answers (I suppose it's yes, no, no). But even if I knew how this code behaved, I would still think it's much more complex than plain methods.

reply
chx
2 days ago
[-]
> Does `$this->country =` use the setter even if it's in a hook (but not a `country` hook)?

To me it is obvious hooks won't use other hooks because that could lead to an infinite loop in a hurry

> Does reading `$this->countryCode` use the getter hook, even it's from a `countryCode` hook?

same

> If not, is there a way to call the `countryCode` getter from this setter?

There is although it's a bit tricky and not intuitive but I feel this falls under the "it is enough this is possible, there's no need for it to be easy": "Be aware, the detection logic works on $this->[propertyName] directly at compile time, not on dynamic forms of it like $prop = 'beep'; $this->$prop. That will not trigger a backing value." Using dynamic properties in what should be simple code should be rare enough this is not a problem. It's like a bridge convention, the benefits vastly outweigh the drawbacks.

reply
c0wb0yc0d3r
2 days ago
[-]
> Does `$this->country =` use the setter even if it's in a hook (but not a `country` hook)? To me it is obvious hooks won't use other hooks because that could lead to an infinite loop in a hurry

I would expect hooks for properties other than `$this->contryCode` to be called inside of a `$this->contryCode` hook.

Btw the docs that are linked in the post[0] seem to be clearer than the example in the announcement. Reads less ambiguously to me.

[0]: https://www.php.net/manual/en/migration84.new-features.php#m...

reply
alt227
2 days ago
[-]
You are corect that the docs read much clearer. Why would they muddy the concept in the release post?
reply
patates
2 days ago
[-]
> To me it is obvious hooks won't use other hooks because that could lead to an infinite loop in a hurry

Yet in Javascript:

test = { set a(x) { this.b = x }, get a() { return 2 }, set b(x) { this.c = 10 }}

Object { a: Getter & Setter, b: Setter }

test.a = 10

10

test

Object { a: Getter & Setter, b: Setter, c: 10 }

and yes it's possible to make infinite loops.

reply
Gabrys1
1 day ago
[-]
Why would you write such code though? If you want to store an underlying properly, use a differently named (and private) one:

public string $countryCode { set (string $countryCode) { $this->_countryCode = strtoupper($countryCode); $this->country = nameCountry($this->_countryCode); }

reply
beberlei
2 days ago
[-]
Just to set the record straight, Nikita is not the creator of the PHP JIT code, that is Dmitry and he is employed by Zend owned by Perforce working mostly on this.
reply
idoubtit
2 days ago
[-]
Thanks for correcting me, and sorry for the error. I should have checked before writing.
reply
jacobyoder
2 days ago
[-]
I'd tried to put together an RFC years ago to introduce groovy-style accessors in PHP.

$this->foo

would look for a getFoo() method, and execute if it existed, or not if not. Felt like that was easier to reason about, fwiw, but I couldn't get it off the ground. Even then, there were multiple C#-style get/set proposals floating around, so this style seems to be the one more people like. Not a fan of the style, personally, and probably won't use these much directly any time soon. If it helps people maintaining libraries that I use to deliver code that is cleaner and more productive to them... I'm OK with that.

reply
wvenable
2 days ago
[-]
I'm not a fan of that kind of magic in my languages but such a thing was already easily doable in PHP. You could just have a base class that implements __get and __set so that $this->foo automatically calls $this->getFoo().
reply
mgkimsal
1 day ago
[-]
can't do that if you declare the properties on the class. __get only works for undefined properties.
reply
wvenable
1 day ago
[-]
Well don't do that then. :)
reply
hks0
1 day ago
[-]
That advice doesn't always work in real life; otherwise for every compiler or linter check in any language, we could drop all those checks and tell the programmers not to do that.

E.g. if a base class declares a variable it can potentially break its children. Whose at fault here?

I agree with your original comment though. And if the bypass of exisitng fields is badly wanted, somehow marking __get to disregard them makes more sense to me.

reply
munk-a
1 day ago
[-]
Or, alternatively, use `__call`
reply
9dev
1 day ago
[-]
Doctor, doctor, it always hurts when I press here…
reply
notresidenter
1 day ago
[-]
This has existed for so long though, through `__get`, `__set` and other methods, the ArrayAccess interface, the `__call` and `__callStatic` methods.

This way, at least, it's much more explicit. And this should probably only be used inside frameworks anyway, and not in "user-land" code.

reply
keyle
1 day ago
[-]
I agree with what you wrote and I am familiar with that saying.

PHP to me, professionally, is nothing without Laravel. So as long as Laravel doesn't become more obtuse than it already is, it's all good.

I really dislike getters and setters, particularly when they allow async code. Now all the sudden you have a massive performance risk, it's all too typical to see junior devs doing expensive stuff in getters and now the whole application, exponentially, becomes slower.

Anything that _may_ involves magic is dangerous in large code bases.

reply
conradfr
2 days ago
[-]
Don't you get tired of managing getters/setters in your entities?
reply
cutler
2 days ago
[-]
Entities, shrentities - it's all just data.
reply
mgkimsal
2 days ago
[-]
aren't you just managing them in a new syntax now?
reply
joshmanders
1 day ago
[-]
The difference with property hooks and userland getter/setters is that you're now just doing

    echo $obj->prop
    $obj->prop = 'bar';
not

    echo $obj->getProp();
    $obj->setProp('bar');
reply
stephenr
1 day ago
[-]
A big part of this is about code that's consumed by third parties: i.e. library code.

Previously, it was very common to not expose a public property directly, even if it required no setter logic, because any future change to add setter logic would mean it has to become a setter method.

This results in potentially dozens of boilerplate getter/setter methods, that provide no actual benefit, but are necessary to avoid potential BC breaks in a future version of the library.

With property hooks, the property doesn't need to define any getter/setter logic initially - and adding a hook later to the `set` action doesn't change the way other code calls it.

So no, it isn't just "new syntax" now - it's a case of largely not needing to write/generate any of that boilerplate any more - it's just not needed, regardless of how that property's behaviour changes in future.

reply
whalesalad
2 days ago
[-]
stockholm syndrome is real
reply
immibis
1 day ago
[-]
This comment is referring to the practice of always writing getters and setters even when they are not needed, then feeling frustrated by the amount of boilerplate.
reply
tcfhgj
2 days ago
[-]
which getters/setters?
reply
alt227
2 days ago
[-]
I agree. PHP is such a simple language to follow but now with these property hooks, if you dont fully understand how they work then the code becomes unreadable due to the magic.

Worse than that, it is possible to read it wrongly which is going to cause many nasty headaches for amateur developers of the future trying to debug PHP code.

reply
wvenable
2 days ago
[-]
PHP has had the ability to dynamically handle properties for decades so this doesn't hurt readability -- in fact, it makes it better.
reply
giraffe_lady
2 days ago
[-]
I wrote php exclusively only for about two years early in my career but have had to come back to it periodically every once in a while. I find it one of the most difficult languages to be a visitor in. The way variable, array, and class semantics mix can make it hard to decipher the exact behavior of a chunk of code. Especially if you have a mix of "old" procedural and modern OO php, which the projects I work on do.

I'm not bringing this up as a particular criticism of the language, I think it's fine. It is also an experience I have with lisp, where it is fun and easy to write but hard to read when coming back to it after a while away. I just don't think php is a simple language, on several levels. The semantics that I mentioned, combined with the mixing of paradigms, and the large and inconsistent standard library. You can write simple php but it takes a lot of discipline.

reply
alt227
2 days ago
[-]
> Especially if you have a mix of "old" procedural and modern OO php

I guess thats a result of such wildly changing features in each version change. Each major version of PHP has brought in such drastic changes of concept and semantic that it is easy to start mixing them together and get confused looking code.

However I find this in a lot of other systems. Look at node.js, every release changes things so much that people regularly rewrite their entire code base multiple times to take advantages of the new features. Do a google search for guides on node programming a specific issue, and depending on how old it is it you will get wildly differnt approches and results. Popular and highly developed languages change often, and this will always cause issues between old and new.

reply
giraffe_lady
2 days ago
[-]
I agree. I think for largely cultural and timing reasons, and also its success, there are a lot more long-lived php codebases for this to play out in compared to most languages.

I also think possibly node is our generation's php, with it being so fast-changing and there not being a community consensus about framework. So every complex node project is, like pre-laravel php, essentially a totally unique ad-hoc framework composed of a mix of libraries. Ruby and python aren't better languages than php or node, and rails and django aren't perfect, but to a large extent those languages avoid this problem just because everyone is using the same solutions.

reply
wbl
2 days ago
[-]
T_PAAMAYIM_NEKUDOTIM, mysql_real_es ape2, parse_str, etc.
reply
duskwuff
1 day ago
[-]
> mysql_real_escape2

Blame MySQL for that name, not PHP.

https://dev.mysql.com/doc/c-api/8.4/en/mysql-real-escape-str...

(And, if you're doing modern PHP, it's just PDO->quote().)

reply
munk-a
1 day ago
[-]
I'm not certain about OP's objection but for me it's less the function name and more the terrible history of how PHP tried to automatically fix SQL injection and instead made everything a thousand times worse. If you're not using bound parameters for user data you're taking a huge risk and making your life multitudes more difficult. PHP's PDO is by far the better option at this point but it suffers from poor enough usability that I've built my own wrapper for it at two different companies.
reply
Dylan16807
1 day ago
[-]
> the terrible history of how PHP tried to automatically fix SQL injection and instead made everything a thousand times worse

Are you thinking of stuff like magic quotes? mysql_real_escape is not part of an automatic anything. You manually use it to quote each value.

reply
hparadiz
1 day ago
[-]
Writing a wrapper for PDO is standard operating procedure for various good reasons.
reply
wbl
1 day ago
[-]
Why should I blame MySQL? It's the PHP developers that decided to introduce it and not change the name, plus have several functions that don't do the right thing as well.
reply
cess11
1 day ago
[-]
This hasn't been an issue for like fifteen years or whatever.

In hindsight I think it's a good thing, it's a pea that keeps princesses at a distance from the language.

reply
reaperducer
1 day ago
[-]
The two new language features bring a higher language complexity for dubious gains.

For a long time now, PHP has been on a trajectory of trying to be everything to everyone, constantly bolting on features from every language that happens to drift by.

My observation has been that the people who are deeply invested in PHP are tired of being hazed online for using a "toy" language, so they're trying to adopt all of the complexity and problems of other languages, rather than just keeping things simple, which is what used to be PHP's primary strength.

reply
cess11
1 day ago
[-]
PHP was never particularly simple, it has always had a diverse standard library and lots of similar but subtly different builtins and a rather funky type system and so on.

It's not for people that compulsively talk about category theory and lenses five minutes into every programming conversation.

reply
dubcanada
2 days ago
[-]
None of this is required. You can still write spaghetti code perfectly fine.
reply
smarkov
2 days ago
[-]
Of course it's not required but when you start pushing the boundaries of a language with the goal of achieving a clean interface, obscure features you wouldn't normally resort to become appealing. I dislike all of the magic around Laravel's Eloquent ORM - model relationships, query builder, abuse of ForwardsCalls trait, etc, but at the same time I can appreciate how "clean" it all looks once it's put together.
reply
eurleif
1 day ago
[-]
I was curious about why setting `$this->countryCode` inside the setter for `countryCode` didn't result in infinite recursion. Turns out this is spelled out in the RFC, but not in the docs:

   When a hook is called, inside that hook $this->[propertyName] will refer to the “unfiltered” value of the property, called the “backing value.” When accessed from anywhere else, $this->[propertyName] calls will go through the relevant hook. This is true for all hooks on the same property. This includes, for example, writing to a property from the get hook; that will write to the backing value, bypassing the set hook.
   
   A normal property has a stored “backing value” that is part of the object, and part of the memory layout of the class. However, if a property has at least one hook, and none of them make use of $this->[propertyName], then no backing value will be created and there will be no data stored in the object automatically (just as if there were no property, just methods). Such properties are known as “virtual properties,” as they have no materialized stored value.
   
   Be aware, the detection logic works on $this->[propertyName] directly at compile time, not on dynamic forms of it like $prop = 'beep'; $this->$prop. That will not trigger a backing value.
Feels like too much magic to me that a property access can mean different things depending on context, but I'm not a PHP user, so I don't get a vote.
reply
hipadev23
1 day ago
[-]
> too much magic

The backing value is effectively private to everything but its own get/set methods, that seems fairly straightforward to me.

reply
eurleif
1 day ago
[-]
What's magic is that `$this->foo` refers to different entities in different contexts despite the same value of `$this`, not that one of the entities to which it refers can be private.
reply
nedt
1 day ago
[-]
The dynamic form is really not needed very often. Should it ever become a problem triggering a loop you can just set and get from a private property with a different name. But then also 90% of getters and setters are really simple so it will feel as magic as gravity.
reply
akie
1 day ago
[-]
Whenever I read about a new PHP release on HackerNews I always come away disappointed with the discussion. You are right, the "magic" that the top comment is complaining about is a non-issue, and I say that as someone who really strongly dislikes "magic" behavior.

In fact, you can imagine what their argument WOULD have been if setting `$this->countryCode` inside the setter for `countryCode` DID result in infinite recursion.

When it comes to PHP, whatever it does, on HackerNews and in the rest of the industry, it just results in a bunch of people complaining about it. Disappointing, and unprofessional.

reply
ezekiel68
1 day ago
[-]
Funny world where a feature to prevent infinite recursion -- at a moment in the runtime lifecycle where that would make sense -- is somehow viewed as dangerous footgun magic (addresed to: several replies under this comment).
reply
Dylan16807
1 day ago
[-]
You could prevent the recursion without this magic, by making the access a compiler error.
reply
Implicated
1 day ago
[-]
404 ComPHPiler Not Found
reply
Dylan16807
22 hours ago
[-]
Whatever you want to call the code that parses the file and emits a syntax error.

Though what would you personally call "the thing that turns it into bytecode"?

reply
Drew_
1 day ago
[-]
C# has the same thing as Properties, but the backing value is set explicitly as a separate variable:

https://learn.microsoft.com/en-us/dotnet/csharp/programming-...

reply
wvenable
1 day ago
[-]
There are many times I would love to have an automatic backing field in C#. C# will do that if you use the default setter but in cases where that's not possible I dislike having to both declare a separate field and having it available to the rest of the class outside of the setter.
reply
bwoebi
1 day ago
[-]
C# 13 has this via the field keyword (as preview feature): https://learn.microsoft.com/en-us/dotnet/csharp/language-ref...

It's pretty similar to what PHP provides here, except that PHP uses "$this->propname =" and C# uses "field =".

Edit: As someone involved in the RFC, it's somewhat funny, because we considered a special variable like "$field" or "$value" too magic, and C# does just that with a field keyword.

reply
kroltan
1 day ago
[-]
The `field` keyword also already existed in C#, to add attributes to the backing field of automatic properties, so I think the argument was easier there.

I used it in Unity projects to have serialized/inspectable values exposed through properties:

    [field: SerializeField]
    public int MyProperty { get; private set; }
reply
Spivak
1 day ago
[-]
I think it being a keyword does change how magic the feature feels. "$field" and "$this->name" make me think that this behavior is playing by the normal rules of the language but is implemented using some trickery to edit the local scope of this function to add or modify variables. When it's a keyword it says this is a special form and that this is a feature of the language itself.
reply
neonsunset
1 day ago
[-]
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/cs...

edit: the properties reference now documents the 'field' keyword too

reply
wvenable
1 day ago
[-]
That might be all the motivation I need to go move to .NET 9.
reply
runevault
1 day ago
[-]
.NET 9 has so much good stuff in it. Thing that I randomly realized I wanted only to find out it works in 9 is dictionary access with "related" types (so like if you have a ReadOnlySpan<char> you can use that to find a value from a string in the dictionary via a value type created off the dict).
reply
tail_exchange
1 day ago
[-]
I'm also not a php developer, but I agree. This seems like a huge footgun.

I've never been a fan of this kind of magic, and I wonder how other languages deal with this case.

reply
crimsonnoodle58
1 day ago
[-]
Well in python I assume it would be equivalent of accessing:

  self.__dict__['property_name']
And if those PHP rules were in python you could just write:

  @property
  def property_name(self):
      return self.property_name
In actual python though, that would infinitely recurse.
reply
arkh
1 day ago
[-]
Or if they could follow Godot syntax: https://docs.godotengine.org/en/stable/tutorials/scripting/g...

var milliseconds: int = 0

var seconds: int:

get:

  return milliseconds / 1000

 set(value):

  milliseconds = value * 1000
reply
Liquidor
1 day ago
[-]
Lua has rawget() and rawset() to bypass the magic methods, which is used a lot inside/outside the metatables (objects with magic methods) to avoid magic loops I guess.
reply
kijin
1 day ago
[-]
It might be a footgun, but it will be extremely obvious when it is triggered.
reply
stephenr
1 day ago
[-]
The original RFC that led to this feature originally used a special variable to indicate the backing store; that was overwhelmingly disliked, as it was "magic".

Conversely php already has other places where context affects property accesses, and IME it's not the problem you make it out to be.

reply
acabal
2 days ago
[-]
I'm most excited for property hooks. Having getters and setters as part of the language syntax was something I dearly missed from my C# days, nearly two decades ago.

In my projects I sometimes emulate getters and setters using `__get()` and `__set()` but that's heavy-handed and requires lots of PHPDoc annotation for type checking. Property hooks look awesome!

reply
Xeoncross
1 day ago
[-]
I'm curious, why do you like getters and setters?

I know the textbook answer is so that every single possible property can become some mutable chain of events so you can swap names or side-effects without the caller knowing, but I've yet to find a use for that in real life.

It just leads to builder patterns and other oddities like forced decorators like Java has everywhere. I felt like beans were the realization that perhaps we shouldn't be doing this.

reply
acabal
1 day ago
[-]
They are very useful when modeling CRUD-dy objects, because you can lazy-load infrequently-accessed child object using getters.

It makes for a cleaner OOP-y interface in which the caller only cares about actually exposed properties and not methods to get and manipulate hidden properties.

IMHO using properties directly is a much more natural way to talk about objects, than having a bunch of methods to get properties. Getters and setters also help ensure that methods are only for changing an object's state, not getting an object's state. For example:

  class User{
      public ForumsPost $LastForumsPost{
          get{
              if(!isset($this->LastForumsPost)){
                  $this->LastForumsPost = <get from database...>;
              }

              // Return the cached property so we don't keep hitting the database.
              return $this->LastForumsPost;
          }
      }
  }

  print($user->LastForumsPost->Title);
  print($user->LastForumsPost->PostId);

  // instead of...

  print(($user->GetLastForumsPost())->Title);
  print(($user->GetLastForumsPost())->PostId);
reply
Xeoncross
1 day ago
[-]
I appreciate the detailed answer, thanks. However, It feels like $a->foo vs $a->foo() is a personal preference that hides the fact you're doing work behind the scenes.

Then again, I'm not a fan of code that does magical things that aren't apparent. Makes it a lot harder to 1) reason about and 2) solve performance issues. I also don't want the overhead of function lookups for every property access.

reply
acabal
1 day ago
[-]
Getters aren't for everything. But for a basic CRUD case like above, they're a nice way of having a clean OOP contract by demarcating a clear difference between properties, which are pieces data attached to the object that the caller can read and write, and methods, which are the caller can change the object's or app's state, or perform actions with possible side-effects.

Very often for a typical CRUD app, I as the caller don't really care how we got the `LastForumsPost`. It's just an object mapping that comes from some data source like the database. And if I do care, I could get it outside of the object, and set it myself.

reply
Kiro
1 day ago
[-]
Your example seems like an argument against getters. In the case of fetching posts like this I always want to know whether some logic is running. What if the operation is really heavy? When it's a getter you would think it's already loaded.
reply
hamandcheese
1 day ago
[-]
I do not see any advantage here. All I see (or rather, what can't be seen) is hidden control flow. For what? To save a few characters?
reply
acabal
1 day ago
[-]
It's a matter of OOP modeling. Object methods are better reserved for performing actions with side effects, or complex logic or calculations, and not for getting state or simply setting public properties; and as a caller, I don't really care about the implementation details of (in my above example) getting the last forums post, I just care that it's a property I can access. (Maybe it came from a cache and not the database? Maybe it was set earlier in the script? I don't care.)

Putting it behind a getter doesn't "hide" control flow. It just makes for a cleaner interface from the caller's perspective.

FWIW, I almost never use setters. Getters are are much more useful, especially for lazy-loading basic properties.

reply
munk-a
1 day ago
[-]
I've always been a fan because if a property turns from a simple value to a more complex interaction that might involve DB operations or other side effects then if a getter is in place you can modify the logic without needing to update widespread code.
reply
hamandcheese
1 day ago
[-]
If you are replacing a performant property with a slow network call, you are being negligent if you aren't reviewing all the callers to make sure that is okay.
reply
hparadiz
1 day ago
[-]
In a typical ORM when you do say $Model->DateTime = 1732046457; the __set is actually checking the value and seeing oh it's an integer. Treat this as a unix timestamp. But when you run save() the query is actually converting that to a Y-m-d H:i:s (for MySQL/MariaDB). This doesn't actually happen until you run save() when it makes the query and runs the network call. Most of that time it's actually storing everything in memory.

But you might want to support string date times and the PHP object DateTime as well. So a typical well designed ORM converts multiple PHP types into a SQL string for saving. That's what the historical __set and __get are all about. This is called "mapping" by most ORMs and a very well designed modern one like Doctrine will actually have mappings for different SQL storage engines available.

Obviously it also has to handle the reverse.

reply
hamandcheese
1 day ago
[-]
That is a fine argument for setters, but I still don't see the connection between that, and the desire to disguise properties as setter methods.
reply
hparadiz
1 day ago
[-]
Some light weight ORMs do not require you to define all the properties ahead of time. They pull the field names from the table and generate the model record on the fly for you. This generally lets you prototype really fast. Laravel's Eloquent is known to do this. It's also useful for derived SQL fields when you use custom queries or join from other tables. Also kinda fun to do it for properties backed by a method. As in $record->isDirty will run isDirty() under the hood for you. All these things can be documented with PHPDoc and static analyzers handle it just fine.
reply
hamandcheese
1 day ago
[-]
Is it possible to dynamically define methods in PHP?
reply
hparadiz
1 day ago
[-]
Yes.
reply
wvenable
1 day ago
[-]
A method is supposed to be an action and a property is supposed to be data. So I don't see the desire to disguise setting data as a "setting method" rather than using the syntax of assignment.
reply
hamandcheese
1 day ago
[-]
> A method is supposed to be an action and a property is supposed to be data.

I agree! That's why it's wild to allow a setter to do literally anything.

You aren't just setting a property, there is a conversion happening under the hood.

And the reason I hate it is that code that appears to be infallible, isn't. It can have arbitrary side effects, raise exceptions, have unbounded runtime, etc.

reply
lmm
1 day ago
[-]
There are many ways to make code misleading. You can write a method called plus and have it do multiplication. You can write a method that sounds safe but looks dangerous. Every language relies on programmers exercising judgement when writing the program.

In a lot of contexts you have something that requires a bit of code but really does behave like a property access, where it's more misleading to make it look like a method call than to make it look like a data access. E.g. using an ORM hooked up to SQLite embedded in the program. Or accessing properties of objects that you're using an EAV system or array-of-structs layout to store efficiently in memory. Or a wrapped datastructure from a C library that you're binding.

Of course if you make something look like a property that doesn't behave like a property then that's confusing. Programmers have to exercise judgement and only make things look like properties when they behave like properties. But that's not really any different from needing to name methods/objects/operators in ways that reflect what they do.

reply
wvenable
1 day ago
[-]
It's abstraction. Your not supposed to care that the setter is doing anything. The class is providing you an interface -- what it does with that interface is not your concern. I hate to quote Alan Kay but all objects should just respond to messages. Whether that message corresponds to a method or a property is pure semantics.

I sometimes use getters and setters to provide backwards compatibility. What was just maybe a simple data field a decade ago doesn't even exist anymore because some major system has changed and we aren't rewriting every single application when we can provide the values that they need easily enough.

If you know that setters exist then you already know that the code can do more. It's not a huge mental leap from property setting to method calls. You should never assume anything is infallible. I don't think classes should even expose raw fields.

reply
whalesalad
1 day ago
[-]
Getters are great for manipulating data on the way out. For instance, inside the class you might store a raw representation of the data like a json string, but when reading an attribute you will decode that json string into a datastructure and pluck a certain item. I use dynamic getters often to wrap a raw value with some kind of fallback: do this if no data is present, do this if the data is present but is ancient (ie a seamless upgrade of a v1 internal datastructure to a v2 output), etc. For setters, I try not to have implicit side effects but in certain cases where it makes sense, it is nice to be able to centralize that logic: "if this value changes, ensure x and y occur" which you get "for free throughout your codebase when you use a setter, versus having to go thru the entire codebase and sprinkle the do_x() and do_y() calls (which then becomes additional footprint to maintain and worry about)
reply
hparadiz
1 day ago
[-]
They are used in ORMs to do property value conversions from PHP primitives to values a data store might actually want.

I wrote about it here https://technex.us/2023/07/php-attributes-are-so-awesome-i-j...

reply
dragontamer
1 day ago
[-]
The more I program the more I realize that we are all blind men feeling out an elephant.

It sounds like you got the gist but somehow you are in an area of programming where getter/setters aren't useful.

That's fine and okay. Part of growing up as a programmer is realizing your niche.

Most of the advice out there is deep, not broad. It's deeply connected with our niche and not necessarily broadly applicable.

reply
hombre_fatal
1 day ago
[-]
Getters/setters are just as easily associated with hidden behavior that makes systems worse.

The only sibling comment of yours that bothered to even show code just demonstrated how they turned user.lastPost into a method that makes a hidden DB query.

Yet the benefits are supposedly so nuanced and hard to get across that merely asking about it gets a "you'll understand when you get some real experience ;)" comment from you.

reply
keybored
23 hours ago
[-]
Haha as someone who doesn’t understand getters/setters as a pattern I’m bewildered by this subthread.
reply
keybored
1 day ago
[-]
It sounds like you got the gist of the critique of getters/setters but just haven’t been exposed to the alternatives.

That's fine and okay.

reply
smt88
1 day ago
[-]
This was weirdly condescending and content-free.

I've been programming for 30 years, and getters/setters are both pointless and anti-productive.

They hide (potentially a lot of) code from people reading the program, which leads to a lot of "wtf" moments later.

Magic in general is bad, and it's the kind of "look how concise and clever I am" thinking that leads to unmaintainable software.

If setting a property isn't straightforward, make it private/protected and add explicit getter/setter methods. It's more work today and much less work later on.

reply
hparadiz
1 day ago
[-]
Every php ORM disagrees. Nothing about it is magic
reply
smt88
1 day ago
[-]
PHP ORMs and ORMs in general are notoriously hard to maintain. I've written hundreds of thousands of lines of PHP, I'm speaking from experience.
reply
hparadiz
1 day ago
[-]
I maintain an ORM [ https://github.com/Divergence/framework/blob/release/src/Mod... ] and have also maintained a job's fully custom ORM as well. 20 YOE in PHP. Also speaking from experience :)
reply
munk-a
1 day ago
[-]
I've written some auto-getter and setter spawners and with reflection it's pretty do-able to implement proper type checking as long as the type you want to check for matches the type declared on the property. PHP meta-coding is actually quite advanced and pretty accessible compared to what I've done in other languages.
reply
foolfoolz
1 day ago
[-]
this was the one feature i read in here thinking “why would anyone want this?”

seemed like a way to backport poor librar/framework choices to have IDE support but not for new code

reply
tored
2 days ago
[-]
Great PHP release. Better stack traces for closures, performance improvements (always nice), HTML5 support, lazy objects and much more. Great work and a big thanks to everyone involved!
reply
bornfreddy
1 day ago
[-]
Am I the only one excited about bcmath objects? Not so much because of arithmetic operators, but mostly because now we can do data types checks without resorting to wrapper classes. Nice!
reply
LeftHandPath
1 day ago
[-]
I went to look at array accessor overloading today and saw “Property Hooks” in the sidebar (under “Classes and Objects”).

I didn’t know what they were, so I clicked. I was bewildered that I had never run into them before, used them in my own code, or seen them used by others. Come to find out they’ve only been around for about a day!

Reminds me of some of the lovely expressibility and syntactic sugar that’s pulled me to other languages lately. Glad to see it make its way into PHP.

reply
9dev
1 day ago
[-]
The next thing I would love to see adapted would by Python—style array access:

  $foo[1:-3:2]
Instead of the usual array functions, which could stick around for BC. That would be amazing
reply
cbg0
2 days ago
[-]
Glad to see PHP still chugging along after all these years. It's the language I started with as a freelancer more than a decade ago and I still remember having books on my desk learning the proper way to do things, as you had to work around all the unsafe things the language would let you do and which unfortunately led to it getting a bad rep.
reply
ChrisMarshallNY
2 days ago
[-]
One of the issues with creating a language that is easy to use (PHP, BASIC, and many modern languages), is that people who aren't good at programming, will use it.

With predictable results.

The difference between languages like PHP and more modern languages, is that the more modern languages have more airbags, for the bad code. It's still bad code, but it won't do as much damage.

PHP is likely to be around for a long time: https://w3techs.com/technologies/history_overview/programmin...

reply
afiori
1 day ago
[-]
My understanding is that PHP was sort of started by people that did not plan for it like a "serious" programming language, but rather as a tool for specific applications.

So it developed features and functionalities as needed with a very pragmatic focus [0][1]

[0] the most clear example to me is that since functions are not values and cannot be assigned to variables the way to store a function in a variable is to simply assign its name as a string so $callable = "array_map" works. Or that the way to create a pointer to a method is to create a 2 element array of the object and the method name. I like this example because the way method pointers work in JavaScript is objectively worse as the "this" is easily lost. Some languages are built on CS principles and PL theory, others like Bash or PHP are just built to get shit done. I am glad that recent versions are fixing some of the oversight of this approach while keeping the pragmatic culture

[1] I am not sure of how true it is, but some claim that some of the standard functions have irregular names because the interpreter used the name length as hash key

reply
scq
1 day ago
[-]
[1] is true. Here it is straight from PHP's creator: https://news-web.php.net/php.internals/70691
reply
dctoedt
1 day ago
[-]
> more airbags, for the bad code

Great metaphor. I might steal it for some model contract terms I'm doing (for an expanded version of my contract-drafting course materials). I'd been thinking of "guardrails," but "airbags" is far better.

reply
lesuorac
1 day ago
[-]
I dunno, we just about got rid of the whole "cosmic rays" discussions for computers and finally are getting realistic about the bugs that occur in computers are from bad C code and bad hardware. Neither of those things are easy to use and they have done probably more damage than crappy php code does.
reply
inerte
2 days ago
[-]
> With predictable results.

People building and creating awesome new things? Increase in happiness and empowerment? More efficient processes and increase in productivity? New businesses being born? Wealth and value being added to society?

reply
ChrisMarshallNY
2 days ago
[-]
> More efficient processes and increase in productivity

I'd have to see the numbers on those ones.

But I am not a "gatekeeper" type, maybe you are confusing me for one. I'm a high school dropout with a GED, and have been staring up people's noses, all my life.

I just believe that any job we do, should be a good job.

Build on a sand foundation, and you'd better not go too high, or Bad Things Happen.

reply
9dev
1 day ago
[-]
I agree that it’s especially sad then to see someone with your background taking that position then. While we’re busy discussing inelegant abstraction patterns in code, a bunch of founders have written the foundations of a successful startup with horrible code, creating work for better programmers (but worse founders) in the process.

A good friend of mine has founded such a company, and boy, I loathe his code. But at the end of the day, he’s incredibly good at getting something out of the door now, which is working. A language that makes this possible, while still scaling to fully type-safe and optimized bytecode with a JIT compiler if needed is a good one.

reply
ChrisMarshallNY
1 day ago
[-]
So you know someone that is an expert at building sand foundations, and selling them? That’s a good thing, and something to emulate?

For a lot of folks (especially hereabouts), “makes money” is the only valid metric.

That’s not my experience or personal PoV. I’ve been shipping (as opposed to “writing”) code, for over 30 years. Pretty much everything I’ve written, has made it out the door (although not always to subsequent success). I’m fairly familiar with what it takes to ship. I agree that it’s a relatively uncommon skillset, but I’ve also learned to ship stuff with a future. One of the projects I developed, took ten years to come into its own, and it had to stay solid for all that time, until the right team could take it over. The fact that the code is well-written, well-supported, and well-documented, is the main reason that it finally took off.

I don’t like PHP, and one reason, has been alluded in other comments. It’s a sand foundation. Over the years, it has been massively backfilled, and is now pretty damn robust, but the sand foundation is still visible.

But it is a useful tool, if wielded correctly. If used incorrectly, though, that’s another story, and there’s a lot of bad PHP out there.

I have heard a quote, attributed to Stroustrop, that goes “With C, you can shoot yourself in the foot. With C++, you can blow your whole leg off.” I’m skeptical he’s the one that said it, but it’s a truism.

I have a friend that is an arborist (tree guy). He’s really experienced, and really good at it, and makes great money.

Watching him use chainsaws, though, is kinda terrifying. For one thing, every one of his saws has the safety guard removed, and he’ll go monkeying up a tree, with three running chainsaws, hanging off him. He uses them like you’d use a fork at the dinner table, and can take down a huge locust tree, in an hour or so, alone.

He makes it look easy, but I’m not so idiotic, as to think I could emulate him.

We have a running joke, every time he sees me, he holds up his hand, showing that he still has all his fingers, because I told him that he would end up chopping off a finger or two.

There now exists a huge base of very good PHP programmers. It took quite a while to coalesce, but it’s here. I don’t claim to be one of them, but I have used the language to ship some fairly ambitious stuff, for the last quarter century or so, so I can wrangle it reasonably well.

reply
grey-area
2 days ago
[-]
This varies by domain of course, but on the web (PHP's domain), the language in greatest use nowadays by professional programmers is....Javascript.
reply
omnimus
2 days ago
[-]
Because its hard requirement. Its not the case at all on backend.
reply
grey-area
1 day ago
[-]
No, I’m talking about voluntary use of frameworks like react to create websites.

The front end can have very little js and still be fully functional (like this website for example).

reply
7bit
2 days ago
[-]
What a condescending point of view.
reply
owenpalmer
2 days ago
[-]
I don't think OP was trying to be condescending. Even if they were, they're still right. A lot of modern languages are designed with bad programmers in mind.
reply
munk-a
1 day ago
[-]
One thing I'd like to highlight though is that there were mountains of terrible advice out there around PHP from novices who had figured out a way to make things work - around the time of PHP 5.3 the community ran an ambitious initiative to crawl through sites like Stack Overflow and replace bad answers with correct ones. The community realized how dangerous it was for novices and how much all the bad advice was hurting the reputation of the language and they took decisive action to fix it.

Separately, IMO, languages should always be designed with bad programmers in mind - good programmers are going to figure out the right way to do things in any language but bad programmers are going to fire off every foot gun they can find. PHP has made efforts to remove or de-emphasize foot guns and it has evolved into a much safer tool to give someone.

reply
ChrisMarshallNY
1 day ago
[-]
Wasn't trying to be, but it's my experience that people will deliberately assume the very worst intentions, behind whatever I write, so it's a losing proposition, trying to be circumspect.

I am, however, pretty against selling crap. If people pay for my work, or even if they don't (most work I do, these days, is free), they have the right to expect that I did good work.

I do run into quite a few folks that write crap, know they write crap, but don't care, and expect people to pay top dollar for their crap.

If that's a "condescending" attitude, then guilty as charged.

reply
rty32
1 day ago
[-]
To be honest, it's a pattern I see under every PHP thread:

(Neutral) PHP news -> PHP bad -> PHP not bad

Even if people didn't actually say "PHP bad"

reply
ChrisMarshallNY
1 day ago
[-]
I use PHP for my backend work. I am not an outstanding PHProgrammer, because, quite frankly, I don't like the language, but I'm good enough to write fairly robust, secure, and performant backends.

I just hold my nose, write my backend, then get back to my frontend, as soon as possible.

reply
rty32
1 day ago
[-]
Which part is condescending? Maybe spell that out?

From what I can see it's some pretty unbiased conclusion that's quite reflective of the truth.

reply
littlestymaar
2 days ago
[-]
I find it pretty fascinating that what used to be a beginner-friendly language, with limited capabilities but that is very easy to get started with, has now evolve to a bloated monster full of advanced features that you can't expect to know entirely, with a complex framework and tooling ecosystem to support it.

PHP lovers generally don't like acknowledge that, but the PHP we've learned back-end development two decades ago is no more and that it's now as beginner unfriendly as Java was when we picked it.

It's a pity because there's nothing as beginner-friendly anymore. I think the blame is on people calling themselves “PHP developers” who never bothered learning more advanced languages after PHP and instead pushed PHP to reach parity with those, at the expanse of losing its soul.

reply
ceejayoz
1 day ago
[-]
You can still write the old PHP4 way in virtually all cases. <?php echo('hello world'); ?> works fine.

I've done so periodically, and every time I go "this sucks, gimme the tooling".

reply
littlestymaar
1 day ago
[-]
Sure, and I'm still using PHP every once in a while for personal needs (I have a handful of small personal websites built this way: PHP has this insanely cool capability of being just a scripting language for a basic dynamic website).

What's sad is that it's not how people use and teach PHP today.

PHP's magic really is that you can write small scripts super easily to do small tasks, but somehow most PHP developers insist that “no PHP isn't for building small scripts” but “a real, professional back end language ready for mission critical enterprise requirements blah blah blah”, because surely that make them sound more serious as programmers, missing the point entirely…

(And sorry to all insecure PHP programmers out there, but for serious stuff using PHP is still equivalent to coding with handcuffs and you should really learn a second programming language at last because being a one trick poney really isn't as cool as you think it is).

reply
leetnewb
1 day ago
[-]
I picked up php a couple of months back after 30 years of ignoring it, mostly after reading a comment somewhere about using php for shell scripting. Very easy to read the language documentation on php.net and get moving. Powerful standard library. I haven't found another language (not an exhaustive claim) that offers language documentation as helpful as php's for a beginner.
reply
NackerHughes
1 day ago
[-]
PHP is still definitely a beginner-friendly language that is still very easy to get started with. Setup is as trivial as it always has been, copy a .php file onto a server and you’re good to go. No complicated frameworks or “deployment process” needed if you don’t want them (and most people don’t need them).

The difference between it and Java is you’re not forced into the ClassObjectGetterSetterPropertyHookFactoryBean paradigm with PHP. You can continue to write concise, simple, elegant scripts that read from top to bottom and serve one page and serve it well. You don’t have to use any of these crazy newfangled features - I, for one, will be using none of them, and will be sticking to my if-else blocks and nested for loops that will be easy to read and grok when I (or someone else!) come back to the code two months down the line.

reply
immibis
1 day ago
[-]
Java doesn't force you into that paradigm either. Well, most of it. Your code is still contained within a method within a class.

If you write JSP, you don't even need that.

reply
littlestymaar
1 day ago
[-]
I still do, every once in a while when I'm using PHP for my personal websites, but it's been a very long time since I've updated the (very basic) dependencies I'm using since they all migrated to the “enterprise-grade tooling of the day” after 2010 or something.

While PHP can still be uses like that today (and is still unmatched in terms of ease of use for simple stuff when used like that) it's been a long time since the PHP project and developer community stopped caring about this use-case.

reply
nneonneo
2 days ago
[-]
If you want any evidence that terrible language design is alive and well in PHP, look no further than the new array_find function.

Not only is it yet another global function in a namespace already chock full of random array helpers, it is extremely similar in both name and usage to array_search - a global function since PHP 4. Except, of course, that in typical PHP fashion, array_find’s argument order is ($array, $filter_callback) while the older array_search is ($search_value, $array).

There are literally hundreds of hits for existing, global, functions named array_find. If these are loaded from a library, they will break uses of the new built-in function in exciting ways. Yet, even with this mentioned in the RFC (https://wiki.php.net/rfc/array_find) it seems to have been no obstacle whatsoever to its inclusion - despite the fact that the implementation is literally three lines of code.

I have to question if the benefits of this global function really outweigh the benefits. PHP devs claim that other languages have these functions so PHP should too - but neglect to note that most languages don’t make them global functions (rather, they’re usually array methods or in some utility module).

reply
mklepaczewski
1 day ago
[-]
Your IDE should help you with the argument order if that's an issue for you. It has never been a problem for me and I don't understand the argument. I get that it might be confusing the few first times you use these functions, but if you use them every day you just remember the argument order.

The backward compatibility section found only 200-ish projects where array_find() was defined in global name space. For me that's a small price to pay for introducing the new function, and refactoring should BE easy when upgrading a project to PHP 8.4.

Adding array_find() to a namespace would be inconsistent. All other array_*() functions are global.

reply
xigoi
1 day ago
[-]
An IDE can help you write the code, but does not make it easier to read the code.
reply
mklepaczewski
1 day ago
[-]
Can you elaborate? I'm not sure what you mean, but IDEs definitely make reading code easier. IDE does code formatting, highlighting, argument hints, jumping to methods, declarations, and various hover effects on variables, methods, and classes. Some IDEs offer call graphs and other more advanced tools. Not to mention static analysis that works out of the box in PHPStorm (and I'm sure it can be set up in VSCode).
reply
xigoi
1 day ago
[-]
I mean that no matter what you do, the arguments will always be shown in an inconsistent order and you’ll have to mentally swap them around. You probably could configure your editor to visually swap them, but that sounds like a really bad idea.
reply
mklepaczewski
1 day ago
[-]
If the argument order is a problem for you, you can use named arguments.
reply
nedt
1 day ago
[-]
array_search() has the same needle, haystack order as in_array() or array_key_exists(). array_find() has a callback and takes the same order as array_walk() or array_filter(). It's just array_map() that's different, but that's because it can take multiple arrays. And writing your own function with a prefix already used by PHP in the global namespace is just not a very good idea.
reply
bwoebi
1 day ago
[-]
array_find parameter ordering is modeled after other non-variadic array functions, e.g. array_filter also having ($array, $callback) order.

But I agree, there is already some inconsistency, and when adding a new function you have to choose which function to make it consistent and which one to make it inconsistent with.

reply
kyleee
2 days ago
[-]
I had similar thoughts, but do appreciate the additional mb_ functions bringing multi byte support to some remaining functions.

Also people should be coding defensively with things like “if not defined” when implementing their own global helper functions (or avoid doing that at all)

reply
williamdclt
2 days ago
[-]
"if not defined" doesn't help, if your own `array_find` doesn't have the same signature and semantics than the new global then you're screwed. You'd want the opposite: overwrite it if it already exists in the global scope (dunno if that's easy / how that'd work in PHP)
reply
nodogoto
2 days ago
[-]
You can't redefine functions in PHP.
reply
mklepaczewski
1 day ago
[-]
There are extensions which allow you to redefine even constants.
reply
someothherguyy
1 day ago
[-]
> `array_find` doesn't have the same signature and semantics than the new global then you're screwed

Screwed? Just rename or move the function to a namespace in an IDE and it will update all your references?

reply
asddubs
1 day ago
[-]
the answer is using a namespace
reply
theodorejb
2 days ago
[-]
Property hooks are the headline feature, but they seem like something I'd rarely use in practice. It is nice to have the option available though, in case I need to add extra logic to a property without breaking everywhere that it's accessed.
reply
IluTov
2 days ago
[-]
> A primary use case for hooks is actually to not use them, but retain the ability to do so in the future, should it become necessary.

My personal motivation was always to finally put an end to the getters/setters boilerplate.

reply
inglor_cz
2 days ago
[-]
I have a question to the PHP-in-production crowd: how long do you wait before migrating to higher version of PHP? Is the first release usually already fine, or is it better to wait for a few months and let someone else catch the early errors?
reply
kugelblitz
2 days ago
[-]
Solo Dev on my own PHP project since 14 years.

I wait 1-3 months, but then update. It used to take way longer, because Amazon's Elastic Beanstalk platform would take longer to update, but I've now changed to Platform.sh and the transition should be easier.

It has been very backward-compatible (i.e. stuff that works in 8.n also works in 8.n+1; and unless you use exotic functions or are relying on special functionality, it should work for you, too).

Once I'm at 8.4, I would slowly update the code / syntax with rector and the assistance of phpstan.

For framework updates I wait 1-2 patch versions before updating, because of composer dependency problems and sometimes bugs do still find themselves into new releases (e.g. I would wait at least until Symfony 7.2.1 before upgrading from Symfony 7.1.x).

reply
edhelas
2 days ago
[-]
Basically I follow Debian Stable releases and migrate all my code to it when a new version is pushed. So so far I'm on 8.2.

It also often fit with the current Laravel version (11).

reply
jspaetzel
2 days ago
[-]
I usually wait 6mo to a year in order for composer dependencies I use to get updated. Then its usually a trivial upgrade. I've upgraded sooner before for simpler projects though and things are usually pretty stable upon release.
reply
bawolff
2 days ago
[-]
Wikipedia is still on php 7.4.33 so don't feel too bad if you are behind.
reply
inglor_cz
2 days ago
[-]
8.2 and 8.3, respectively.

I enjoy the PHP 8 new features such as named arguments, constructor arguments promotion and nullsafe operators. Made my new code a lot more readable.

I am not that sure about 8.4 yet, though the new array_ functions and new DOM look interesting.

reply
Cthulhu_
2 days ago
[-]
For a project like Wikipedia, stability and continuity are far more important than latest and greatest feature support; in fact, there's an argument to be made to avoid newer language features to ensure consistency, that is, if new features are used, they should be used everywhere at once. Else you end up with frankenstein code where every file could use a different style.
reply
EasyMark
23 hours ago
[-]
For most projects outside of hobby projects, I feel this should be the default case, unless there are just some huge costs savings like “improved performance by 50% and now you can save money and scale down your AWS allocations!”
reply
inglor_cz
2 days ago
[-]
"Else you end up with frankenstein code where every file could use a different style."

Yeah, this is a huge problem, but also, in the long run, inevitable.

Plenty of Kernighan & Ritchie C code still out there...

reply
wbl
1 day ago
[-]
Almost none: ANSI was over 30 years ago and enough of an improvement people switched. If you mean C89 then yes, loads of it.
reply
skissane
1 day ago
[-]
It helps there are automated tools for converting old style K&R function declarations to the new ANSI/ISO style, like protoize.

But K&R C is now so dated, protoize was removed from GCC 4.5 and onwards. When (in a bout of idiosyncrasy) I wanted to convert some ancient K&R C to new style a couple of years back, I ended up putting GCC 4.4 in a Docker container to make it easier: https://github.com/skissane/protoize

reply
Dachande663
2 days ago
[-]
The last few point releases have been very stable, so normally within a week or so. Obviously this relies on having a pretty good test suite (we run ~8,000 tests in ~60 seconds so not too bad for us).
reply
pilif
2 days ago
[-]
We start making sure our application runs on the next version around the time Beta 1 comes out.

We upgrade the development environment around the time when our tooling (phpstan, cs-fixer) runs on the next version, but doesn't necessarily support new language features.

We upgrade the production environment when our tooling supports most of the new language features and at least all of the ones we want to make use of.

This usually happens within 3-6 months of the release. By that time the version has stabilized enough to be safe for production use.

reply
DaiPlusPlus
2 days ago
[-]
> how long do you wait before migrating to higher version of PHP?

I still have a PHP5 project that somehow still runs.

reply
gog
1 day ago
[-]
Usually the release is fine, but dependencies can be lacking in proper support/testing of the newer versions, so it takes a couple of months.

Also external tooling, like for example NewRelic extension, takes some time to release a version that supports the new release.

reply
TimWolla
2 days ago
[-]
For PHP 8.3, we upgraded production during the RC phase, but were prepared to revert back to an older one by not relying on the new functionality. Docker makes this easy.

As long as you do not use the new functionality, I'd claim that a new PHP version is no less stable than an older one. And on a contrary you would be missing out on some bugfixes that were deemed too risky to apply to an existing version.

Disclosure: I've got a commit-bit for PHP, so we had in-house expertise to diagnose issues ourselves.

reply
stronglikedan
2 days ago
[-]
I wait until I need a new feature, or if there's a security issue. I still have PHP 5 apps in production.
reply
crowcroft
2 days ago
[-]
Didn't PHP 5 stop getting security updates more six or seven years ago?

I guess depending on the app that might not really matter, but that seems like it could be an issue at some point.

reply
giraffe_lady
2 days ago
[-]
There's an entire ecosystem of companies doing support and proprietary security patches and even framework-bearing polyfills for php 5. So much of the web runs on php 5 that is never ever going to be updated. It's a mini-industry unto itself.

The licensing is on the order of thousands or low tens of thousands per year. Worth it for a 40-person business that has a 20-year-old legacy codebase supporting a few million dollars a year revenue. It's not what we think of as a standard "tech" company but it describes an absolutely ridiculous number of businesses.

reply
eamann
2 days ago
[-]
I'm just waiting for the official PHP Docker images to bump their updates ... which should be any time now.
reply
artificialLimbs
2 days ago
[-]
We’re still on 7.4 at my mid co. =|
reply
dubcanada
2 days ago
[-]
I wait one version, I’ll upgrade to 8.3 now and 8.4 when 8.5 is out.
reply
ransom1538
1 day ago
[-]
We leave it on staging for about 4 months, scan logs etc. If there is no complaints from qa or devs we roll it out.
reply
PaulHoule
2 days ago
[-]
That “public private(set)” boggles my mind. Why not “readonly public”?
reply
bwoebi
1 day ago
[-]
readonly is rather a misnomer for "writeonce" in PHP. And as such it also disallows repeated assignment in class scope, while private(set) has no such restriction.
reply
wvenable
2 days ago
[-]
Readonly might have different semantics (as it does in C#).

Readonly has been discussed but it wasn't part of the property hooks RFC and is a separate issue/feature. This is just a natural consequence of having private setters.

reply
klaussilveira
1 day ago
[-]
reply
arkh
1 day ago
[-]
> Object API for BCMath

Really good thing when doing some operations on monetary values. No need to use bc_* functions anymore it seems.

reply
shikck200
1 day ago
[-]
Looks like PHP is going even further towards Java. I really loath getters/setters with passion. I really wish PHP instead focused on getting some sort of concurrency builtin and proper unicode string literals. That should be the main focus, instead of copying various features from Java.
reply
9dev
1 day ago
[-]
Look at it this way: getters/setters are the only conceivable way Laravel could ever get something like static analysability, and I wouldn’t call that framework particularly Javaian. What they do is make a whole sleuth of magic code actually discoverable and understandable, but you’ll never have to use them if you don’t want to. And even if a library under the hood implements a getter, all you’ll see of that is $foo->bar. There really have been both more invasive and more Java-style features in the past than this one.
reply
shikck200
1 day ago
[-]
I really dont want to access a property and have it do any sort of magic behind the scenes. This is just bad. Now a property lookup could do some IO, or even throw an exception. PHP should not aim to please the framework of the month, but it in fact seems like Laravel lobbied this into PHP core.

> but you’ll never have to use them

But i do. I now cant tell if im accessing a property or a getter. With custom functions (like getFoo()) it was annoying, but still obvious, now its just magic and library authors will 100% start to abuse this feature allover.

reply
9dev
1 day ago
[-]
> I now cant tell if im accessing a property or a getter.

But you never could have been sure for the last 20-ish years either? What if my library you're using (and you can be certain at least one of them does) includes a class like this:

  class Foo
  {
      public function __get($prop) {
          return match ($prop) {
              'bar' => $this->doSomeHeaveIoOp(),
              'baz' => query_db()
              default => throw new RuntimeError('Invalid property ' . $prop)
          };
      }
  }
The difference to a proper getter is that you never knew Foo supported the virtual properties "bar" and "baz"; the only chance you'd have was if I added doc comments, or a note in the documentation; otherwise, good luck finding it in the source code. Compare to:

  class Foo
  {
      public string $bar
      {
          get => $this->doSomeHeaveIoOp();
      }

      public string $baz
      {
          get => query_db();
      }
  }
This is definitely better. It is discoverable by both you and your IDE; it allows proper documentation; it is not magic, but code; it won't go out of sync with the __call handler; it allows static analysis and typing.

> I really dont want to access a property and have it do any sort of magic behind the scenes. This is just bad. Now a property lookup could do some IO, or even throw an exception. PHP should not aim to please the framework of the month, but it in fact seems like Laravel lobbied this into PHP core.

Without any kind of property overloading, you're missing out on a lot of API simplification that other languages have long taken for granted. You may not like it, by stuff like pandas in Python wouldn't be possible at all without heavy overloading, and I prefer a world with pandas over one without it. Ergonomics are important; not writing tons of useless boilerplate code is, too.

reply
shikck200
1 day ago
[-]
Its obvious that this has been possible before. It always was bad practice to do so, no matter of the language. I for see people starting returning `$this` and having these really complex chains of getters. Its going to turn into even more spaghetti, because now there is two syntaxes for basically doing the same thing. It seems simplicity is just something everyone wants to abandon.
reply
Timon3
1 day ago
[-]
> It seems simplicity is just something everyone wants to abandon.

I think this very much depends on your perspective. "Simplicity" isn't a single dimension, you'll always face trade-offs at some point.

While the language did get slightly more complicated with the introduction of property hooks, they also simplify a lot of real-world code. Instead of handling all getter/setter logic inside two big functions, there's now a direct relation between each property and its getter/setter logic. There's a lot of value in that!

Of course you can say that's not good practice and therefore shouldn't be made simpler, but then you're still offloading complexity onto the individual program and developer. They are using these features in production code, and keeping the language simpler means that every class using getters/setters has its own custom logic. That's not simple at all!

To give a real-world example, Typescript supports many things that probably wouldn't be necessary if the language were designed from the ground up. But it's meant to add type safety to Javascript, so it has to support adding types to patterns that aren't best practice. But this also simplifies adding types to the existing ecosystem by a large margin, which is arguably the reason it has become the de-facto best practice for writing frontend apps.

reply
cannibalXxx
1 day ago
[-]
even though it's a much criticized language I still build my applications using it. for example the site https://chat-to.dev was written entirely in php
reply
trevor-e
2 days ago
[-]
The property access is looking a lot like Swift, particularly the `private(set)` part which I haven't seen in many other languages.
reply
nilslindemann
1 day ago
[-]
Non PHP expert here, can someone explain to me the line

get => \sprintf("%s_%s", $this->languageCode, $this->countryCode);

in the first code example? Is it a lambda?

reply
tored
1 day ago
[-]
Yes, you can read about it the rfc under "Abbreviated syntax"

https://wiki.php.net/rfc/property-hooks

It follows the syntax of arrow functions

https://www.php.net/manual/en/functions.arrow.php

reply
nilslindemann
1 day ago
[-]
Ahhh, and the backslash is the global namespace, as I just figured out: https://stackoverflow.com/questions/4790020/what-does-a-back...
reply
justinclift
1 day ago
[-]
Did they skip 8.4.0 and just go to 8.4.1 directly?
reply
ainiriand
1 day ago
[-]
No, they made 8.4.0 2 days ago and fixed it before the offcial release:

https://php.watch/versions/8.4/releases/8.4.0

reply
KRAKRISMOTT
2 days ago
[-]
Are there any solid PHP WebSockets and WebRTC setups outside of Laravel?
reply
kyleee
2 days ago
[-]
Symfony? Or is this a case where Laravel has actually built out their own packages for support in these two instances?
reply
josephscott
1 day ago
[-]
reply
hipadev23
2 days ago
[-]
swoole makes websockets extremely easy and fast.

webRTC is a beast with the STUN server needs better handled elsewhere.

reply
radicalriddler
1 day ago
[-]
The new Dom stuff looks really cool. I had to work with the previous functions a couple months ago and it was terrible. New API looks nice.
reply
cute_boi
2 days ago
[-]
I can see PHP is getting too much complex.
reply
wvenable
2 days ago
[-]
You trade complexity in source code for complexity in language. For example, property hooks will make code that currently uses other methods to accomplish that task much easier to read and write.
reply
vfclists
2 days ago
[-]
For how many years will it get support, security and bug fixes?
reply
philipwhiuk
2 days ago
[-]
Support: 31 Dec 2026

Security: 31 Dec 2028

Bug Fixes: 31 Dec 2026

From https://www.php.net/supported-versions.php

reply
nedt
1 day ago
[-]
If needed you can get LTS from Zend. They still offer security fixes for 7.2 until end of 2026 and 8.3 is supported until end of 2029. But that's just if upgrading every second or third year is too expensive to you.
reply
chx
1 day ago
[-]
Zend offerings are confusing. https://www.zend.com/services/php-long-term-support only lists 8.0 and earlier, https://www.zend.com/products/zendphp-enterprise does have a chart showing 8.3 into 2029 but once again the text only mentions 8.0. What gives?
reply
chx
2 days ago
[-]
oooo

variable-length lookbehind assertions are now supported.

yay! I needed that so many times.

reply
bwoebi
1 day ago
[-]
While variable-length lookbehind is surely more comfortable to work with, I found clever usage of \K to be largely sufficient in most cases.

But I agree, a great feature!

reply
that_guy_iain
1 day ago
[-]
The breaking changes section doesn’t even mention they changed error handling in methods that haven’t been change for 20 years.
reply
TheRealPomax
1 day ago
[-]
Standards compliance for HTML is huge. Hopefully everyone switches to it ASAP.
reply
dmsnell
1 day ago
[-]
DOM\HTMLDocument is a huge boon. Niels Dosche incorporated lexbor into PHP to do so, and it maintains the same interface as DOMDocument once it’s instantiated.

In case people aren’t aware, DOMDocument is dangerous. You can’t parse HTML with an XML parser; so everyone currently using DOMDocument for HTML would benefit by replacing that with DOM\HTMLDocument immediately, eliminating both security and corruption issues.

Have you tried using an HTML parser?

reply
anttihaapala
2 days ago
[-]
Oftentimes many of the significant new PHP features are to fix the shortsighted implementation in the previous ones - for example this method chaining with `new` - there was precedent already, C++ got it right well before PHP even existed and with the very same arrow operator that PHP borrowed (and so did Java and JavaScript with .), so the question is why did PHP have to get it wrong at first and for so long.

Another pet peeve of me is that the global namespace is littered with these utility functions that should be easily composable or maybe be methods on the objects themselves - and looks like PHP 8.4 adds four more `array_*` functions. For comparison, Python's builtin namespace has a total of 71 functions and a couple of exception classes. PHP's builtin namespace has more functions for dealing with arrays and now 58 of those are prefixed with `array_`.

reply
dubcanada
2 days ago
[-]
The global namespace change would break everything. It’s unlikely they would ever do something like that.

It’s hard to build on a language used by so many, when you can’t modify the base. Python decided to do 2.7 vs 3 and fragmented the eco system terribly.

reply
nneonneo
2 days ago
[-]
They could help by not adding any more cruft to the global namespace.

Adding any globals should be a carefully-considered change. User-defined functions are global by default, and although there are (now) much better ways to write PHP libraries, I can absolutely see some old library defining array_find (one of the new global functions in 8.4) in an incompatible way and breaking new code that attempts to use the built-in function.

Sure, you can’t touch the existing pile of globals, but at least stop pouring fuel on that particular fire…

reply
chx
2 days ago
[-]
That would be some really old library. Already in 2012 when Composer was released there was PSR-0 and today almost all libraries are Composer managed and using a namespace following PSR-4 which itself is ten years old. A library that old would almost surely not run on PHP 8 unchanged anyways.

Surrendering the global namespace to the language is not so bad an idea.

reply
nneonneo
2 days ago
[-]
Suppose I want to add some new code to an old website? Or I want to gradually upgrade an ancient code base - twelve years is not so old for PHP, when ancient frameworks like Wordpress are still alive and kicking.
reply
chx
2 days ago
[-]
If we hitched language development on Wordpress we would still be on PHP4 as they refused to join gophp5 some seventeen years ago.

Again, an ancient enough codebase which contains a library using array_find will need enough upgrades to run on PHP8 much less PHP8.4 the change from array_find to something else is the least of your worries.

reply
nneonneo
2 days ago
[-]
Seriously? 2k results for array_find in PHP on GitHub: https://github.com/search?q=array_find++language%3APHP&type=.... RFC authors (https://wiki.php.net/rfc/array_find) explicitly noted over 600 hits for definitions of array_find, around 30% of which are not false positives - that is, there's a good possibility that there are 200+ implementations of global array_find in just open-source projects.

First page hits https://github.com/hawind/gdoo/blob/master/app/Support/helpe..., a PHP app last updated just two years ago (140 stars, 63 forks) which only supports PHP 8.x. Implementation is thoroughly incompatible with 8.4's array_find.

There are so many more examples. Lots of the hits are from codebases that have seen updates in the last few years. Many more are plugins or other addons for PHP frameworks or apps which are still widely used (WordPress, phpBB, etc.).

reply
alganet
2 days ago
[-]
The example you picked:

https://github.com/hawind/gdoo/blob/master/app/Support/helpe...

Is namespaced. You need to realize that \array_find is different from \Illuminate\Support\Arr\array_find.

There is zero chance of collision here. Totally compatible.

reply
nneonneo
1 day ago
[-]
IIUC the `use` declaration is including the target namespace (https://laravel.com/api/8.x/Illuminate/Support/Arr.html) in the current scope, not declaring a namespace itself. If you wanted to create a namespace you need the `namespace` declaration, which this file lacks. `helpers.php` is directly included by both `index.php` and `artisan` and the functions are thereby in the global scope of the entire app.

In any case, it wouldn't make sense for that file to be namespaced under Illuminate\Support\Arr, as most of those functions have nothing to do with arrays.

reply
alganet
1 day ago
[-]
Fair enough, you're right!

Anyway, it _could_ have been namespaced. It _should_ have been namespaced. I'm sad for the app author, but he should have seen that coming. His app was developed well after namespaces were introduced.

You're making impossible demands. PHP has chosen to be backwards compatible _to a certain point in the past_, and it is generous in what it decides to keep working.

To expect that 8.4 will care about not breaking some code that was written with 5.2 style is unrealistic.

You're making a time travel judgement. You're saying that PHP should have renamed everything back then to categorized namespaces and broken compatibility _way_ earlier, which is actually a much worse break than the break that actually happened.

reply
nneonneo
1 day ago
[-]
8.4 is not even backwards compatible with perfectly working code written to target 8.x. It doesn't materially matter that the code is written in "5.2" style if it was meant to run on only 8.x. Even that style point is arguable. The author uses Composer! And Laravel! And mostly does use namespaces, outside of a few useful helper functions that are reasonably global so they don't keep needing to import them or use namespace prefixes.
reply
alganet
1 day ago
[-]
What you are saying makes no sense.

"The author uses Composer! And Laravel"

So what? Can you explain what this means in this context?

To me, it looks like you're defending shitty code just to be able to attack PHP.

reply
9dev
1 day ago
[-]
Then you use your IDEs refactoring feature to rename your version of the function, or put it into a namespace, and you’re done in about 12 seconds.
reply
imoverclocked
2 days ago
[-]
I think the bigger issue is that these lessons have already been learned. However, PHP (Personal Home Page) was not created carefully by someone to become a fully fledged language. It grew into that role organically which is why it has so many warts in hindsight.
reply
sam_goody
2 days ago
[-]
I don't get your issue with builtin utilities.

The design philosophy of PHP is to include whatever common methods would otherwise be in a popular library. (PHP actually began more as a library than as a language.) This differs from, eg, Python, but doesn't hurt.

The decision not not to make methods on the objects, but to include everything in the main namespace (so array_walk instead of Array.walk or Array()->walk etc) is another function of the same philosophy. It may not fit your idea of cosmetics, but there is nothing wrong with it.

On the other hand, I would love if PhP gained chainability ([].array_map.array_find()) and then the names would be a pain. If that ever happens there are solutions.

reply
askonomm
2 days ago
[-]
There is a RFC on it (https://wiki.php.net/rfc/function-composition) which I'd love if it made it through. Until then Crell's FP library is a good option (https://github.com/Crell/fp).
reply
lofaszvanitt
2 days ago
[-]
Whats the problem with global namespace littered with utility functions. Do they get in the way? They hurt you? They whisper in your ear? Or with the badly named functions? Or the type juggling? Do they eat your soul?
reply
rty32
2 days ago
[-]
It could be much easier for user defined functions to collide with standard functions, especially when it happens unintentionally.

Someone else creates a function named array_something in the namespace. Maybe it already exists in earlier versions, maybe it happens to collide with one of the four introduced in 8.4. This function is accessible to you in the current scope. Now, you try to call the function like the way it is defined in the standard library. You get a very confusing error and spend 10 minutes trying to figure if it is you or PHP that is hallucinating. Turns out you have been inadvertently calling that other user defined function. The other user may be completely unaware of the fact that they created a function with naming collision.

To combat this, you need strong IDE help including static type checking, which is not always there for everybody. And it still doesn't help with cases where the user defined function collides with a new standard function.

Most "modern" languages have very few built-in functions in the global namespace. Another example is Go. Correct me if I am wrong, but I believe there is 0 function in global namespace in Rust. println! exists but that's a macro. In other words, the example I mentioned just never happens with these languages.

Not to mention the long list of junk you see in IDE when you type "array_".

I guess you haven't written much MATLAB.

reply
nneonneo
2 days ago
[-]
Rust namespaces everything in the standard library to std:: or core::, and has a clear distinction between them.

However, it does implicitly include the entirety of the std::prelude namespace (https://doc.rust-lang.org/std/prelude/index.html) into every source file, as well as including every macro directly exported under std:: (including println!). This enables the unprefixed use of things like Result, Option, Some, Send, etc.

The prelude and std:: macros are the closest thing that Rust has to a global namespace, and even they can be disabled in crates that specifically request it.

reply
alganet
2 days ago
[-]
This would be a valid point 20 years ago.

PHP functions can be namespaced. I can just write myLib\array_find, otherLib\array_find. You choose what implementation you want when importing. IDE will pick the correct one.

So, zero chances of collision.

reply
rty32
1 day ago
[-]
Read my comment and all previous comments again.

Don't write such meaningless words and waste your and other people's time when you don't even understand what people are talking about.

reply
alganet
1 day ago
[-]
Your previous comment makes little sense and your reply is just angry and explains nothing.

A tool to avoid collision was introduced decades ago. This tool was made proeminent by the language and the ecosystem (PHP-FIG, frameworks, books, popular PHP celebrities).

You literally have to had stopped programming PHP more than a decade ago to not understand namespaced functions.

https://phptherightway.com/#namespaces

This problem of collision was seen miles ahead, and people were gently introduced to the idea that the global namespace belongs to PHP builtins and you should not pollute it even further.

I would say it is consensus for the PHP community that if your code broke because you defined array_filter globally before 8.4, then your code sucks and you don't know PHP.

reply
immibis
1 day ago
[-]
What is the practical difference between a prefix and a namespace?
reply
mg
2 days ago
[-]
These days, I am super torn about what language to use for new web projects.

PHP:

    - Easy to deploy: Upload files, done.
    - Easy to develop: Reload page, see changes.
    - Lots of HTTP tooling built in.
    - Fast.
Python:

    - Great language.
    - Great code reuse system: Modules.
    - Nice framework: Django.
    - Less breaking changes in recent years.
reply
cess11
2 days ago
[-]
PHP has a rather nice type system. It also doesn't use whitespace as syntax, which makes it much easier to generate ad hoc.

Slim is a pretty nice framework: https://www.slimframework.com/

reply
shikck200
1 day ago
[-]
Does anyone really FTP files like its 2003? Even in PHP you deploy with some sort of tool, like docker etc. The reload page thing is pretty much solved in all languages with a watcher. entr is a universal one, thats written in C and fast as anything.

The thing (most) other languages have is unicode support and concurrency. In PHP there is basically none of these.

Fast? You mean fast as in CPU bound tasks? 99.99% of PHP code is slow because of IO, and without any concurrency all the other languages beat PHP easily. If you need CPU bound work, you would not pick PHP (or any other scripting language) anyway.

In most benchmarks PHP (with Laravel/Symfony) is barely doing 500req/sec. Compare this to languages in the same space (like nodejs/python) and they run the same program and can serve 10K-30K req/sec.

Having said that python (a slow langauge) is still capable of doing heavy CPU bound tasks with libraries like numpy. Im not aware if PHP can install C dependencies with composer, like you can with pip.

reply
Implicated
1 day ago
[-]
reply
shikck200
1 day ago
[-]
Seems like that requires some sort of ad-hoc PHP extension. These are not in the standard PHP distribution? I would not want to rely on some random PHP extension that maintained by a single guy for anything production grade. Compare that to something like tensorflow thats backed by a HUGE community of maintainers.
reply
Kiro
1 day ago
[-]
Link those benchmarks please. Both 500 and 10k-30k seem extremely low.
reply
shikck200
13 hours ago
[-]
That was a ballpark estimation, and while pure req/sec is usually irrelevant, it still comes in when the load starts to increase and you need to squeeze every last drop of perf.

PHP usually is doing poorly, even with its "cache", and when you realize that PHP devs actually are not PHP devs, but framework (like laravel/symfony) devs you need to account for the overhead of the framework too.

But you can have a look at the framework benchmarks game:

https://www.techempower.com/benchmarks/#section=data-r21&hw=...

reply
igouy
51 minutes ago
[-]
I think they'd prefer not to be confused with the benchmarks game ;-)

https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

reply
notpushkin
2 days ago
[-]
> Reload page, see changes.

This should work in Python, too. With Django, I think you need to use https://pypi.org/project/django-browser-reload/, and rith most other frameworks / WSGI servers just try adding --reload flag.

Edit: Django should wor out of rhe box actually – that package is for refreshing the page in browser.

> Easy to deploy. Upload files, done.

I can see the appeal, but generally you’d want to avoid that (for anything other than quick prototypes, maybe). Set up a CI, push to deploy. This goes for modern PHP as well.

If you want something simple to deploy webapps and know a little Docker, I’ve built a deployment tool you can run on your own VPS: https://lunni.dev/. (Feel free to reach out if you need any help!)

reply
mg
2 days ago
[-]
There are of course ways to get "reload page, see results" to work even with Python. After all, computers are touring complete.

But in PHP you have it out of the box. Faster, with less complexity and less resource consumption. And you can use the same setup in development as you can use in production.

reply
notpushkin
2 days ago
[-]
Maybe I'm missing something, but PHP is not more efficient in that regard.

When you load a Python page, it is served by an in-memory process. If code is updated, the process is restarted, parsing the code and initialising the application, but it is done only once.

When you load a PHP page, it parses the code and initializes the app for each request. It then tears everything down after the request. There are less wasteful ways (most recent are app servers, just like in Python or other langs), but I'm not sure if those are widely used in local development. Even then, it’s same as Python, Node or pretty much anything else.

And of course, I’m not trying to diss on PHP here – it’s gotten pretty good recently. But reload on change is built in pretty much every app framework nowadays. It works out of the box and is negligibly fast. It’s not a good point to compare.

reply
graemep
2 days ago
[-]
> When you load a PHP page, it parses the code and initializes the app for each request. It then tears everything down after the request. There are less wasteful ways (most recent are app servers, just like in Python or other langs), but I'm not sure if those are widely used in local development.

There are things like opcode caches that make PHP more efficient transparently, while still feeling to the developer like a reload each time.

There are reliability and development advantages to starting each request from scratch. NO leaks, no state you need worry about.

PHP is very much like serverless.

reply
mg
2 days ago
[-]
In my experience:

PHP is always blazing fast, with no additional setup to make "Reload page, see results" work.

Python needs additional setup. Either by monitoring the filesystem and pessimistically recompiling the application every time a file changes. Causing resource consumption every time you hit save in your editor. Or by having the web workers that serve the requests die after 1s of inactivity or so. Which makes the next pageview slow again, even if no code changed.

I think PHP's advantage is because of 3 things:

1: Recompiling changed files is built in.

2: With PHP you can set your project up in a way that only the code necessary to answer a single request is updated. With Python and Django, all the code for all requests is updated and even code paths that are actually never used.

3: PHP keeps each file compiled to bytecode in memory and only recompiles files that have been changed. Although you might accomplish something similar in Python if you let it pollute your filesystem with cached bytecode files.

reply
mobilio
2 days ago
[-]
This is true when you call PHP using CGI or CLI. Then opcode is build, running and thrown away.

But when u are using FCGI or PHP-FPM then you have running process where opcode is cached except on first request where opcode cache is build.

reply
hipadev23
2 days ago
[-]
With standard opcaching and jit enabled, the reparsing step doesn’t happen.

Initializes for each request is standard with php-fpm, but swoole/workerman/etc are rapidly gaining popularity and run as a more typical app server with coroutines.

reply
aedis
2 days ago
[-]
Don't forget Laravel for PHP.
reply
mg
2 days ago
[-]
To get to know Laravel, I forced myself to build a project with it for a few weeks and I did not like it.

I found myself getting sucked in into a complex project structure and dealing with all kinds of strangeness like "artisan commands", "the autoload cache" etc.

With Django, I can build a web application in a single file that has "import django" on top and take it from there:

https://news.ycombinator.com/item?id=40788329

reply
conradfr
2 days ago
[-]
reply
jonwinstanley
2 days ago
[-]
Laravel is excellent for building a website, for smaller projects there are simpler tools and frameworks
reply
ognarb
2 days ago
[-]
I much prefer Symfony, but that's mainly because it's the framework I started with.
reply
bojan
1 day ago
[-]
I was forced to move from Symfony to Laravel and I really dislike it. This experience seems to be very common.
reply
donperignon
1 day ago
[-]
It’s difficult for me to trust a framework backed by venture capital (https://blog.laravel.com/accel-invests-57m-into-laravel). There are too many incentives to prioritize making money, which makes it easy to overlook developer experience. I rather use Symfony instead.
reply
esskay
1 day ago
[-]
Symfony took venture capital years ago, it's no different really: https://www.sourceguardian.com/blog-symfony-gets-boost-from-...
reply
orangepanda
2 days ago
[-]
I had hoped to forget
reply
BafS
2 days ago
[-]
You don't like magic? /s
reply
jayflux
2 days ago
[-]
> Easy to deploy: Upload files, done

I know people love to say this, but does anyone realistically make websites or web apps that way? No, not really. Even with PHP there are frameworks, there is a package manager, there is version control, and there are deployment systems.

Pretending that PHP developers are uploading a .php file to a shared hosting server (like in 2002) to suit the narrative feels disingenuous to me as it doesn’t align with what I see PHP developers doing at all.

reply
wvenable
2 days ago
[-]
> I know people love to say this, but does anyone realistically make websites or web apps that way?

In PHP, I do. In other platforms, no. My personal PHP site is published by a git push to the server.

reply
handzhiev
1 day ago
[-]
I do it all the time, thank you very much. For a simple web app I don't even need a framework - you can literally create a simple files/folder structure, include files, include folders and get stuff done. An yeah, you can also upload the files by FTP. For something more complicated I'd use WP or Code Igniter depending on the specific project. And then you can again just SFTP those files to the server.
reply
9dev
1 day ago
[-]
That only works if your application has reasonably few users. Otherwise, your upload will result in some requests hitting a partially completed code base overwrite, that is, only some of your changes have been uploaded at request time, possibly leading to an error. This is a nice strategy for a hobby project, but it plain does not work for a business.
reply
handzhiev
1 day ago
[-]
That's not true. For mission-critical apps we route the traffic to the stable version while uploading the new version. This may be similar to what most CI tools do but it doesn't change the fact that we just upload the files and can do it as we see fit. Another good solution is to simply switch off a feature for maintenance while uploading it's files. If your software is well planned, that's a breeze and still keeps the whole process very simple.
reply
9dev
23 hours ago
[-]
Well, you’re shifting the goal posts. The original scenario was simply uploading files to the application folder on production servers and reloading the page.

Of course there are viable strategies to avoid this specific issue, but they all introduce complexity of themselves.

reply
alt227
2 days ago
[-]
>but does anyone realistically make websites or web apps that way?

You are correct in that a lot of PHP use now is larger frameworks with asset compilation and cache clearing etc, but even when developing on large systems like that it is nice to sometimes be able to just manually tweak a file and refresh.

For R&D and quick tests, just uploading a quick & dirty php file to the server is a very useful language feature to have IMO.

reply
jayflux
2 days ago
[-]
> For R&D and quick tests it is a very useful language feature to have IMO

Right, but unless you have an ftp server or quick ssh access and PHP isn’t doing any code caching that feature isn’t an advantage, how many developers are in that situation? Is this something you do?

If you’re running locally PHP spawns its own server which other runtimes have. If you’re running this on a server you’re most likely going to have app/code caching (apc Or opcache) switched on so you’ll need to restart the server anyway, in which case it’s not more advantageous than uploading a js file and restarting node.

reply
alt227
1 day ago
[-]
> Right, but unless you have an ftp server or quick ssh access

These days all of that is built right into IDEs

> Is this something you do?

Yes. After linking my IDE to a remote location I can then noodle around with scripts to test whatever. The immediate nature of PHP means the instant you hit ctrl-s your changes are live online.

> If you’re running this on a server you’re most likely going to have app/code caching (apc Or opcache) switched on so you’ll need to restart the server anyway

In prod yes, but in dev environments all that is switched off as its not needed.

reply
sjm-lbm
2 days ago
[-]
.. and as soon as you stop just uploading files (which, as you say, nobody does), a lot of the other advantages go away also. Laravel and Symphony both make PHP much slower. If you are going to have sane routing, you're probably going to need to tweak your websever to behave, well, less like a web server. There's a decent chance you'll need to clear a cache after you upload your changed files if you want to actually see those changes.

I actually like PHP a lot, and it's amazing how far it has come in the past 10 or so years, I just think way too many people assume you get the 2004-era PHP simplicity with all of the 2024-era PHP refinements, and you really don't. There's tradeoffs.

reply
jiehong
2 days ago
[-]
Python’s packaging and dependencies system is lacking, but trying to get better. But too many choices not always compatible nor working perfectly right (should you use pip, poetry or pipenv? Well, you see…)

How’s php’s?

reply
pluc
1 day ago
[-]
They just added extension support to packagist, so composer looks like a pretty healthy ecosystem that's officially supported.

https://thephp.foundation/blog/2024/11/19/pie-pre-release/

reply
BadBadJellyBean
2 days ago
[-]
> Python’s packaging and dependencies system is lacking

It is? I never had problems with poetry. Though I agree that there are mroe options than necessary.

reply
sigmonsays
2 days ago
[-]
That's a wild perspective.

Python has the worst packaging ecosystem i've ever seen

reply
taskforcegemini
2 days ago
[-]
worse than javascript?
reply
steve918
2 days ago
[-]
Python's packaging system is worse, but Javascripts packages / standard libraries are far worse than Python.

In python managing packages is a pain and there are too many package manager options, but for the most part there are good libraries, and chances are you don't even need one because the standard libraries are so good and mature.

In Javascript NPM is really all you need (even if yarn is a bit nicer), but you're gonna need to install 50 packages just to get a basic boiler plate app going and the quality of said packages is not always great.

reply
fbn79
1 day ago
[-]
Node: - easy to deploy: If you dont complicate yourself, with cpanel or plesk hosting is just matter of copy the files. - Terabytes of npm packages (even too much :)) - A non bloated and nice language (JavaScript) - Optional type checking with typescript if you want. - Non blocking IO
reply
JodieBenitez
2 days ago
[-]
> - Easy to deploy: Upload files, done.

Sure, it works for simple/less important cases. But it also means that your application code is inconsistent while the files are uploading.

Stop your service, upload the files, start the service: safer.

For a Django app you would upload files and ask Gunicorn to graceful reload... similar, just cleaner.

reply
lenlorijn
2 days ago
[-]
Most PHP apps use a deployment method where a symlink gets set to a directory with a new version of the code. Because of how opcache works this has no impact on running requests, while new requests get handled with the new code.
reply
JodieBenitez
2 days ago
[-]
Yes, my point really... it's really not "just upload files" like it's 1997.
reply
dizhn
1 day ago
[-]
That sounds pretty neat.
reply
kijin
2 days ago
[-]
You can use the same strategy with PHP. Preload all your scripts in opcache. Once you're done making changes, reset your opcache.

In practice, any serious project is likely to be version-controlled. Git pull is generally fast enough that it behaves like an atomic change. (By default, opcache will not reload a file that's less than 2 seconds old.)

reply
JodieBenitez
2 days ago
[-]
I'm pretty sure many PHP dev don't know about OPCache. Many of my colleagues don't know for sure. My point is "be aware of the state of your app code and what you execute", and so be aware of the shortcomings of this deployment "strategy". It's sure perfectly fine and easy for small apps / low traffic / not critical apps. I just want to point that it's not inherently good enough and definitely not the universal way to deploy a PHP app.

Git pull to deploy is something I avoid.

reply
kijin
1 day ago
[-]
Yeah, I've seen cases where even git is not fast enough. That's when opcache preload comes into play. It's still better than manually uploading files over FTP.

Having said that, the "most modern" deployment strategy is to spin up a new container with your new code already loaded, point your LB at the new container, and scrap the old container. No opcache issues. No race condition.

reply
whalesalad
2 days ago
[-]
technically you can do the same thing with python, via python server pages =)
reply
ransom1538
1 day ago
[-]
The PHP framework slim is x1000 better than Django and is quite popular.

https://www.slimframework.com/

reply
alternatex
2 days ago
[-]
PHP fast? Compared to all popular web frameworks it's quite low in the pecking order when it comes to performance.
reply
dubcanada
2 days ago
[-]
Not sure where you got that from. It’s equally if not faster then python, faster then Java, slower then compiled language, faster then ruby. Loses to NodeJS most of the time.

But who cares, we are literally talking millisecond differences between them all. Throw a reverse proxy, DB into the mix and a few packages and they are all slow.

reply
askonomm
2 days ago
[-]
And if we actually want to talk speed, PHP with something like Swoole or ReactPHP is many times even faster[0] than the already fast regular PHP.

[0]: https://medium.com/@dimdev/9-php-runtimes-performance-benchm...

reply
biorach
2 days ago
[-]
> faster then Java

You sure about that? Not what I would have expected. Source?

reply
dubcanada
2 days ago
[-]
My point was less about the leaderboards and more about it being pointless comparison. But I was looking at https://web-frameworks-benchmark.netlify.app/result?l=java,p... though I don't really know what people consider "best benchmark" for raw vs raw. Once you start throwing in apache/nginx/proxies/what ever it really starts to balance itself.
reply
igouy
28 minutes ago
[-]
reply
sneed_chucker
2 days ago
[-]
Definitely not faster than Java if we're talking single thread performance.
reply
hasnain99
1 day ago
[-]
I don't Use Php but I think learning Php its better than to learn Typscript
reply
reconvene1290
2 days ago
[-]
> PHP 8.4 is a major update of the PHP language.

No it’s not: it’s a MINOR update.

reply
dadver
2 days ago
[-]
It can be a major update even though it's a minor version bump.
reply
pwdisswordfishz
2 days ago
[-]
It could have been, but isn’t. Most of those are rather small, incremental quality-of-life improvements. Nothing revolutionary.
reply
theodorejb
2 days ago
[-]
I wouldn't consider all the new features small, but even many small improvements can result in a major improvement.
reply