Using PHP Objects as Array keys

So I noticed a PHP RFC today which suggests implementing objects as array keys via a magic __toHash method. I’ll be addressing it in today’s PHP newsletter to some extent (if you haven’t signed up for it, you should!) but basically, this RFC would allow syntax like this:

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

… which makes me wonder about how it would handle this:

<?php
class Foo {
    public function __hash() {
        return "Foo";
    }
}
 
$foo = new Foo();
$fooString = "Foo";

$test = [
    $foo => true,
    $fooString => false
];

To me, it seems like the proposal is too much trouble for what it brings to the table (which explains the vote status somewhat), but I’m curious to see what the rest of you think about it.

Probably the same way it handles this:

$test = [
   'Foo' => 'one',
   'Foo' => 'bar',
];

With this output:

Array
(
    [Foo] => bar
)

Presumably it would be acceptable to use keys that are objects in other languages where everything is an object, such as Ruby, and would set up PHP to possibly allow a switch to similar typing later on. There would be no difference between

$foo = new string('My String');

$test = [
    $foo => true
];

and

$foo = 'My String';

$test = [
    $foo => true
];

at that point. The string class would presumably have a __hash() method that simply returns the string value in this case. But whether we need it or not, is something completely different :smile:

Yes, I’m aware that creating a new string() is not how it works in Ruby, but you get my point (I hope)

1 Like

Great, just what PHP needs, a way to make it’s swiss army knife arrays even more confusing. :angry:

1 Like

What’s confusing about PHP’s arrays?

First off, they aren’t arrays, they’re what other languages call dictionaries or maps. Arrays have numeric keys only.

Second, PHP allows some real weirdness - like $a[0] and $a[‘0’] being allowed in the same array and pointing to different values. The fact that keys can be any arbitrary string desired caused at least one major security failure in Drupal.

PHP arrays are powerful and they aren’t that confusing to experienced programmers - but I’ve watched them stump novices many a time. They also combine what are several discreet object types in other languages into one.

I don’t see a use case for objects as keys. I do see it as a way to let beginners and intermediates further shoot themselves in the foot. It just feels like more trouble than its worth, both from the userland perspective and the internals of the language.

1 Like

While all you say is true, blaming PHP’s arrays for Drupal’s code slips isn’t right. It’s far from PHP’s fault.

Yes, other languages have different names for the same structure and yes, arrays as presented in PHP are generally called something else elsewhere, but therein lies the catch - 0 simply isn’t equal to "0" in PHP, and as such having those as separate keys pointing to different values in the same array makes sense in the PHPverse, even if it is strang when coming from other environments.

I agree with you on objects as keys - I find it confusing and unnecessary, too.

While all you say is true, blaming PHP’s arrays for Drupal’s code slips isn’t right. It’s far from PHP’s fault.

I disagree in that PHP as a platform set the stage. If PHP had a true array type to begin with the data in that function could have been bound to that type, dumping any unwanted text keys. The final responsibility does lie with the Drupal team, but to hold the environment the language provides as faultless isn’t correct either.

A lot of bugs and security exploits in PHP arise out of a variable unexpectedly changing datatypes. I have long argued that PHP should have a strict set of variables which must be declared to be used and when declared their datatype is locked down. Two subtypes of these variables would exist, tolerant and intolerant.

Tolerant variable have a locked datatype declared like so in proceedure

var integer $a = 1;

And like this in classes

protected integer $a = 1;

If $a is assigned a non-integer value, it immediately casts the value to integer. No notice or warning is thrown, this is what tolerants are for. Strict variables have a new keyword and are declared like so

strict integer $a = 1;

And in classes

public strict integer $a = 2;

If a non integer is assigned to a strict catchable fatal error is thrown. The whole point of strict variables is to die hard when such behavior occurs.

Changing the datatype requires unsetting the variable entirely, which is not possible for class members.

Yes, other languages have different names for the same structure and
yes, arrays as presented in PHP are generally called something else
elsewhere, but therein lies the catch - 0 simply isn’t equal to “0” in PHP

You know that, I know that, now the catch is explaining it to the beginners. Ease of access has always been a strong point for the language, and admittedly a weakness as well since loose datatyping has all sorts of pitfalls for the unwary. It’s still less intimidating than having to learn datatypes at the same time as learning variables.

As far as $a[0] vs. $a[“0”] I wish it would at least kick a warning. I see no reason other than sowing confusion to set up keys that way.

I agree with you on objects as keys - I find it confusing and unnecessary, too.

Having given this further thought I can think of a possible use case - keeping an object intact while using array_flip on the array that contains it. However, that case is a bit contrived and there should be better ways to accomplish this.

1 Like

How would be accomplished traversing through that kind of arrays? For example, in each foreach loop with keys exposed we will restore reference to an object from a hash string in key? It looks like moving some parts of SplObjectStorage from SPL library to native language functionality?
As for me, if there exists some cases to use exact objects as keys - they could be covered by own Collection implementation or SplObjectStorage class. Otherwise that kind of functionality will increase internal array size for non scalar types (e.g. array structure MUST know about that string in key is a hash of the class instance).
And I agree with @Michael_Morris about typing. PHP is not really have strong type system to conceive typed lists functionality implemented in other languages. But, many of that we could implement by own.

@Michael_Morris your points are well placed.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.