PHP array_push() 返回整数?解决及数组操作优化
2025-03-24 16:25:48
解决 array_push()
返回整数而不是数组的问题
最近遇到一个挺常见的问题,在使用 array_push()
函数向数组添加元素时, 获取到的返回值不是预期的包含新元素的数组,而是一个表示数组新长度的整数。这导致后续操作没法按预期进行,比如我这想把数据写进数据库,结果就卡壳了。
一、 问题根源:array_push()
的特性
array_push()
这个函数,它的主要作用是向数组的末尾添加一个或多个元素。重点来了!它的返回值是添加元素 后 数组的新长度(也就是一个整数),而不是修改后的数组本身。 很多人,包括我刚开始的时候,都会误以为它会返回更新后的数组,然后就把这个返回值拿去用了, 自然就会出问题。
看下PHP官方文档关于array_push()
的定义就能更明白了:
int array_push ( array &$array , mixed $value1 [, mixed $... ] )
返回值是int
类型, 这清楚的表明了返回值是什么。
二、 解决方案
明白了问题原因, 解决起来就简单多了。下面列出几个常见的修正方法:
1. 直接操作原数组
既然 array_push()
会直接修改原数组, 那咱们直接用原数组不就好了。
原理: array_push()
函数会直接修改传入的数组(通过引用传递),所以不需要它的返回值。
代码示例:
$i = 1;
$test = array(); // 在循环外初始化数组
foreach ($row_result as $results)
{
$f = fopen("jigsaw.csv", "a+"); //这行建议放到循环外.
$content = $results->findElement(WebDriverBy::className('seo-company'))->getText();
if ($i == 1)
{
$Orgnisation_name = $content;
array_push($test, $Orgnisation_name); // 直接操作$test
echo "\n";
}
if ($i == 2)
{
echo $Website = $content;
echo "\n";
array_push($test, $Website); // 添加更多元素
}
if ($i == 3)
{
echo $HeadQuarters = $content;
echo "\n";
array_push($test, $HeadQuarters);
}
if ($i == 4)
{
echo $Phone = $content;
echo "\n";
array_push($test, $Phone);
}
if ($i == 5)
{
echo $Industries = $content;
echo "\n";
array_push($test, $Industries);
}
if ($i == 6)
{
echo $Employees = $content;
echo "\n";
array_push($test, $Employees);
}
if ($i == 7)
{
echo $Revenue = $content;
echo "\n";
array_push($test, $Revenue);
}
if ($i == 8)
{
echo $Ownership = $content;
echo "\n";
array_push($test, $Ownership);
}
//循环所有条件后,再操作。
$i++;
}
//循环结束后,可以安全地使用$test.
print_r($test); // 打印查看 $test
//后续数据库写入,使用 $test 即可。
fclose($f);
关键是: 把 $test
数组初始化放在foreach
循环外部,然后每次符合if 条件时, 直接对 $test
数组进行array_push
。 循环结束, $test
数组就已经是完整的数据。
2. 使用数组字面量语法(更简洁)
PHP 里有个更简单的添加元素的方法, 就是用[]
。
原理: $array[] = $value;
这种语法等同于将 $value
添加到 $array
的末尾。
代码示例:
$i = 1;
$test = array(); // 在循环外初始化数组
foreach ($row_result as $results)
{
$f = fopen("jigsaw.csv", "a+");//这行建议放到循环外.
$content = $results->findElement(WebDriverBy::className('seo-company'))->getText();
if ($i == 1)
{
$Orgnisation_name = $content;
$test[] = $Orgnisation_name; // 更简洁的添加方式
echo "\n";
}
if ($i == 2)
{
echo $Website = $content;
echo "\n";
$test[] = $content;
}
if ($i == 3)
{
echo $HeadQuarters = $content;
echo "\n";
$test[] = $content;
}
if ($i == 4)
{
echo $Phone = $content;
echo "\n";
$test[] = $content;
}
if ($i == 5)
{
echo $Industries = $content;
echo "\n";
$test[] = $content;
}
if ($i == 6)
{
echo $Employees = $content;
echo "\n";
$test[] = $content;
}
if ($i == 7)
{
echo $Revenue = $content;
echo "\n";
$test[] = $content;
}
if ($i == 8)
{
echo $Ownership = $content;
echo "\n";
$test[] = $content;
}
$i++;
}
//循环结束后,可以安全地使用$test.
print_r($test);
//后续数据库写入,使用 $test 即可。
fclose($f);
这种方法写起来更短,更清晰。是我个人更推荐的。
3. 合并数组 (适用于多个数组)
如果你需要把几个数组合并成一个,可以用 array_merge()
。
原理: array_merge()
函数可以将一个或多个数组合并成一个新数组。
代码示例: (这个例子和原问题相关性不大, 但可以作为合并数组的一个例子)
$array1 = [1, 2, 3];
$array2 = [4, 5, 6];
$mergedArray = array_merge($array1, $array2);
print_r($mergedArray); // 输出:Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 )
这个array_merge
和题目不太一样, 只是在合并数组的场景中非常好用。
4.改进原代码的结构(代码更清晰)
你的原代码里用了很多 if ($i == x)
这种形式, 这种方式不太好维护,而且容易出错。建议将数据和对应的字段名关联起来。
$test = array(); // 在循环外初始化
$fieldNames = [
1 => 'Orgnisation_name',
2 => 'Website',
3 => 'HeadQuarters',
4 => 'Phone',
5 => 'Industries',
6 => 'Employees',
7 => 'Revenue',
8 => 'Ownership',
];
$i=1;
$f = fopen("jigsaw.csv", "a+"); // 移到循环外
foreach ($row_result as $results)
{
$content = $results->findElement(WebDriverBy::className('seo-company'))->getText();
if (isset($fieldNames[$i]))
{
$fieldName = $fieldNames[$i];
// echo $fieldName .": " . $content ."\n"; //用于调试.
$test[$fieldName] = $content; // 存储到关联数组中
}
$i++;
if($i > 8)
{ // 如果数据超过了8项.为了安全.加个终止循环的判定
break;
}
}
fclose($f);
print_r($test);
这样做的好处:
- 代码更容易读懂。
- 如果要添加或删除字段,只需要修改
$fieldNames
数组。 - 把值直接关联到对应的key. 方便后续操作. 例如
$test['Phone']
就能获取到电话号码。 - 加入了
$i>8
的保护机制. 避免潜在错误。
再进一步优化,考虑到你这是从网页上抓取数据,其实完全可以在一次循环里获取所有信息, 而不用$i做多次判定:
$f = fopen("jigsaw.csv", "a+"); // 移到循环外
$all_data = []; //总数据.
foreach ($row_result as $results) {
$data = [];
$elements = $results->findElements(WebDriverBy::className('seo-company')); //找到所有的元素
//按照顺序赋予key
$keys = ['Orgnisation_name','Website', 'HeadQuarters', 'Phone', 'Industries', 'Employees', 'Revenue', 'Ownership'];
foreach($elements as $index => $element)
{
if(isset($keys[$index])) //保证不越界
{
$data[$keys[$index]] = $element->getText();
}
}
$all_data[] = $data; //收集每一次的数据
// print_r($data); //调试用.
}
fclose($f);
print_r($all_data);
//这里可以连接数据库了, 把$all_data 里的内容批量或者逐条写入。
这个改进版本一次性获取了所有的seo-company
元素, 然后通过索引和预定义的 key 对应, 避免多次的if判断. $all_data
收集所有数据,最后统一处理, 效率也更高。
三、 安全建议
在处理用户输入或从外部获取的数据时,永远要小心!
- 数据验证: 确保你获取的数据是符合预期的。比如,如果某个字段应该是数字,就检查一下它是不是真的是数字。
- 防止注入: 在写入数据库之前,对数据进行适当的转义或使用参数化查询。 避免SQL注入攻击。
这次主要解决的是数组操作的问题, 所以安全方面提的不多, 但在实际应用中,务必注意!