# Pass source object to clone like __clone($origThis)

- Thread: https://externals.io/message/111791
- Original archive: https://news-web.php.net/php.internals/111791
- Started by vorismi3@fel.cvut.cz on 2020-09-02T18:41:35+00:00
- Messages: 12
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #111791 — vorismi3@fel.cvut.cz — 2020-09-02T18:41:35+00:00

URL: https://externals.io/message/111791#111791

Hi, please look at
https://stackoverflow.com/questions/63675888/get-original-source-instance-in-clone


do you have anything against updating PHP to pass "instance before
cloned" to any __clone call from php? 

no BC - user may accept this extra argument or declare function
__clone() without any param like now 

With kind regards / Mit freundlichen Grüßen / S přátelským pozdravem,

Michael Voříšek

---

## #111793 — David Rodrigues — 2020-09-02T19:10:55+00:00

URL: https://externals.io/message/111791#111793 · In reply to: #111791

I understand... seems that `$this` is very confusing inside `__clone()`:
when writing, it writes to the clone, when reading it reads from original.

Seems valid a new optional parameter definition with the original source.



Atenciosamente,
David Rodrigues


Em qua., 2 de set. de 2020 às 15:41, Michael Voříšek - ČVUT FEL <
vorismi3@fel.cvut.cz> escreveu:

> Hi, please look at
>
> https://stackoverflow.com/questions/63675888/get-original-source-instance-in-clone
>
>
> do you have anything against updating PHP to pass "instance before
> cloned" to any __clone call from php?
>
> no BC - user may accept this extra argument or declare function
> __clone() without any param like now
>
> With kind regards / Mit freundlichen Grüßen / S přátelským pozdravem,
>
> Michael Voříšek

---

## #111811 — Nikita Popov — 2020-09-03T11:06:00+00:00

URL: https://externals.io/message/111791#111811 · In reply to: #111791

On Wed, Sep 2, 2020 at 8:42 PM Michael Voříšek - ČVUT FEL <
vorismi3@fel.cvut.cz> wrote:

> Hi, please look at
>
> https://stackoverflow.com/questions/63675888/get-original-source-instance-in-clone
>
>
> do you have anything against updating PHP to pass "instance before
> cloned" to any __clone call from php?
>
> no BC - user may accept this extra argument or declare function
> __clone() without any param like now
>

Could you please provide some more information on what the intended
use-case is?

I'm not opposed to this change, but I also don't understand why it is
needed.

Regards,
Nikita

---

## #111812 — mail@pmmaga.net — 2020-09-03T11:48:47+00:00

URL: https://externals.io/message/111791#111812 · In reply to: #111791

On Wed, Sep 2, 2020 at 7:41 PM Michael Voříšek - ČVUT FEL <
vorismi3@fel.cvut.cz> wrote:

> do you have anything against updating PHP to pass "instance before
> cloned" to any __clone call from php?
>

Yes, I think that allowing the original object to be modified by a cloning
operation could be the cause for a lot of confusion. If we had a proper way
to make it read-only I wouldn't mind, but as is, it doesn't sound like a
good idea.

---

## #111817 — David Rodrigues — 2020-09-03T13:41:52+00:00

URL: https://externals.io/message/111791#111817 · In reply to: #111812

I don't see problem to allow modify the original object, once that you are
doing it by using a new argument, and not the $this itself.

Em qui, 3 de set de 2020 08:49, Pedro Magalhães <mail@pmmaga.net> escreveu:

> On Wed, Sep 2, 2020 at 7:41 PM Michael Voříšek - ČVUT FEL <
> vorismi3@fel.cvut.cz> wrote:
>
> > […]
>
> Yes, I think that allowing the original object to be modified by a cloning
> operation could be the cause for a lot of confusion. If we had a proper way
> to make it read-only I wouldn't mind, but as is, it doesn't sound like a
> good idea.

---

## #111818 — Sara Golemon — 2020-09-03T14:21:08+00:00

URL: https://externals.io/message/111791#111818 · In reply to: #111793

On Wed, Sep 2, 2020 at 2:11 PM David Rodrigues <david.proweb@gmail.com>
wrote:

> I understand... seems that `$this` is very confusing inside `__clone()`:
> when writing, it writes to the clone, when reading it reads from original.
>
>
That's not an accurate description of what happens today.

$newObj = clone $oldObj;
// 1. Engine creates a new instance of get_class($oldObj), without calling
the constructor
// 2. Engine copies all properties from the old object to the new object
// 3. Engine invokes $newObj->__clone()
  public function __clone() {
    // Userspace object handles any property specific re-initialization
required.
    // $this always refers to the new object here.
 }

The question Niki asked is appropriate; What would one want to do to
$oldObj here?
If the goal is to read from the old object, then you have that already.
The new object is a perfect copy, so read from that.
If the goal is to write to the old object, then justify why you need to do
so, because it's not a clone operation at that point.

-Sara

---

## #111825 — David Rodrigues — 2020-09-03T15:39:53+00:00

URL: https://externals.io/message/111791#111825 · In reply to: #111818

Now I rethinked about what I said. Really, maybe clone is not the best
option. So maybe we can just use a method that will clone and will have
access to both informations. But I don't know if it solves the original
message.

public function getUserCopy() {
    $userCopy = clone $this;
    $this->copies[] = $userCopy;

    return $userCopy;
}

Considering it, we have access to both now, with "write to source" support
with no additional feature need.

Em qui, 3 de set de 2020 11:21, Sara Golemon <pollita@php.net> escreveu:

> On Wed, Sep 2, 2020 at 2:11 PM David Rodrigues <david.proweb@gmail.com>
> wrote:
>
> > […]
> That's not an accurate description of what happens today.
>
> $newObj = clone $oldObj;
> // 1. Engine creates a new instance of get_class($oldObj), without calling
> the constructor
> // 2. Engine copies all properties from the old object to the new object
> // 3. Engine invokes $newObj->__clone()
>   public function __clone() {
>     // Userspace object handles any property specific re-initialization
> required.
>     // $this always refers to the new object here.
>  }
>
> The question Niki asked is appropriate; What would one want to do to
> $oldObj here?
> If the goal is to read from the old object, then you have that already.
> The new object is a perfect copy, so read from that.
> If the goal is to write to the old object, then justify why you need to do
> so, because it's not a clone operation at that point.
>
> -Sara

---

## #111827 — Sara Golemon — 2020-09-03T16:00:39+00:00

URL: https://externals.io/message/111791#111827 · In reply to: #111825

On Thu, Sep 3, 2020 at 10:40 AM David Rodrigues <david.proweb@gmail.com>
wrote:

> Now I rethinked about what I said. Really, maybe clone is not the best
> option. So maybe we can just use a method that will clone and will have
> access to both informations. But I don't know if it solves the original
> message.
>
> public function getUserCopy() {
>     $userCopy = clone $this;
>     $this->copies[] = $userCopy;
>
>     return $userCopy;
> }
>
>
If your goal is to track copies, then a static makes much more sense.

class AllKnowing {
    private static $copies = [];

    public function __construct(...) {
        self::$copies[] = $this;
        ....
    }

    public function __clone() {
        self::$copies[] = $this;
   }
}

-Sara

---

## #111828 — David Rodrigues — 2020-09-03T16:03:29+00:00

URL: https://externals.io/message/111791#111828 · In reply to: #111827

It was just an example to avoid modify how clone works, using existing
features. :)

Em qui, 3 de set de 2020 13:00, Sara Golemon <pollita@php.net> escreveu:

> On Thu, Sep 3, 2020 at 10:40 AM David Rodrigues <david.proweb@gmail.com>
> wrote:
>
> > […]
> If your goal is to track copies, then a static makes much more sense.
>
> class AllKnowing {
>     private static $copies = [];
>
>     public function __construct(...) {
>         self::$copies[] = $this;
>         ....
>     }
>
>     public function __clone() {
>         self::$copies[] = $this;
>    }
> }
>
> -Sara

---

## #111830 — Sara Golemon — 2020-09-03T16:06:46+00:00

URL: https://externals.io/message/111791#111830 · In reply to: #111828

On Thu, Sep 3, 2020 at 11:03 AM David Rodrigues <david.proweb@gmail.com>
wrote:

> It was just an example to avoid modify how clone works, using existing
> features. :)


>

Right, but the question remains "Why would we want the original object
during a clone operation?".  No legitimate example of that has been
provided yet.

-Sara

---

## #111832 — vorismi3@fel.cvut.cz — 2020-09-03T16:36:46+00:00

URL: https://externals.io/message/111791#111832 · In reply to: #111827

The goal is to be able to access the original object and it's id/hash. 

Usecases: 

- something is associated with the object using the object id/hash and
it needs to be cloned as well 

we need the original object to obtain it's id/hash for spl_object_id and
spl_object_hash methods 

- bounded Closures ar associated with the original object and they needs
to be rebound to the cloned object 

example: 

public function __clone(self $origThis)
{
    if ((new \ReflectionFunction($this->fx))->getClosureThis() ===
$origThis) {
        $this->fx = \Closure::bind($this->fx, $this);
    }
} 

Modification of php is simple: 

https://github.com/php/php-src/pull/6063/files#diff-beea8c5a8ceb318220b34b73e4ecfc98R252


we simply pass the old object as 1 parameter. I belive, passing old
object have positives and no performance nor compatibility impact. All
other current solutions require an extra property and a lot of code, as
assigning in constructor is not enough (due serialization etc.), or it
is even impossible, if object was created using reflection without
constructor. 

With kind regards / Mit freundlichen Grüßen / S přátelským pozdravem,

Michael Voříšek



> On Thu, Sep 3, 2020 at 10:40 AM David Rodrigues <david.proweb@gmail.com>
> wrote:
> 
> > […]
> If your goal is to track copies, then a static makes much more sense.
> 
> class AllKnowing {
> private static $copies = [];
> 
> public function __construct(...) {
> self::$copies[] = $this;
> ....
> }
> 
> public function __clone() {
> self::$copies[] = $this;
> }
> }
> 
> -Sara

---

## #111833 — David Rodrigues — 2020-09-03T17:43:43+00:00

URL: https://externals.io/message/111791#111833 · In reply to: #111832

Just to I know, it can't be done by an intermediary method like my previous
example? Why are the limitations to that?

About PR, could you provide some additional tests?

Thanks!

Em qui, 3 de set de 2020 13:37, Michael Voříšek - ČVUT FEL <
vorismi3@fel.cvut.cz> escreveu:

> The goal is to be able to access the original object and it's id/hash.
>
> Usecases:
>
> - something is associated with the object using the object id/hash and
> it needs to be cloned as well
>
> we need the original object to obtain it's id/hash for spl_object_id and
> spl_object_hash methods
>
> - bounded Closures ar associated with the original object and they needs
> to be rebound to the cloned object
>
> example:
>
> public function __clone(self $origThis)
> {
>     if ((new \ReflectionFunction($this->fx))->getClosureThis() ===
> $origThis) {
>         $this->fx = \Closure::bind($this->fx, $this);
>     }
> }
>
> Modification of php is simple:
>
>
> https://github.com/php/php-src/pull/6063/files#diff-beea8c5a8ceb318220b34b73e4ecfc98R252
>
>
> we simply pass the old object as 1 parameter. I belive, passing old
> object have positives and no performance nor compatibility impact. All
> other current solutions require an extra property and a lot of code, as
> assigning in constructor is not enough (due serialization etc.), or it
> is even impossible, if object was created using reflection without
> constructor.
>
> With kind regards / Mit freundlichen Grüßen / S přátelským pozdravem,
>
> Michael Voříšek
>
> 
>
> > […]
