php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #28879 Behavioural issues: $foo = array() vs $foo[] and objects vs resources
Submitted: 2004-06-22 11:42 UTC Modified: 2004-06-24 01:39 UTC
From: aidan@php.net Assigned:
Status: Closed Package: Arrays related
PHP Version: 5.0.0RC3 OS: WinXP
Private report: No CVE-ID:
 [2004-06-22 11:42 UTC] aidan@php.net
Description:
------------
This bug report pertains to two seperate but related problems:

1. Unexpected and undocumented behaviour, between $foo[] and $foo = array()

2. Automatic conversion of objects to strings when used as the key in an array.

Part 1;
-------
With a given resource, the automatic casting of a resource to an interger differs based on the method of array creation.

This is both unexpected, and undocumented behaviour. I can see no reason why this would be a feature, rather than a bug.

I suggest the behaviour be changed to be consistant with both methods of array creation.

Part 2;
------
When an object is used as the key of an array (with behaviour changing between method of array creation), should n't the object be casted to an interger or the __toString method called?

When used with array() no error is thrown, the array is simply empty. With $foo[__object__] an error is thrown.

I suggest the behaviour of objects as array keys be changed to be consistant with that of resources.


The code in the reproduce code section demonstrates both aspects of the behavioural issue.

Reproduce code:
---------------
<?php
// Create a sample object
class id_obj { var $_id; function id_obj($id) { $this->_id = $id; } }
// Create two new objects
$id1 = new id_obj(1);
$id2 = new id_obj(2);
// Add them to an array with two different methods
$array = array(); $array[$id1] = 'foo';
$array2 = array ($id1 => 'id1', $id2 => 'id2');
echo "objects: first method:\n";
var_dump($array);
echo "objects: second method:\n";
var_dump($array2);

// Create two resources
$fp1 = fsockopen("www.example.com", 80, $errno, $errstr, 30);
$fp2 = fsockopen("www.example.com", 80, $errno, $errstr, 30);
// Add them to an array with two different methods
$resarray = array(); $resarray[$fp1] = 'fp1';
$resarray2 = array($fp1 => 'fp1', $fp2 => 'fp2');
// Show the result
echo "resources: first method:\n";
var_dump($resarray);
echo "resources: second method:\n";
var_dump($resarray2);
?>


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-06-22 17:59 UTC] aidan@php.net
Here's a little more information for Part 1, as I don't think I really explained myself.

For example:
<?php
// Let $fp1 and $fp2 be resources

// Array creation - Method #1
$resarray = array();
$resarray[$fp1] = 'fp1';
$resarray[$fp2] = 'fp2';

// Method #2
$resarray2 = array(
    $fp1 => 'fp1',
    $fp2 => 'fp2');
?>

For Method #1, PHP behaves as expected. The resource is casted to an interger and the array is populated.

For Method #2, PHP does not behave as I would expect. The resource is not casted, no error is thrown and the array is not populated.

This is demonstrated in the Reproduce Code section.
 [2004-06-22 18:05 UTC] aidan@php.net
I'm going to re-paste the Reproduce Code section, as it is rather confusing.

Part 1;
-------
Inconsistant behaviour between different methods of array creation.

<?php
// Create two resources
$fp1 = fsockopen("www.example.com", 80, $errno, $errstr, 30);
$fp2 = fsockopen("www.example.com", 80, $errno, $errstr, 30);

// Add them to an array with two different methods
$resarray = array(); $resarray[$fp1] = 'fp1';
$resarray2 = array($fp1 => 'fp1', $fp2 => 'fp2');

// Show the result
echo "resources: first method:\n";
var_dump($resarray);
echo "resources: second method:\n";
var_dump($resarray2);
?>

With Method #1 there is no problem.
With Method #2 no error is thrown, and the array is not populated.


Part 2;
-------
Failure of an object to cast itself to an interger or string. With the second method, failure to produce an error.

<?php
// Create a sample object
class id_obj { var $_id; function id_obj($id) { $this->_id = $id; } }

// Create two new instances
$id1 = new id_obj(1);
$id2 = new id_obj(2);

// Add them to an array with two different methods described above
$array = array(); $array[$id1] = 'foo';
$array2 = array ($id1 => 'id1', $id2 => 'id2');

// Check the results
echo "objects: first method:\n";
var_dump($array);
echo "objects: second method:\n";
var_dump($array2);
?>

In Method #1, an error is thrown (Illegal offset type). The array is not populated.

In Method #2, no error is thrown and the array is not populated.
 [2004-06-24 01:39 UTC] pollita@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

$a = array($objectvar => 'value');
$b = array($arrayvar => 'value');
$c = array($resourcevar => 'value');

Will now throw an E_WARNING "Illegal offset type" just like:

$a[$objectvar] = 'value';
$b[$arrayvar] = 'value';

already do.



$c[$resourcevar] = 'value'; 

will continue to work (for backwards compatability), however it will now throw an E_WARNING "Resource ID#X used as offset, casting to integer (X)" to strongly discourage this behavior.  

If this is a genuinely desired/used feature, then the error can be supressed using the standard @ operator or (preferrably) by manually casting the resource to an int:

@$c[$resourcevar] = 'value';
$c[(int)$resourcevar] = 'value';
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Thu Apr 17 21:01:56 2014 UTC