Re: [PHP-DEV] [RFC[ Property accessor hooks, take 2

On Wed, Feb 21, 2024 at 7:58 PM Larry Garfield <larry@garfieldtech.com> wrote:

Hello again, fine Internalians.

After much on-again/off-again work, Ilija and I are back with a more polished property access hooks/interface properties RFC. It’s 99% unchanged from last summer; the PR is now essentially complete and more robust, and we were able to squish the last remaining edge cases.

Baring any major changes, we plan to bring this to a vote in mid-March.

https://wiki.php.net/rfc/property-hooks

It’s long, but that’s because we’re handling every edge case we could think of. Properties involve dealing with both references and inheritance, both of which have complex implications. We believe we’ve identified the most logical handling for all cases, though.

Note the FAQ question at the end, which explains some design choices.

There’s one outstanding question, which is slightly painful to ask: Originally, this RFC was called “property accessors,” which is the terminology used by most languages. During early development, when we had 4 accessors like Swift, we changed the name to “hooks” to better indicate that one was “hooking into” the property lifecycle. However, later refinement brought it back down to 2 operations, get and set. That makes the “hooks” name less applicable, and inconsistent with what other languages call it.

However, changing it back at this point would be a non-small amount of grunt work. There would be no functional changes from doing so, but it’s lots of renaming things both in the PR and the RFC. We are willing to do so if the consensus is that it would be beneficial, but want to ask before putting in the effort.


Larry Garfield
larry@garfieldtech.com

In regards to arrays, what about additional operations next to get/set? I doubt this solution will cover all the use-cases or perhaps even over-complicate things, just throwing the idea out there.

class Test {
private array $_myData = [];
public array $myData {
get => $this->_myData;
append => $this->_myData[] = $value;
}
}

Thinking about the other post about offset and containers (https://github.com/Girgias/php-rfcs/blob/master/container-offset-behaviour.md):

class Test {
private array $_myData = [];
public array $myData {
get => $this->_myData;
append => $this->_myData[] = $value;
write_dimension => $this->_myData[$offset] = $value;
}
}

Is this issue restricted to arrays only? From my understanding objects functioning as arrays are already by reference and thus should not suffer from this?

class Test {
private ArrayObject $_myData;
public ArrayObject $myData {
get => $this->_myData;
}

public function __construct() {
$this->_myData = new ArrayObject();
}

}

// would this work without issues?
$obj = new Test();
$obj->myData[] = 'test';

On Mon, Mar 18, 2024, at 9:13 AM, Lynn wrote:

In regards to arrays, what about additional operations next to get/set?
I doubt this solution will cover all the use-cases or perhaps even
over-complicate things, just throwing the idea out there.

class Test {
    private array $_myData = [];
    public array $myData {
        get => $this->_myData;
        append => $this->_myData[] = $value;
    }
}

Thinking about the other post about offset and containers
(php-rfcs/container-offset-behaviour.md at master · Girgias/php-rfcs · GitHub):

class Test {
    private array $_myData = [];
    public array $myData {
        get => $this->_myData;
        append => $this->_myData[] = $value;
        write_dimension => $this->_myData[$offset] = $value;
    }
}

Those hooks may be possible; we'd have to try it and see. However, they also wouldn't be able to fully emulate arrays. $foo->bar['baz'] = 'beep' could get very weird. Those wouldn't cover unsetting. Array functions like array_splice() still wouldn't work. Basically, there will never be a way to make arrays 100% transparent with hooks. That's why the RFC recommends still using a method for array modification, as that's already a very well-understood and flexible approach.

Fortunately, as currently written (append and write_dimension are forbidden), those additional hooks could be considered and added in their own RFC in the future with no BC break. Whether or not they make sense or cover "enough" use cases is a question that could be answered in the future, after Gina's RFC passes.

So on this one, I think "punt" is the best option for now. It can be safely revisited in the future.

Is this issue restricted to arrays only? From my understanding objects
functioning as arrays are already by reference and thus should not
suffer from this?

class Test {
    private ArrayObject $_myData;
    public ArrayObject $myData {
        get => $this->_myData;
    }

    public function __construct() {
        $this->_myData = new ArrayObject();
    }
}

// would this work without issues?
$obj = new Test();
$obj->myData[] = 'test';

Mostly correct. Objects pass by handle, not by reference. (You can pass an object by reference instead, and it behaves subtly differently.) But the net effect is the same. Your sample code there would run fine.

--Larry Garfield