Re: Objects as array key names??

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, Mar 15, 2008 at 6:02 PM, Jim Lucas <lists@xxxxxxxxx> wrote:

> It has been brought to my attention that with Perl and Ruby, you can use
> Objects as the value of the key within an array.  The examples that were
> shown to me make me think that this would be an awesome ability to have
> within PHP.


this is essentially already possible, w/ some limitations due to type
checking w/in php.  remember that spl thing that everyone loves to bash?
well thats what makes this remotely possible.  you can put elements in using
array notation and objects as keys, but thats about as far as it goes.  some
of the global functions like array_key_exists() dont work because they check
the type of the $needle argument internally.  also, iteration via foreach
does not work correctly.  implementing the Iterator interface to tell php
how to iterate over the structure works as expected however a strange error
is raised when trying to retrieve the current key: PHP Warning:  Illegal
type returned from ObjectArray::key().  LAME, *sigh*.  anyway, its still
pretty cool, and part of what youre looking for.  i might see if marcus
could tell me something about a condition w/in the code for key() inside of
php that would allow this to actually work, because imho, if its overridden
the internal check thats currently in place should be bypassed.  also
forgive the long post (theres code to follow ;))

<?php
class ObjectArray implements ArrayAccess, Countable, Iterator{
        private $indexes = array();
        private $values = array();
        private $curOffset = -1;
        private $totalElements = 0;

/// Countable interface
        public function count() {
                return $this->totalElements;
        }

/// ArrayAccess interface
        public function offsetExists($offset) {
                $offsetExists = false;
                foreach($this->indexes as $curIndex => $curObj) {
                        if($curObj === $offset) {
                                $offsetExists = true;
                                $this->curOffset = $curIndex;
                                break;
                        }
                }
                return $offsetExists;
        }

        public function offsetGet($offset) {
                if($this->offsetExists($offset)) {
                        return $this->values[$this->curOffset];
                }
        }

        public function offsetSet($offset, $value) {
                if(!$this->offsetExists($offset)) {     // grab index of
offset
                        /// set value of offset for first time
                        $this->indexes[] = $offset;
                        $this->values[] = $value;
                        $this->totalElements++;
                } else {
                        /// update value of offset
                        $this->values[$this->curOffset] = $value;
                }
        }

        public function offsetUnset($offset) {
                if($this->offsetExists($offset)) {
                        unset($this->indexes[$this->curOffset]);
                        unset($this->values[$this->curOffset]);
                        $this->totalElements--;
                }
        }

/// Iterator interface
        public function current() {
                return $this->values[$this->curOffset];
        }

        public function key() {
                return $this->indexes[$this->curOffset];
        }

        public function next() {
                $this->curOffset++;
        }

        public function rewind() {
                $this->curOffset = 0;
        }

        public function valid() {
                $isValid = false;
                if(isset($this->indexes[$this->curOffset]) &&
                        isset($this->values[$this->curOffset])) {
                        $isValid = true;
                }
                return $isValid;
        }
}

$objArr = new ObjectArray();

/// make $a & $c the same so == comparison should succeed
$a = new StdClass();
$b = new StdClass();
$b->a = 'spl is the shit ;)';
$c = new stdClass();

// test putting a value in w/ object as index
$objArr[$a] = 5;
echo $objArr[$a] . PHP_EOL;
// test changing the value
$objArr[$a] = 6;
echo $objArr[$a] . PHP_EOL;
// note we can put in objs that pass == test, because internally
// we use ===
$objArr[$c] = 7;

echo 'count: ' . count($objArr) . PHP_EOL;
$objArr[$b] = 8;
echo 'count: ' . count($objArr) . PHP_EOL;

var_dump($objArr[$a] == $objArr[$b]);   // false
var_dump($objArr[$a] == $objArr[$c]);   // false

/// broken even w/ Iterator implemented :(
foreach($objArr as $key => $val) {
        if($a === $key) {
                echo "keyFound: {$objArr[$a]}" . PHP_EOL;
                break;
        }
}

-nathan

[Index of Archives]     [PHP Home]     [Apache Users]     [PHP on Windows]     [Kernel Newbies]     [PHP Install]     [PHP Classes]     [Pear]     [Postgresql]     [Postgresql PHP]     [PHP on Windows]     [PHP Database Programming]     [PHP SOAP]

  Powered by Linux