我有像这样的csv
product_id,stock_unit
1, ,
2, ,
3, ,
4, ,
5, ,
6, ,
现在在我的PHP代码中,我将获得产品ID并对数据库运行查询以从数据库中获取库存单元。获取产品的库存单元后,脚本应将其更新为csv而不更改任何名称。
所以我所有的代码都是这样的
<?php
$mysqli = new mysqli("localhost", "username", "password", "database");
/* check connection */
if ($mysqli->connect_errno) {
printf("Connect failed: %s\n", $mysqli->connect_error);
exit();
}
$file = "update_pd.csv";
$csv = array_map("str_getcsv", file($file,FILE_SKIP_EMPTY_LINES));
$keys = array_shift($csv);
$stock_array = array();
if (($handle = fopen($file, "r")) !== FALSE) {
fgetcsv($handle);
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$stock_array[] = get_data($data[0]);
}
fclose($handle);
}
//print_r($stock_array);
$handle = fopen("update_pd.csv", "a");
fputcsv($handle, $stock_array);
function get_data($id) {
if( !empty($id) ) {
$result = $mysqli->query("SELECT `stock_unit` FROM `products` WHERE `product_id` = ".$id." ");
if( $result ) {
while($row = $result->fetch_assoc()) {
return $row['stock_unit'];
}
}
}
}
这里写的是csv我的意思是数据写在最后一行,所有旧的数据都存在。脚本应根据csv文件中的产品ID写入库存数量,而不对csv头和文件名进行任何更改。有人能告诉我怎么做吗?任何帮助和建议都会非常明显。
更新
由于库存单位将从数据库中获取。输出应该像
product_id,stock_unit
1, 24,
2, 22,
3, 37,
4, 46,
5, 89,
6, 96,
答案 0 :(得分:0)
如果我找到你,你的代码正在运行,但会附加数据而不是覆盖文件。这是因为你在做:
$handle = fopen("update_pd.csv", "a");
将以追加模式打开文件。要覆盖它,您需要在写入模式下打开它,例如
$handle = fopen("update_pd.csv", "w");
中mode
参数的说明
'w' - 仅供写作;将文件指针放在文件的开头,并将文件截断为零长度。如果该文件不存在,请尝试创建它。
'a' - 仅供写作;将文件指针放在文件的末尾。如果该文件不存在,请尝试创建它。在这种模式下,fseek()无效,写入总是附加。
但是,您在$mysqli
函数中使用get_data
变量,但该变量未在该范围内定义,因此它根本不起作用。确保将变量传递给函数,例如
function get_data($mysqli, $id) {
然后像这样调用它:
get_data($mysqli, $data[0]);
但是如果你的查询基本相同并且只在WHERE
子句中使用不同的值,那么使用Prepared Statements可以更快地执行查询。
在创建mysqli实例后在全局范围内定义:
$query = $mysqli->prepare(
"SELECT `stock_unit` FROM `products` WHERE `product_id` = ?
);
然后,不是将$mysqli
变量传递给get_data
,而是传递$query
变量。将get_data
函数更改为此代码:
function get_data($query, $id) {
if( !empty($id) ) {
$query->bind_param("i", $id);
$result = $query->execute($query);
…
作为替代方案,不要单独提取股票单位,而应考虑:
$file = "file.csv";
$data = array_map('str_getcsv', file($file, FILE_SKIP_EMPTY_LINES));
$ids = array_filter(array_column($data, 0), 'is_numeric');
$ids = implode(',', $ids);
然后使用WHERE … IN和INTO OUTFILE在一个查询中完成所有操作:
SELECT "product_id", "stock_unit"
UNION ALL
SELECT product_id, stock_unit
FROM products
WHERE product_id IN ($ids)
INTO OUTFILE '/path/to/update_pd.csv'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY ',\n';
请注意,由于SQL注入攻击的风险,将变量插入查询是不好的做法。但是既然我们确保id是数字的,那么在这种情况下它是可以的。另外,mysqli does not allow easy binding of values in WHERE … IN queries。