Developers often use methods to wrap and guard access to object properties. There are several highly common patterns for such logic, which in practice may be verbose to implement repeatedly. Alternatively, developers may use __get
and __set
to intercept reads and writes generically, but that is a sledge-hammer approach that intercepts all undefined (and some defined) properties unconditionally. Property hooks provide a more targeted, purpose-built tool for common property interactions.
class User { public string $name { set { if (strlen($value) === 0) { throw new ValueError("Name must be non-empty"); } $this->name = $value; } } public function __construct(string $name) { $this->name = $name; } }
You can play around with them on 3v4l.org
Provides a nice code structure keeping together: declaration, getter and guarded setter
All arguments against already mentioned. I also believe internally PHP could become slower, because of more complex parsing. Copying some open questions from another argument too: How should child classes behave? Are they overridable? How do you know if there is a setter behavior defined already? How should traits behave? Is there a way to call the parent class setter/getter? Would that be overriden or just called by default?
This is a much better approach than having to create getters and setters for validating values before assigning them to properties. Actually, this is an aspect from C# which I really like...
Getters and setters work just fine.
Additionally RFC says there is a large and obscure performance penalty for array
typed properties and it's introduces additional complexity.
It feels like it adds a huge amount of complexity just to avoid getter/setter methods. Also, I'm not sure it's a good thing to lose the explicit differentiation between a property access and method call.
Note: setter methods are something I almost never use in the first place, since it's typically better to have immutable value objects.
This sounds pretty familiar to C# way for defining setters and getter. My problem with this RFC that it discourage code decoupling and separation of responsibilities. I know this is just an example use case, but an object shouldn't know how values should look like, it should be a responsibility of another component.
Yes, I agree with the idea of property hooks. It feels like a natural way to add more control over input and output without the need for heavy methods. It’s like bringing the convenience of Laravel’s Accessors/Mutators directly into PHP, but with more flexibility. While I understand some of the concerns about the implementation, I think it’s a step in the right direction for cleaner and more efficient code.
With this feature, one can conveniently set a property directly, but still have validation on it behind the scenes. This is more convenient than using __set
.
Adds important value to the language. As I'm almost always programming against interfaces, this would help reducing boiler plate code a lot.
This is one of my favorite TypeScript features. But what has me even more excited is the ability to add properties to interfaces.
Soon we'll be able to fully describe simple structures in interfaces. Anyone who has ever done serious TypeScript coding in CDK knows how powerful this is.
Comparing to the code below, it is not usable and clear. the only benefit of that can be just knowing the name of the variable. other than that the syntax is way far from PHP and confusing. the value variable should be defined with type and when you start adding the parts that result will be like the __set
method
class User
{
public string $name;
public function __construct(string $name) {
$this->name = $name;
}
public function __set(string $name, string $value){
if($name !== 'name'){
return;
}
if (strlen($value) === 0) {
throw new ValueError("Name must be non-empty");
}
$field = ucfirst($value);
}
}
$u = new User('');
var_dump($u->name);`
This rfc is needed to remove setters and getters. I hope that ability of use property hooks will be added to doctrine cause I hate entities with 1k lines of code just with setters and getters.
This feels a lot nicer than the __get
/__set
weirdness I currently have to deal with. The ability to define properties as part of an interface contract is something that would have been nice to have in some projects I've previously worked on.
This proposal reduces boilerplate, simplifies developer API contracts, reduces the need for refactors when revising existing code, and aids static analysis tools. The benefits definitely outweigh the cost of the additional syntax to learn and the oddities of said syntax (namely $field), if you ask me.
I had some issues with the syntax in earlier versions of the RFC (namely the number and implementation of shorthand syntax), but most of those have since been addressed, and the only notable one left ($field
) is acceptable given the lack of better alternatives.
class User { private string $internalName; // Renamed to avoid conflict
public string $name {
set {
if (strlen($value) === 0) {
throw new ValueError("Name must be non-empty");
}
$this->internalName = $value; // Store the value in internalName
}
get {
return $this->internalName;
}
}
public function __construct(string $name) {
$this->name = $name;
}
}
The internal property used to store the value of $name is renamed to $internalName to avoid the conflict with the setter method, resolving the issue of the infinite loop. Error handling is improved by throwing a ValueError exception when an empty string is provided as the value for the name property. This ensures that validation errors are appropriately handled within the class.
This is well established in many other languages (Swift, Kotlin, C#) and the concerns of other commenters has not caused mass chaos as they would have you believe.
I'm not saying there aren't valid concerns, but the idea that "programmers will use it wrong" is not good enough.
This RFC proposes a way to have multi-line short closures — closures that don't need explicit use
statements, but can still have multiple lines and a return statement.
Chain method on newly created objects without parentheses
The "pipe operator" |>
allows you to chain multiple function calls in a more convenient way.