- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我在 php.net 之前将此发布在这里,以便更好地理解我在 PHP 5.x 和 7.x 之间看到的行为差异。
以下代码适用于 PHP 5.x 但不适用于 7.x
$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() 只是验证返回的行是否包含第二个参数中的值。
在 PHP 7(无论如何是 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[0] 现在是预期的引用。
在下一个 $cacheRow[0] = '2274' 时,当 $cacheRow 的副本在赋值期间创建时,生成的副本中的 $cacheRow[0] 不再是引用,只是一个指向的 zval原始字符串。
复制后,当分配到新的 $cacheRow[0] 时,它只是更改其 str 指针。
现在新的 $cacheRow[0] 指向与 oci8_statement 的 bindp->zval 不同的字符串,因此下一个 oci_execute 将提取旧的绑定(bind)值。
我可以通过确保涉及 $cache[0] 的分配(输入到和输出)是通过引用来解决这个问题。这避免了这个问题,因为 $cacheRow 数组永远不会分开。
我也可以用纯 PHP 代码重现它
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 参数的引用计数,我的原始测试在 PHP 之间的行为将相同5 和 PHP 7。话又说回来,我愿意相信这是预期的行为,我确实需要使用 assignment-by-ref。
最佳答案
试试刚刚上传到https://bugs.php.net/patch-display.php?bug_id=71148&patch=oci8-php7-bind&revision=latest的PHP OCI8补丁
关于php7、引用文献和 oci_bind_by_name,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38861588/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,
我对描述 PHP 内部工作原理、陷阱和一些高级功能的文献(互联网上的文章、杂志、书籍、播客 - 我真的不介意任何东西)很感兴趣。那里有这样的东西吗?我试着在谷歌上搜索,但大多数文章都是关于从 PHP
我知道这个问题的答案是否可能是主观的,(而且我还没有找到类似的问题)但我的问题如下: 我在互联网/文献上看到过不同来源的代码片段,其中一个来 self 项目中的队友。通常他们中的一些人会采用类似...
我是一名优秀的程序员,十分优秀!