ID: 34934
User updated by: adove at booyahnetworks dot com
Reported By: adove at booyahnetworks dot com
Status: Bogus
Bug Type: SPL related
Operating System: WinXP, Linux
PHP Version: 5.0.5
Assigned To: dmitry
New Comment:
Ok, isset works as expected. IMHO, the behavior should be made
consistent across the one array_key_exists example that works.
Previous Comments:
------------------------------------------------------------------------
[2005-10-24 09:01:00] dmitry@php.net
After discussion with Marcus and Andi, this fix is reverted and bug
marked as bogus. array_... functions were not designed to work with
ArrayAccess interface, ao array_key_exists() shouldn't call
ofssetExists() at all.
You should use isset() instead of it.
------------------------------------------------------------------------
[2005-10-21 17:21:08] dmitry@php.net
Fixed in CVS HEAD and PHP_5_1.
------------------------------------------------------------------------
[2005-10-21 07:42:19] adove at booyahnetworks dot com
Here's a full code sample to replicate. Note I stripped out the method
comments. If you want them I can repost.
<?php
class MyArray extends ArrayObject
{
function __construct(
$mValue = array()
)
{
// Convert our value.
if(is_array($mValue))
{
$mValue = &$this->recurs($mValue);
}
elseif(is_object($mValue) && ($mValue instanceof ArrayObject))
{
// Get the raw array from our ArrayObject for handling.
$mValue = &$this->recurs($mValue->getArrayCopy(),
$constFlags);
}
elseif(null == $mValue)
{
$mValue = array();
}
elseif(!is_object($mValue))
{
// Turn primative into an indexed array.
$mValue = array($mValue);
}
// else - it's an object, enum its public properites.
parent::__construct($mValue);
}
protected function explodeKeyPath($mKeyPath)
{
return explode("/", trim($mKeyPath, "/"));
}
function offsetSet($mKey, $mValue)
{
$mKey = trim($mKey, "/");
if(stristr($mKey, "/"))
{
// A path was requested. Start out pointing to ourself.
$mRetval = $this;
$aKeyPathParts = $this->explodeKeyPath($mKey);
// Need to take the LAST path off. That's what we assign
our value too.
$strLastPathPart = array_pop($aKeyPathParts);
foreach($aKeyPathParts as $strPathPart)
{
// We know we our data are either a primative type or an
ArrayAccess.
if(($mRetval instanceof ArrayAccess) &&
array_key_exists($strPathPart, $mRetval)
)
{
$mRetval = $mRetval[$strPathPart];
}
else
{
// Need a new empty one of us and then point to
it!
$mRetval[$strPathPart] =
$this->newArrayObject($strPathPart, array(),
$this->getFlags());
$mRetval = $mRetval[$strPathPart];
}
}
// Now put our value!
$mRetval[$strLastPathPart] = $mValue;
}
else
{
if(is_array($mValue))
{
// Need to create a new instance of us!
$mValue = $this->newArrayObject($mKey, $mValue,
$this->getFlags());
}
parent::offsetSet($mKey, $mValue);
}
}
function offsetGet($mKey)
{
$mRetval = null;
$mKey = trim($mKey, "/");
if(stristr($mKey, "/"))
{
// A path was requested. Start out pointing to ourself.
$mRetval = $this;
$aKeyPathParts = $this->explodeKeyPath($mKey);
foreach($aKeyPathParts as $strPathPart)
{
// We know we our data are either a primative type or an
ArrayAccess.
if(($mRetval instanceof ArrayAccess) &&
array_key_exists($strPathPart, $mRetval)
)
{
$mRetval = $mRetval[$strPathPart];
}
else
{
$mRetval = null;
break;
}
}
}
else
{
$mRetval = parent::offsetGet($mKey);
}
return $mRetval;
}
function offsetUnset($mKey)
{
$mKey = trim($mKey, "/");
if(stristr($mKey, "/"))
{
// A path was requested. Start out pointing to ourself.
$oArray = $this;
$aKeyPathParts = $this->explodeKeyPath($mKey);
// Need to take the LAST path off. That's what we unset.
$strLastPathPart = array_pop($aKeyPathParts);
foreach($aKeyPathParts as $strPathPart)
{
// We know we our data are either a primative type or an
ArrayAccess.
if(($oArray instanceof ArrayAccess) &&
array_key_exists($strPathPart, $oArray)
)
{
$oArray = $oArray[$strPathPart];
}
else
{
// Hmmmm... bad path... Die. Nothing will happen
below.
break;
}
}
// Now unset our value!
if(($oArray instanceof ArrayAccess) &&
array_key_exists($strLastPathPart, $oArray)
)
{
unset($oArray[$strLastPathPart]);
}
// else - Bad path.. do nothing...
}
else
{
parent::offsetUnset($mKey);
}
}
function offsetExists($mKey)
{
$bRetval = false;
$mKey = trim($mKey, "/");
if(stristr($mKey, "/"))
{
// A path was asked for. Start at our root.
$mPathData = $this;
$aKeyPathParts = $this->explodeKeyPath($mKey);
foreach($aKeyPathParts as $strPathPart)
{
// We know we our data are either a primative type
(non-array)
// or an ArrayAccess.
if(($mPathData instanceof ArrayAccess) &&
array_key_exists($strPathPart, $mPathData)
)
{
// So far so good... True will remain unless a
latter path
// part is invalid.
$bRetval = true;
// Set for next loop.
$mPathData = $mPathData[$strPathPart];
}
else
{
// Nope, bad path.
$bRetval = false;
break;
}
}
}
else
{
$bRetval = parent::offsetExists($mKey);
}
return $bRetval;
}
protected function &recurs(
$aData
)
{
$aRetval = $aData;
foreach($aRetval as $mKey => &$mValue)
{
// If we have a primative array or MyArray-based instance
// convert them to us... Buhahahahahah!!!
if(is_array($mValue) ||
(is_object($mValue) && ($mValue instanceof
ArrayObject))
)
{
$aRetval[$mKey] = new MyArray($mValue);
}
// else - leave it alone!
}
return $aRetval;
}
}
$a = array(
"test" => array(
"one" => "dunno",
"two" => array(
"peekabo" => "do you see me?",
"anyone" => array("there")
)
)
);
$oArray = new ArrayObject($a);
$oMyArray = new MyArray($a);
$bWorks1 = array_key_exists("test", $oArray);
$bWorks2 = array_key_exists("test", $oMyArray);
$bShouldWorkButDoesNot = array_key_exists("test/two/peekabo",
$oMyArray);
$bDirectWorks = $oMyArray->offsetExists("test/two/peekabo");
$bDirectBadPathWorksToo =
$oMyArray->offsetExists("test/two/notfound");
?>
------------------------------------------------------------------------
[2005-10-20 19:30:56] tony2001@php.net
Provide a short but complete reproduce script then.
The code you've pasted in the report is not complete - there is no
declaration of MyArray class.
------------------------------------------------------------------------
[2005-10-20 19:28:17] adove at booyahnetworks dot com
Same behavior in both the latest 5.0.5 and 5.1...
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
http://bugs.php.net/34934
--
Edit this bug report at http://bugs.php.net/?id=34934&edit=1