首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >php7、参考文献和oci_bind_by_name

php7、参考文献和oci_bind_by_name
EN

Stack Overflow用户
提问于 2016-08-09 22:42:37
回答 2查看 429关注 0票数 3

我在这里发布这篇文章是为了更好地理解PHP5.x和7.x之间的行为差异。

以下代码适用于PHP5.x,但不适用于7.x

代码语言:javascript
复制
$conn = oci_connect('****', '****', '****', '****');
$stmt = oci_parse($conn, 'select record# from company where record#=:1');

$cache = [];

$cacheRow[0] = '2270';

oci_bind_by_name($stmt, ":1", $cacheRow[0], 2*strlen($cacheRow[0])+32);

$cache[0] = $cacheRow;

$result = runStmt($stmt);
checkResult($result, '2270');

$cacheRow = $cache[0];
$cacheRow[0] = '2274';
$cache[0] = $cacheRow;

$result = runStmt($stmt);
checkResult($result, '2274');

runStmt()只有oci_execute和oci_fetch_array。checkResult()只是验证返回的行是否包含第二个参数中的值。

在PHP7(至少是7.0.8和7.0.10 )中,对checkResult的第二个调用报告返回的行包含RECORD# 2270,而不是预期的2274。

通过gdb中的代码进行跟踪,下面是我拼凑起来的内容:

  • oci_bind_by_name的$variable参数最终被z/取消引用,在bindp->zval (oci8_statement.c:1250)中以简单字符串zval的形式存在。这是可以的,因为其他更简单的测试可以工作,只要所有的zval都指向同一个字符串。
  • 从oci_bind_by_name返回时,$cacheRow现在就像预期的那样成为一个参考。
  • 在下一个$cacheRow = '2274‘上,当在赋值期间复制$cacheRow时,结果副本中的$cacheRow不再是引用,只是指向原始字符串的zval。
  • 在将赋值复制到新的$cacheRow之后,它只是更改了它的str指针。

现在,新的$cacheRow指向与oci8 8_语句的bindp->zval不同的字符串,因此下一个oci_execute将提取旧的绑定值。

我可以通过确保涉及$cache0的作业是参考的来解决这个问题。这避免了这个问题,因为$cacheRow数组从未分开。

我也可以用纯PHP代码来再现这一点。

代码语言:javascript
复制
function bbn1(&$var)
{
}

function test1()
{
    $cache = [];

    $cacheRow[0] = '2270';

    bbn1($cacheRow[0]);
    $x = $cacheRow[0];

    $cache[0] = $cacheRow;

    $cacheRow = $cache[0];
    // Copy-on-write of $cacheRow does not preserve the reference in 
    // $cacheRow[0] because $cacheRow[0]'s refcount == 1
    // zend_array_dup_element in zend_hash.c
    $cacheRow[0] = '2274';

}

function bbn2(&$var)
{
    static $cache = [];
    $cache[] =& $var;
}

function test2()
{
    $cache = [];

    $cacheRow[0] = '2270';

    bbn2($cacheRow[0]);
    $x = $cacheRow[0];

    $cache[0] = $cacheRow;

    $cacheRow = $cache[0];

    // Copy-on-write of $cacheRow preserves the reference in 
    // $cacheRow[0] because $cacheRow[0]'s refcount != 1
    // zend_array_dup_element in zend_hash.c
    $cacheRow[0] = '2274';

}

由于我可以在纯PHP测试中得到不同的行为,这取决于我是否保持对bbn传递参数的引用,这使我认为,如果oci_bind_by_name增加了传入bind_var参数的拒绝次数,我的原始测试将在PHP5和PHP7之间的行为相同。然后,我愿意再次确信这是预期的行为,我确实需要使用赋值-by-ref。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-10-13 04:54:44

票数 1
EN

Stack Overflow用户

发布于 2016-08-17 00:56:32

参见https://bugs.php.net/bug.php?id=71148中的注释--PHP7ref正在计算对OCI8产生影响的更改(对于performance)。我们试验了在OCI8扩展中碰撞引用数,但这破坏了其他事情。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38861588

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档