[PHP-DEV] Extract ArrayAccessRead from ArrayAccess

Hello, internals!

Recently I was implementing some collections and realized that I cannot use ArrayAccess for immutable collections without throwing BadMethodCallException in offsetSet and offsetUnset. I also cannot have an interface ReadonlyCollection extends ArrayAccess, because offsetSet and offsetUnset are mutators and have TValue in a contravariant position.

Here’s the idea: let’s extract ArrayAccess::offsetExists and ArrayAccess::offsetGet methods into a separate ArrayAccessRead interface (name can be different) and allow read operations $exists = isset($object['key']) and $value = $object['key'] for objects of classes that implement this interface. ArrayAccess will then extend ArrayAccessRead and add the remaining 2 methods. Looks like this change should not break backward compatibility.

interface ArrayAccessRead
{
public function offsetExists(mixed $offset): bool;
public function offsetGet(mixed $offset): mixed;
}

interface ArrayAccess extends ArrayAccessRead
{
public function offsetSet(mixed $offset, mixed $value): void;
public function offsetUnset(mixed $offset): void;
}

// then interfaces of the doctrine/collections package might look like this:

namespace Doctrine\Common\Collections;

interface ReadableCollection extends Countable, IteratorAggregate, ArrayAccessRead {}
interface Collection extends ReadableCollection, ArrayAccess {}

···

Regards, Valentin Udaltsov

On Mon, May 27, 2024 at 7:16 AM Valentin Udaltsov <udaltsov.valentin@gmail.com> wrote:

Hello, internals!

Here’s the idea: let’s extract ArrayAccess::offsetExists and ArrayAccess::offsetGet methods into a separate ArrayAccessRead interface (name can be different) and allow read operations $exists = isset($object['key']) and $value = $object['key'] for objects of classes that implement this interface. ArrayAccess will then extend ArrayAccessRead and add the remaining 2 methods. Looks like this change should not break backward compatibility.

Please check this: https://externals.io/message/122609#122609 where Gina analyzed and proposed a solution for this.
It looks like the DimensionReadable is exactly the same thing. Maybe also DimensionFetchable if you consider returning by reference.

Maybe the improvement can be done in smaller incremental steps, but I think it’s better to agree on a complete solution for splitting ArrayAccess.

Regards,
Alex

Wow! That’s a great RFC with thorough analysis and an awesome proposal. Forget about my email :smile:. Looking forward to news from Gina.

···

Regards, Valentin Udaltsov