返回

PHP array_push() 返回整数?解决及数组操作优化

php

解决 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 收集所有数据,最后统一处理, 效率也更高。

三、 安全建议

在处理用户输入或从外部获取的数据时,永远要小心!

  1. 数据验证: 确保你获取的数据是符合预期的。比如,如果某个字段应该是数字,就检查一下它是不是真的是数字。
  2. 防止注入: 在写入数据库之前,对数据进行适当的转义或使用参数化查询。 避免SQL注入攻击。

这次主要解决的是数组操作的问题, 所以安全方面提的不多, 但在实际应用中,务必注意!