3

I have class which implements Countable, ArrayAccess, Iterator and Serializable. I have a public varibale $data, in array form. And my iteration implementions:

public function rewind() { return reset($this->data); }
public function current() { return current($this->data); }
public function key() { return key($this->data); }
public function next() { return next($this->data); }
public function valid() { return isset($this->data[$this->key()]); }

Well everything works with foreach loop, but if i manually call current($arrayObject), it returns whole $data array, not teh current in it. I can do current($arrayObject->data), but like to keep native array functionality as where i can.

This is php behavior right? (not mine code bug) And is there any workaround this, without custom function(fingers crossed)?

[EDIT] Simplified version of full class(working):

$arrayObject = mysqli_fetch_object($this->result_id, "simpleMysqliResult ", array(array(
        "fields" => array( "field1", "field2", "field3" )
    )));
class simpleMysqliResult implements Countable, ArrayAccess, Iterator, Serializable {

    public $data = array();

    public function __construct($input) {
        extract($input);
        foreach ($fields as $field) {
            $this->data[$field] = $this->{$field};
            unset($this->{$field});
        }
    }

    public function &toArray() { return $this->data; }
    public function offsetGet($index) { return $this->data[$index]; }
    public function offsetSet($index, $value) { $this->data[$index] = $value; }
    public function offsetUnset($index) { unset($this->data[$index]); }
    public function offsetExists($index) { return $this->offsetGet($index) !== null; }
    public function count() { return count($this->data); }
    public function rewind() { return reset($this->data); }
    public function current() { return current($this->data); }
    public function key() { return key($this->data); }
    public function next() { return next($this->data); }
    public function valid() { return isset($this->data[$this->key()]); }
    public function serialize() { return serialize($this->data); }
    public function unserialize($str) { return $this->data = unserialize($str); }

    public function __call($func, $argv) {
        if (!is_callable($func) || substr($func, 0, 6) !== 'array_')
        {
            throw new BadMethodCallException(__CLASS__.'->'.$func);
        }
        return call_user_func_array($func, array_merge(array($this->data), $argv));
    }

}
4
  • 1
    Show the full class. I have seen similar implementations, which works fine. Commented Jan 10, 2012 at 12:30
  • Added, simplified it a bit, also, i'm extending this class but overriding only Arrayacces implementions Commented Jan 10, 2012 at 12:41
  • Have you thought about extending ArrayObject? It provides a lot of the functionality you require. Commented Jan 10, 2012 at 12:43
  • I'm using my own implemetion cause is need to $data be in an array not object params. I'm extendin mysqliResult class with this one i coiped here and there is some logic going on in offsetSet() and offetGet(). And also this isolates mysql variables from object variables. Right now the new class has 8 variables + 2 static variables. And on of these 8 can match a mysql field name. Commented Jan 10, 2012 at 12:51

1 Answer 1

1

Try placing your data in private mode. I suspect you have an external procedure playing around with it and making changes to it. I copied your class and altered your constructor a bit since i didn't have the same input as you and i get no strange behavior. Ultimately, you might want to look into why you extract($input) also, just use $input['fields'] or $input->fields as you see fit, it'll still work.

Here are my corrections:

private $data = array();

public function __construct($input) {
    foreach($input['fields'] as $field) {
        $this->data[$field] = $input[$field];
    }
}

Here are my tests

$data = array('fields' => array('id', 'name'), 'id' => 1, 'name' => 'Franco');
$smr = new simpleMysqliResult($data);
var_dump($smr->current());
var_dump($smr->current());
var_dump($smr->current());
var_dump($smr->current());
var_dump($smr->next());
var_dump($smr->current());
var_dump($smr->current());

And my output is ok

int(1) int(1) int(1) int(1) string(6) "Franco" string(6) "Franco" string(6) "Franco" 

So like i said, i think your problem mainly lies in the fact that your $data is public and something else is playing with it.

OR

It lies in your constructor that i had to fix to make it work on my side.

Good luck

Sign up to request clarification or add additional context in comments.

4 Comments

Ups, didn look so closely, you are using $smr->current(), i guess that would work for me to, but my problem vas with current($smt)..
Yep, using $smr->current() it work for but current($smt). And if i'll put $data as private then current($smt) outputs an empty array. So what i want to accomplish doesn't have support from php yet. Goodbye backwards compability..
Ohhhh ok, yeah, i don't think you can do that. The function current inside your class is not automatically called when you call current on your object. The current() implementation only works for the iterator implementation so that FOREACH may work fine. I hadn't understood your question. I don't think there are any possible SPL implementations that exist for that, let me look just in case but i don't think you can do that
And the answer is no, there doesn't seem to be any SPL feature that allows you to use CURRENT on an object and map it to the current function in your object, sorry about that...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.