rfc:clone_with_v2

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

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.

<?php
 
final readonly class Response {
    public function __construct(
        public int $statusCode,
        public string $reasonPhrase,
        // ...
    ) {}
 
    public function withStatus($code, $reasonPhrase = ''): Response
    {
        // Only works if all properties are assignable via __construct
        $values = get_object_vars($this);
        $values['statusCode'] = $code;
        $values['reasonPhrase'] = $reasonPhrase;
        return new self(
            ...$values
        );
    }

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”.
    1. Visibility rules for property access are enforced
    2. Property hooks work as expected
    3. Dynamic properties respect #[AllowDynamicProperties]
    4. __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

Rejected Features

None

rfc/clone_with_v2.txt · Last modified: 2025/03/30 12:03 by edorian