====== PHP RFC: Clone with v2 ======
* Version: 1.0
* Date: 2015-03-30
* Author: Volker Dusch (volker@tideways-gmbh.com), Tim Düsterhus (tim@tideways-gmbh.com)
* Status: Draft
* First Published at: https://wiki.php.net/rfc/clone_with_v2
===== Introduction =====
Both readonly properties and the cloneing of objects are commonplace in a lot of PHP application, but these two concepts don’t fully work together in all cases.
These RFC proposes to address this issue by allowing the clone language construct to work well with readonly.
A common usage pattern for object cloning are “immutable value-objects” having ->withProperty methods returning a new object with this property changed. This doesn’t work well with readonly properties at the moment.
To address this, we propose a hopefully, simple change that makes clone look and mostly behave like a regular function call, making it work with current PHP users' expectations regarding syntax and semantics while respecting visibility rules.
public function withStatus($code, $reasonPhrase = ''): Response
{
return clone(
$this,
statusCode: $code,
reasonPhrase: $reasonPhrase,
);
}
===== Prior Works =====
This change was proposed in https://wiki.php.net/rfc/clone_with and discussed https://externals.io/message/120048
Máté, the original RFC author, dropped the RFC and had no objections to us proposing this continuation trying to address the same need.
===== Proposal =====
We propose to change clone from a standalone keyword to a language construct that optionally accepts parenthesis and a parameter list.
For most end-user cases this would, in practice, mean that any instance of clone $x could also be written as if there would be clone function with the following signature:
function clone(object $object, mixed ...$updatedProperties): object {}
allowing for all the following syntax examples to be valid:
$y = clone $x;
$y = clone($x);
$y = clone($x, foo: $foo, bar: $bar);
$y = clone($x, ...$array);
$y = clone($x, ...[
"foo" => $foo,
"bar" => $bar,
]);
==== Technical Details ====
* A magic __clone method will be called before the new properties are assigned.
* Assignment of new properties happens in parameter order. As a result, should there an error during the assignment, e.g. because of property hooks, the error will be raised for the first impacted property.
* Properties assignments are made just as a regular assignment would be. Meaning all regular PHP rules apply with only the readonly state being "unlocked".
- Visibility rules for property access are enforced
- Property hooks work as expected
- Dynamic properties respect #[AllowDynamicProperties]
- __set works as expected
==== Design Goals ====
When re-proposing this RFC, one of our goals was to take all previous discussion into account and propose something that is small in scope and cognitive load.
This RFC explicitly rejects any BC impacting syntax choices like the proposed with keyword suggested previously, as we don't feel the scope of the feature warrants any BC impact.
Likewise, all syntax has to exist in other parts of PHP already, to not add cognitive load to readers when they come across it.
==== Example ====
TBD (Throw order, etc)
===== Backward Incompatible Changes =====
No BC break is expected. The new syntax is optional and the old syntax will continue to work as before.
===== Proposed PHP Version(s) =====
Next PHP 8.x
===== RFC Impact =====
==== To SAPIs ====
None
==== To Existing Extensions ====
None
==== To Opcache ====
TBD. Opcache adjustment can be made if needed.
==== New Constants ====
None
==== php.ini Defaults ====
None
===== Open Issues =====
None
===== Unaffected PHP Functionality =====
===== Future Scope =====
None
===== Proposed Voting Choices =====
2/3 majority:
Vote
===== Patches and Tests =====
TBD
===== Implementation =====
TBD
===== References =====
* https://wiki.php.net/rfc/clone_with
* https://externals.io/message/120048
===== Rejected Features =====
None