stas

Stas Malyshev , from Zend Technologies
(user votes do not necessarily reflect their company's views)

krakjoe

krakjoe

Contents

PHP RFC: Objects as hash keys

The purpose of this RFC is to introduce a magic method that will allow objects to serve as hash keys.

Introduction

In PHP array keys can be only represented as numbers and strings. However, there already are several classes that represent different kinds of numbers (such as GMP objects) and some objects can also represent strings (e.g. Unicode strings) or string-like objects. It would be convenient to be able to use such objects as array keys to.

It could be achieved as conversion to string, but this is not ideal since object's string representation does not always match object's identity and there may be case where human-readable string may be different from value for the purposes of hashing. Also, some object may prefer to produce numeric index.

Proposal

Create a new magic method, __hash() which is called when object is supplied as a hash key, and returns string or integer that is used as the hash key.

A number of languages implement the same facility, namely:

  • Java has hashCode() and toString()
  • Python has __str__, __repr__ and __hash__
  • Ruby has object.hash

The method should produce a value which is acceptable as a key (not including objects), otherwise the engine will still produce an illegal offset type error. The objects not having this method implemented would produce an illegal offset type error when used in hash key position as before.

<?php
class Foo {
    public function __hash() {
        return "Foo";
    }
}
 
$foo = new Foo();
$test = [
    $foo => true
];

Inheritance shall work as any other magic method:

<?php
class Foo {
    public function __hash() {
        return "Foo";
    }
}
 
class Bar extends Foo {
    /* shall use Foo::__hash unless Bar::__hash is implemented */
}
 
$bar = new Bar();
$test = [
    $bar => true
];

Returning a non-scalar shall fail as it did before:

<?php
class Foo {
    public function __hash() {
        return [];
    }
}
 
$foo = new Foo();
$test = [
    $foo => true
];

Shall yield:

Warning: Illegal offset type in %s on line %d

The current behavior of __toString is unchanged.

Backward Incompatible Changes

Should not break anything as we don't allow this now.

Proposed PHP Version(s)

Targeted for PHP 7

RFC Impact

To SAPIs

No impact on SAPIs

To Existing Extensions

If somebody implements something like ArrayAccess they may want to update it to accommodate objects.

To Opcache

Since objects are run-time, should not have any effects on opcache.

Open Issues

  1. Should SplFixedArray support object indexes?
  2. Should SplObjectStorage support calling __hash for an object if it exists?

Implementation

References

Rejected Features

- Using __toString for the key conversion, for the reasons discussed above. - Supporting the use of objects for string indexes

Votes

An option needs 2/3 votes to win

Should we support using objects as keys as described in this proposal? (20% approved)
User Vote
ab Yes, via method __hash
aharvey No
ajf No
bate No
bwoebi No
colder No
derick No
dm No
dragoonis No
fa No
fredemmott No
guilhermeblanco No
jedibc No
kalle No
klaussilveira Yes, via method __hash
kriscraig No
leigh No
levim No
mbeccati No
mfischer No
mfonda No
mike No
mrook Yes, via method __hash
nikic No
pajoye Yes, via method __hash
pierrick Yes, via method __hash
pollita No
reeze No
salathe No
stas Yes, via method __hash