php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #39764 array_key_exists inconsistent behavior
Submitted: 2006-12-07 10:38 UTC Modified: 2008-11-27 02:10 UTC
Votes:3
Avg. Score:3.7 ± 0.9
Reproduced:2 of 3 (66.7%)
Same Version:1 (50.0%)
Same OS:0 (0.0%)
From: techtonik@php.net Assigned:
Status: Wont fix Package: Arrays related
PHP Version: 4.4.4 OS: Windows2000
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: techtonik@php.net
New email:
PHP Version: OS:

 

 [2006-12-07 10:38 UTC] techtonik@php.net
Description:
------------
Array indexes can be resources - in this case they are casted to int automatically without any warning (E_STRICT is turned off in PHP5). Hovewer, array_key_exists() throws warning if resource is passed as a key and fails to recognize the key. 

This leads to confusion and is illustrated below.

More logical behavior is to make conversion automatically and display warning only in E_STRICT mode for PHP5.

Yes, the problem persists in PHP5 as well. 


Reproduce code:
---------------
<?php
$depth = array();

$parser = xml_parser_create();

$depth[$parser] = "xxx";

echo "\n -".array_key_exists((int)$parser, $depth);
echo "\n -".array_key_exists("" + $parser, $depth);
echo "\n -".array_key_exists("" . $parser, $depth);
echo "\n -".array_key_exists((int) $parser, $depth);
echo "\n".$depth[$parser];
echo "\n".$depth[(int)$parser];
echo "\n";

$z = "" + $parser;
var_dump($z);
$z = "" . $parser;
var_dump($z);
$z = (string) $parser;
var_dump($z);
$z = strval($parser);
var_dump($z);

exit();


Expected result:
----------------
Warning: array_key_exists(): The first argument should be either a string or an integer in C:\php51\test00.php on line 8

 -
 -1
 -
 -1
xxx
int(4)
string(14) "Resource id #4"
string(14) "Resource id #4"
string(14) "Resource id #4"


Actual result:
--------------
 -1
 -1
 -
 -1
xxx
int(4)
string(14) "Resource id #4"
string(14) "Resource id #4"
string(14) "Resource id #4"


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-12-07 10:41 UTC] techtonik@php.net
"Expected result" and "Actual result" should be switched. Sorry for confusion.
 [2006-12-07 10:50 UTC] tony2001@php.net
Name at least one reason why do you need to use resource as array keys.

>E_STRICT is turned off in PHP5
Yes, it can be turned off, as well as E_WARNING.
 [2006-12-07 12:27 UTC] techtonik@php.net
For resource-dependent array data. Configuration or state information, whatever. 

For example - http://www.php.net/xml#AEN211968
 [2006-12-07 12:35 UTC] tony2001@php.net
Why do you promote bad code in the docs? This code sample is wrong and should be fixed in order to avoid using special types as array keys.
 [2006-12-07 12:56 UTC] techtonik@php.net
If even experienced developers who write the manual tend to make this kind of "mistakes" then what should we expect from other users?

From the other side if we assume that PHP is OO language then it should be indifferent to the type of object used as array key as long as the object can be hashed and compared to others. IIRC that is the way it works for Python and Java (toString() method).
 [2006-12-07 13:11 UTC] tony2001@php.net
>If even experienced developers who write the manual tend
>to make this kind of "mistakes" then what should we
>expect from other users?

Well, nobody's perfect and even experienced developers make mistakes. But that doesn't mean these mistakes should become a rule.

>From the other side if we assume that PHP is OO language
>then it should be indifferent to the type of object used
>as array key as long as the object can be hashed and
>compared to others. IIRC that is the way it works for
>Python and Java (toString() method).

While I can agree, that resources should have been objects and even the resource type should not exist, this is what we have to live with.
Objects DO have __toString() method (and you cannot use an object as a key without implementing this method in 5.2+), but resources are different.
So I would actually change the E_STRICT error to E_NOTICE, as it doesn't make much sense to me to use an internal resource identifier as a key. This internal ID might be reused or another resource with different ID might exist pointing to the same physical resource (connection, structure etc.).
 [2006-12-07 13:33 UTC] techtonik@php.net
> Objects DO have __toString() method (and you cannot use an
> object as a key without implementing this method in 5.2+),
> but resources are different.

> So I would actually change the E_STRICT error to E_NOTICE,
> as it doesn't make much sense to me to use an internal 
> resource identifier as a key.

Then change it to E_WARNING to be consistent with array_key_exists() and deny serialization of resources to (int) as in $array[$resource] = "value";

> This internal ID might be reused or another resource with > different ID might exist pointing to the same physical 
> resource (connection, structure etc.).

It seems that resources are generated incrementally.
<?php
$xml_parser = xml_parser_create();
xml_parser_free($xml_parser);
var_dump($xml_parser);

$xml_parser = xml_parser_create();
xml_parser_free($xml_parser);
var_dump($xml_parser);
?>

The better solution would be to generate unique hash for resource, which will include resource type and ordinal. 

But the simple way to reach consistency on this stage is still to patch array_key_exists($resource, $array) to report correct information just like isset($array[$resource]) does.
 [2008-11-27 02:10 UTC] jani@php.net
We are sorry, but we can not support PHP 4 related problems anymore.
Momentum is gathering for PHP 6, and we think supporting PHP 4 will
lead to a waste of resources which we want to put into getting PHP 6
ready.


 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Oct 16 04:01:27 2024 UTC