9 ms·
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 d
by idoubtit 2y 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.
- dubcanada 2y agoNone of this is required. You can still write spaghetti code perfectly fine.
- smarkov 2y agoOf 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.
- beberlei 2y agoJust 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.
- idoubtit 2y agoThanks for correcting me, and sorry for the error. I should have checked before writing.
- chx 2y 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.
- idoubtit 2y 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.
- chx 2y 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.
- conradfr 2y agoDon't you get tired of managing getters/setters in your entities?
- mgkimsal 2y agoaren't you just managing them in a new syntax now?
- joshmanders 2y agoThe 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');
- stephenr 2y agoA 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.
- cutler 2y agoEntities, shrentities - it's all just data.
- tcfhgj 2y agowhich getters/setters?
- whalesalad 2y agostockholm syndrome is real
- jacobyoder 2y agoI'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.
- wvenable 2y agoI'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().
- mgkimsal 2y agocan't do that if you declare the properties on the class. __get only works for undefined properties.
- wvenable 2y agoWell don't do that then. :)
- munk-a 2y agoOr, alternatively, use `__call`
- 9dev 2y agoDoctor, doctor, it always hurts when I press here…
- hks0 2y agoThat 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.
- ok123456 2y agoThis 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.
- brtkdotse 2y agoMy experience is that 99% of the work related to geters and seters is handled by the IDE
- ok123456 2y agoThis 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.
- crowcroft 2y agoI 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.
- ok123456 2y agoI 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.
- signal11 2y agoIt’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.
- alt227 2y agoI 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.
- giraffe_lady 2y agoI 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.
- alt227 2y 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.
- giraffe_lady 2y ago
- Shorel 2y agoI 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)
- munk-a 2y agoWhile 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.
- manarth 2y 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/ https://projectlombok.org/
- brazzy 2y agoOr, for immutable entities, just use records. Part of the language since 2020: https://docs.oracle.com/en/java/javase/14/language/records.html https://docs.oracle.com/en/java/javase/14/language/records.h... Admittedly they come with some restrictions, but also some additional benefits.
- klaussilveira 2y agoI 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.
- sieabahlpark 2y ago[dead]
- cutler 2y agoSeriously? 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.
- klaussilveira 2y agoYes, that is correct. And this release marks a point where the language is officially moving away from that.
- thrw42A8N 2y agoHow? 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.
- stephenr 2y 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.
- notresidenter 2y agoThis 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.
- reaperducer 2y agoThe 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.
- cess11 2y agoPHP 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.
- keyle 2y agoI 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.