- 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/
我需要将 float 绑定(bind)到 OCI 语句。 我在做什么: $price = 0.1 oci_bind_by_name($resource, 'price', $price); 在我的 O
什么是 oci_bind_by_name为了?我阅读了 php 手册,但什么也看不懂。请有人给我解释一下 看这个例子: $name = "O'Reilly"; $stid = oci_parse($m
我在 php.net 之前将此发布在这里,以便更好地理解我在 PHP 5.x 和 7.x 之间看到的行为差异。 以下代码适用于 PHP 5.x 但不适用于 7.x $conn = oci_connec
当我向包含 1000 多个条目的表中插入一行并尝试返回行 ID(无论是来自自动增量触发器/序列,还是来自在插入语句中手动设置值)时,我得到一个截断值: $db = OCILogon(DATABASE_
我的代码是这样的: $s = ociparse($conn, "SELECT u.email, u.city FROM tickets t, users u WHERE t.userId = u.us
我有以下内容: $ARTIFACT_NAME = $_POST['ArtifactName']; $ARTIFACT_TYPE = $_POST['ArtifactType'];
我正在尝试从 Oracle 程序包中调用一个函数,但出现此错误: PHP Fatal error: Only variables can be passed by reference 这是我的代码:
我是一名优秀的程序员,十分优秀!