PHP SeekableIterator: catch OutOfBoundsException or check valid () method?

So, I'm not sure if this is a buggy design with PHP, or if there is clear logic to handle inconsistent results for the same interface.

The SeekableIterator interface has two methods ( seekand valid) that either conflict with each other or must work in sequence with each other, but I see both.

The documentation for the interface says that it seekshould throw an OutOfBoundsException class exception, but this seems to negate usefulness validif the iterator position is not updated (by making validreturn false) before throwing the exception (which apparently should be caught).

Three test examples

Example 1

A custom class that implements SeekableIterator, as shown in the example in the docs:

Grade:

class MySeekableIterator implements SeekableIterator {

    private $position;

    private $array = array(
        "first element",
        "second element",
        "third element",
        "fourth element"
    );

    /* Method required for SeekableIterator interface */

    public function seek($position) {
        if (!isset($this->array[$position])) {
            throw new OutOfBoundsException("invalid seek position ($position)");
        }

        $this->position = $position;
    }

    /* Methods required for Iterator interface */

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

    public function current() {
        return $this->array[$this->position];
    }

    public function key() {
        return $this->position;
    }

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

    public function valid() {
        return isset($this->array[$this->position]);
    }
}

Example 1. Test:

echo PHP_EOL . "Custom Seekable Iterator seek Test" . PHP_EOL;

$it = new MySeekableIterator;

$it->seek(1);
try {
    $it->seek(10);
    echo $it->key() . PHP_EOL;
    echo "Is valid? " . (int) $it->valid() . PHP_EOL;
} catch (OutOfBoundsException $e) {
    echo $e->getMessage() . PHP_EOL;
    echo $it->key() . PHP_EOL; // outputs previous position (1)
    echo "Is valid? " . (int) $it->valid() . PHP_EOL;
}

Test result 1:

Custom Seekable Iterator seek Test
invalid seek position (10)
1
Is valid? 1

Example 2:

Using the built-in ArrayIterator :: seek

Test Code 2:

echo PHP_EOL . "Array Object Iterator seek Test" . PHP_EOL;

$array = array('1' => 'one',
               '2' => 'two',
               '3' => 'three');

$arrayobject = new ArrayObject($array);
$iterator = $arrayobject->getIterator();

$iterator->seek(1);
try {
    $iterator->seek(5);
    echo $iterator->key() . PHP_EOL;
    echo "Is valid? " . (int) $iterator->valid() . PHP_EOL;
} catch (OutOfBoundsException $e) {
    echo $e->getMessage() . PHP_EOL;
    echo $iterator->key() . PHP_EOL;  // outputs previous position (1)
    echo "Is valid? " . (int) $iterator->valid() . PHP_EOL;
}

Test result 2:

Array Object Iterator seek Test
Seek position 5 is out of range
1
Is valid? 1

Example 3:

Using native DirectoryIterator :: seek

Test 3 Code:

echo PHP_EOL . "Directory Iterator seek Test" . PHP_EOL;

$dir_iterator = new DirectoryIterator(dirname(__FILE__));
$dir_iterator->seek(1);
try {
    $dir_iterator->seek(500);  // arbitrarily high seek position
    echo $dir_iterator->key() . PHP_EOL;
    echo "Is valid? " . (int) $dir_iterator->valid() . PHP_EOL;
} catch (OutOfBoundsException $e) {
    echo $e->getMessage() . PHP_EOL;
    echo $dir_iterator->key() . PHP_EOL;
    echo "Is valid? " . (int) $dir_iterator->valid() . PHP_EOL;
}

Test Result 3:

Directory Iterator seek Test
90
Is valid? 0

So, how could one reasonably know if one should use valid()to confirm the correct position after seek($position), and also anticipate that it seek()can throw an exception instead of updating the position, so that valid()returns true

+4
source share
1 answer

It seems that the method directoryIterator::seek()is not implemented here with an exception. Instead, it simply does not return a value, and let it valid()process it.

ArrayObject::seek() "" OutOfBoundsException.

: ArrayObject (, , ) , , , , . , DirectoryIterator , . , valid() next() . key() , valid() 0.

, .

: Directory , reset , . , 1000 $it->seek(999), 999 .

IMHO, DirectoryIterator seekableIterator. , , directoryIterator , . , .

seekableIterator , - . SPL LimitIterator. :

$it = new ArrayIterator(range('a','z'));
$it = new LimitIterator($it, 5, 10));

limitIterator , seekableIterator, seek(), 5- , 5- .

: seekableIterator, . , , , .

: seek() . DirectoryIterator ( , ) seekableIterator, , seek() ( "" ).

+4

Source: https://habr.com/ru/post/1589443/


All Articles