我可以理解,
array_unshift($row ,$fmt)
就是让$row
变成下面这样,所以有效数据是从位置1到8。
array(9) {
[0] =>
string(8) "ssssssss"
[1] =>
string(4) "7934"
[2] =>
string(6) "MILLER"
[3] =>
string(5) "CLERK"
[4] =>
string(4) "7782"
[5] =>
string(19) "1980-12-23 00:00:00"
[6] =>
string(4) "1300"
[7] =>
string(0) ""
[8] =>
string(2) "10"
}
<?php
$tname = 'emp';
$fname = 'emp.csv';
$rownum = 0;
function create_insert_stmt($table, $ncols)
{//create insert sql
$stmt = "insert into " . $table . " values(";
foreach (range(1, $ncols) as $i) {
$stmt .= " ? ,";
}
$stmt = preg_replace("/,$/", ');', $stmt);
return $stmt;
}
$db = new mysqli('localhost', 'root', 'root', 'scott');
$db->autocommit(false);
$res = $db->prepare("select * from " . $tname);
$ncols = $res->field_count;
$res->free_result();
$ins = create_insert_stmt($tname, $ncols);
$fmt = str_repeat("s", $ncols);
$res = $db->prepare($ins);
$fp = new SplFileObject($fname, "r");
while ($row = $fp->fgetcsv()) {
if (strlen(implode('', $row)) == 0) {
continue;
}
array_unshift($row, $fmt); //put 'ssssssss' into array $row
foreach (range(1, $ncols) as $i) {
$row[$i] = &$row[$i];
//what does this mean ,when i remove & why it can`t work
}
call_user_func_array(array(&$res, "bind_param"), $row);
$res->execute();
$rownum++;
}
$db->commit();
print $rownum . "rows inserted into " . $tname . "\n<br>";
我感到困惑的是为什么有必要使变量成为对其自身的引用。好像没有它我就做不到,那么它有什么作用呢?
您正在使用的函数
mysqli_stmt_bind_param
期望参数通过引用传递。您所看到的是针对一个非常古老的 PHP 错误的 hack(或者更准确地说是一种设计选择)。当调用动态地通过引用获取参数的函数时,您会收到警告,并且在 PHP 7.1 之前,它甚至根本无法工作。但是有一个可用的技巧:当调用 call_user_func_array
时,如果将参数数组中的元素设置为对变量的引用,它将在没有任何警告的情况下工作。请参阅 是否可以使用 call_user_func_array() 通过引用传递参数?
当 PHP 5.6 出现时,这种 hack 就变得没有必要了。 PHP 拥有可变参数函数和展开运算符 (
...
)。 您不再需要使用 call_user_func_array
来调用带有参数列表的函数。您现在可以这样做:
$stmt->bind_param($types, ...$arguments);
新的扩展运算符在传递参数作为引用时没有问题。
从 PHP 8.1 开始,事情变得更加简单,根本不需要
bind_param
:
$stmt = $mysqli->prepare(/* */);
$stmt->execute($arguments);
从 PHP 8.2 开始,这是最简单的:
$result = $mysqli->execute_query(/* */, $arguments);