Question about Result::$statementMode

How would one go about changing the statement mode for the laminas adapter driver pdo result? I see there is two class constants that define the statement mode, but there is no setter to allow modifying which mode the Result is to use. I’m having a hard time understanding why two modes are considered if there is no way to utilize:

public const STATEMENT_MODE_SCROLLABLE

I see it similarly to how you have already described it. There is actually no method to change Result::$statementMode. Since it is declared as protected, one can 't change this class member publicly. The only possibility I can think of off the top of my head is extending the result class.

<?php

declare(strict_types=1);

namespace Marcel\Db\Adapter\Driver\Pdo;

use Laminas\Db\Adapter\Driver\Pdo\Result;

class MyOwnSimpleResult extends Result
{
    public function setStatementMode(string $statementMode): void
    {
        $this->statementMode = $statementMode;
    }
}

$result = new Result();
$result->setStatementMode(Result::STATEMENT_MODE_SCROLLABLE);
$result->init(...);

The other way around would be changing the protected class member via reflection. However, both options look too complicated for me. It would actually be easier if there was a simple setter method. At the moment, I don’t see anything that could speak against it. Or am I missing something here? The Iterator interface does not implement any functionality, which is associated with a forward only functionality.

1 Like

Yea, have been thinking the same. I suppose the cleanest way to test it will be via the event feature and just attach a listener and modify it via reflection.

So here is how I tackled it initially. The following is just the initial test code.

I created a new feature with a preInitialize method:

<?php

declare(strict_types=1);

namespace Axleus\Db\Feature;

use Axleus\Db\Feature\ScrollablePdoResult\Result;
use Laminas\Db\Adapter\Driver\Pdo\Pdo;
use Laminas\Db\TableGateway\Feature\AbstractFeature;

final class ScrollablePdoResultFeature extends AbstractFeature
{
    public function preInitialize()
    {
        /** @var Pdo */
        $driver = $this->tableGateway->getAdapter()->getDriver();
        if (!  $driver instanceof Pdo) {
            return;
        }
        $resultPrototype = new Result();
        $resultPrototype->setStatementMode(Result::STATEMENT_MODE_SCROLLABLE);
        $driver->registerResultPrototype($resultPrototype);
    }
}

And a subclassed Result class as mentioned by @ezkimo

<?php

declare(strict_types=1);

namespace Axleus\Db\Feature\ScrollablePdoResult;

use Axleus\Db\Exception\InvalidArgumentException;
use Laminas\Db\Adapter\Driver\Pdo;

use function get_class;
use function in_array;

final class Result extends Pdo\Result
{
    private const ALLOWED_MODES = [
        self::STATEMENT_MODE_SCROLLABLE,
        self::STATEMENT_MODE_FORWARD
    ];

    public function setStatementMode(string $mode): void
    {
        if (! in_array($mode, self::ALLOWED_MODES)) {
            throw new InvalidArgumentException(
                '$mode must be one of ' . get_class($this) . '::ALLOWED_MODES received: ' . $mode
            );
        }
        $this->statementMode = $mode;
    }
}

Usage is the same as any other laminas-db TableGateway feature.

@froschdesign is there any reason you can think of that this should not be done?