How to use parameters by reference witch Laminas\Db\Adapter?

Some queries returns value in binded params.
For example, PL/SQL for Oracle database;
“declare result varchar2(1024); begin :result := ‘Some value…’; end;”
How to use parameters by reference witch Laminas\Db\Adapter\Driver\Oci8\Statement?

I give two samples.
First is pure OCI8 - works fine.
Second is laminas-db wrapper - don’t work.


  1. First is pure OCI8 - works fine.

`

<?php
// File name "testOci8BindOut.php"
$username = 'myUserLogin';
$password = 'myUserPassword';
$db = "my-database-host/myDatabaseSID";
try {
    $conn = oci_connect($username, $password, $db);
    if (!$conn) {
        $m = oci_error();
        trigger_error(htmlentities($m['message']), E_USER_ERROR);
    }
    $sql = <<<SQL
--set serveroutput on;
declare
  result varchar2(1024);
begin
  :result :=  'Now ' || to_char(sysdate, 'YYYY-MM-DD_HH24-MI-SS');
  --DBMS_OUTPUT.put_line(:result);
end;
SQL;
    $ociStatement = oci_parse($conn, $sql);
    $resultParamName = 'result';
    $resultParamValue = 'Current value will be replaced';
    oci_bind_by_name($ociStatement, $resultParamName, $resultParamValue, -1, SQLT_CHR);
    $ret = @oci_execute($ociStatement, OCI_COMMIT_ON_SUCCESS);
    if ($ret === true) {
        var_dump(array(
            'success' => true,
            'result' => $resultParamValue
        ));
    } else {
        $errData = oci_error($ociStatement);
        var_dump(array(
            'success' => false,
            'result' => $resultParamValue,
            'errData' => $errData
        ));
    }
    oci_free_statement($ociStatement);
    oci_close($conn);
} catch (Exception $err) {
    var_dump(array(
        'success' => false,
        'result' => 'Exception',
        'error' => $err
    ));
}

`
request to http://localhost:8080/tests/testOci8BindOut.php
answer
[
‘success’ => true,
‘result’ => ‘Now 2020-12-10_10-27-25’
]

As you can see, value in $resultParamValue replaced from ‘Current value will be replaced’ to ‘Now 2020-12-10_10-27-25’


  1. Second is laminas-db wrapper - don’t work.

`

<?php
// File name is "testOci8BindOutLaminas.php"
include_once '../../vendor/autoload.php';
$username = 'myUserLogin';
$password = 'myUserPassword';
$dbConnString =  "my-database-host/myDatabaseSID";
$driverConfig = [
    'driver' => 'Oci8',
    'hostname' => $dbConnString, //Синонимы ключа ['connection_string','connectionstring','connection','hostname','instance']
    'username' => $username,
    'password' => $password,
    //'schema' => 'myschema',
    'charset' => 'AL32UTF8', // Синонимы ключа ['character_set', 'charset', 'encoding']
    // 'unique'  => false, // true - oci_new_connect; false - oci_pconnect|oci_connect
    // 'persistent' => false, // true - oci_pconnect
    // 'session_mode' => ?,
    'profiler' => false,
    'platform_options' => [
        'quote_identifiers' => false
    ],
];
try {
    $dbAdapter = new Laminas\Db\Adapter\Adapter($driverConfig);
    $sql = <<<SQL
--set serveroutput on;
declare
  result varchar2(1024);
begin
  :result :=  'Now ' || to_char(sysdate, 'YYYY-MM-DD_HH24-MI-SS');
  --DBMS_OUTPUT.put_line(:result);
end;
SQL;
    $laminasStatement = $dbAdapter->createStatement($sql);
    $params =  [
        'result' => 'Current value will be replaced'
    ];
    $paramsContainer = new \Laminas\Db\Adapter\ParameterContainer($params);

    // $laminasResult = $laminasStatement->execute($params); // We lost referene to 'result' param

    $laminasStatement->setParameterContainer($paramsContainer); // We have reference to 'result' param by object "$paramsContainer"
    $laminasResult = $laminasStatement->execute();

    $resultParamValue = $paramsContainer->offsetGet('result');
    if ($laminasResult instanceof \Laminas\Db\Adapter\Driver\ResultInterface ) {
        var_dump(array(
            'success' => true,
            'result' => $laminasResult,
            '$resultParamValue' => $resultParamValue
        ));
    } else {
        $ociStatement = $laminasStatement->getResource();
        $errData = oci_error($ociStatement);
        var_dump(array(
            'success' => false,
            'result' => $resultParamValue,
            'errData' => $errData
        ));
    }
} catch (Exception $err) {
    var_dump(array(
        'success' => false,
        'result' => 'Exception',
        'error' => $err
    ));
}

`
request to http://localhost:8080/tests/testOci8BindOutLaminas.php
answer:
[
‘success’ => true,
‘result’ => …//object(Laminas\Db\Adapter\Driver\Oci8\Result)[…
‘$resultParamValue’ => ‘Current value will be replaced’
]

As you can see, value of ‘$resultParamValue’ is wrong.
Class Laminas\Db\Adapter\Driver\Oci8\Statement uses variable from by copy, instead ising by reference!