【问题标题】:How to merge two arrays如何合并两个数组
【发布时间】:2019-06-13 17:12:22
【问题描述】:

我有一个表单,我用它来更新用户个人资料。问题是我不想让所有字段都成为强制性的,所以如果用户留下一个空白字段,那么已经存储在数据库中的值会被更新为空白或空值。因此,我决定查询数据库并获取一个已经存储的值数组,然后我从用户表单中获得了一个值数组。我需要以某种方式合并这两个数组,如果在表单中插入了新值,我可以更新数据库字段,如果表单字段为空,则保留旧的数据库值。

我知道我可以在不使用数组的情况下执行以下操作,但我不知道在这种情况下如何使用准备好的语句

if(!empty($user_last))
  $update_values[] = "user_last='".$user_last."'";
$update_values_imploded = implode(', ', $update_values);

if( !empty($update_values) ){
 $q = "UPDATE users SET $update_values_imploded WHERE user_id='$userid' ";
 $r = mysqli_query($conn,$q);

 if($r){
$_SESSION['success_msg'] = 'profile updated!';
header("location: ../client_profile.php");
exit();
}
}

我尝试过的数组方法如下,但确实不能正常工作。

$merged_array =  array_unique(array_merge($database_rows, $form_data));

您还有其他想法吗?非常感谢

这是带有模拟数组的完整代码

$km_user_id= 2;

// this array comes from the form
$from_array = array(
    'km_user_first_name' => 'Antonio', 
    'km_user_last_name' => 'Acri',
    'km_user_address' => 'via pola',
    'km_user_city' => 'roma',
    'km_user_city_prov' => '',
    'km_user_postcode' => '',
    'km_user_email' => '',
    'km_user_website' => 'url',
    'km_user_telephone' =>  '123456',
    'km_user_mobile' => '',
    'km_user_fiscalcode' => '',
    'km_user_document' => '',
    'km_user_document_number' => '',
    'km_user_document_exp' =>  '',
    'km_user_birth_place' => '',
    'km_user_birth_date' => ''


);


   // select vakues from database

   $query= "SELECT km_user_first_name, km_user_last_name, km_user_address, km_user_city, km_user_city_prov, km_user_postcode, km_user_email, km_user_website, km_user_telephone, km_user_mobile, km_user_fiscalcode, km_user_document, km_user_document_number, km_user_document_exp, km_user_birth_place, km_user_birth_date FROM km_users WHERE km_user_id= ?";
   $stmt = mysqli_prepare($db_user_conn, $query);
   mysqli_stmt_bind_param($stmt, 'i', $km_user_id);
   mysqli_stmt_execute($stmt);
   $result = mysqli_stmt_get_result($stmt);

   $row = mysqli_fetch_array($result, MYSQLI_ASSOC);
   print_r($row);


?>
<br>
<br>
<?php

print_r($from_array);


?>
<br>
<br>
<?php

$result =  array_merge($from_array, $row); 
print_r($result);

您可以在合并的数组中看到值[km_user_address] =&gt; via roma 11 应该是[km_user_address] =&gt; via pola

【问题讨论】:

  • but it doesn't really work properly. 这是什么意思?您需要向我们展示数组的值、您期望的以及您得到的。
  • 向我们展示完整的代码。
  • 您好,我已按照要求使用代码更新了问题
  • 要在准备好的语句中将参数传递给动态数字?,请使用bind_param,如call_user_func_array(array($stmt, 'bind_param'), refValues($params));。见stackoverflow.com/a/16120923/5459839
  • 如果第一个数组有空字段,您可以使用array_filter 排除它们然后合并

标签: php arrays


【解决方案1】:

我想用完全不同的方法提供第二个答案。

你可以做到的最好和最安全的方法就是执行一个简单的静态准备语句,并让空参数的处理由 SQL 来完成:

$sql_update = <<<_SQL_

  UPDATE 
    `users`
  SET
    `km_user_first_name`      = COALESCE(NULLIF(?, ''), `km_user_first_name`      ),
    `km_user_last_name`       = COALESCE(NULLIF(?, ''), `km_user_last_name`       ),
    `km_user_address`         = COALESCE(NULLIF(?, ''), `km_user_address`         ),
    `km_user_city`            = COALESCE(NULLIF(?, ''), `km_user_city`            ),
    `km_user_city_prov`       = COALESCE(NULLIF(?, ''), `km_user_city_prov`       ),
    `km_user_postcode`        = COALESCE(NULLIF(?, ''), `km_user_postcode`        ),
    `km_user_email`           = COALESCE(NULLIF(?, ''), `km_user_email`           ),
    `km_user_website`         = COALESCE(NULLIF(?, ''), `km_user_website`         ),
    `km_user_telephone`       = COALESCE(NULLIF(?, ''), `km_user_telephone`       ),
    `km_user_mobile`          = COALESCE(NULLIF(?, ''), `km_user_mobile`          ),
    `km_user_fiscalcode`      = COALESCE(NULLIF(?, ''), `km_user_fiscalcode`      ),
    `km_user_document`        = COALESCE(NULLIF(?, ''), `km_user_document`        ),
    `km_user_document_number` = COALESCE(NULLIF(?, ''), `km_user_document_number` ),
    `km_user_document_exp`    = COALESCE(NULLIF(?, ''), `km_user_document_exp`    ),
    `km_user_birth_place`     = COALESCE(NULLIF(?, ''), `km_user_birth_place`     ),
    `km_user_birth_date`      = COALESCE(NULLIF(?, ''), `km_user_birth_date`      )
  WHERE
    `user_id` = ?
  ;

_SQL_;

$stmt = $db_user_conn->prepare($sql_update);

mysqli_stmt_bind_param
(
  $stmt,  'ssssssssssssssssi',

  $form_data['km_user_first_name'],
  $form_data['km_user_last_name'],
  $form_data['km_user_address'],
  $form_data['km_user_city'],
  $form_data['km_user_city_prov'],
  $form_data['km_user_postcode'],
  $form_data['km_user_email'],
  $form_data['km_user_website'],
  $form_data['km_user_telephone'],
  $form_data['km_user_mobile'],
  $form_data['km_user_fiscalcode'],
  $form_data['km_user_document'],
  $form_data['km_user_document_number'],
  $form_data['km_user_document_exp'],
  $form_data['km_user_birth_place'],
  $form_data['km_user_birth_date'],
  $km_user_id
);

mysqli_stmt_execute($stmt);

【讨论】:

  • 嗨,是的,我读过关于合并的文章,但从来不明白如何使用它:(你的例子很好,我也会接受你的回答。我读过很多帖子,最好不要在逻辑操作中涉及 mysql 但更喜欢 php 来做艰苦的工作是正确的吗?这只是我问的一个好奇。非常感谢您的时间和您的支持,感谢您,我学到了很多;)跨度>
  • 逻辑应该用 PHP 还是 SQL 没有一般的答案(这更像是一个宗教问题)。我什至倾向于说 SQL 逻辑的使用量通常太少了。在这里,它用于完全避免动态 SQL,这将是 SQL 注入的潜在风险。使用 SQL 时,您应该始终按白名单过滤,或者更好地从地图['form_field_name' =&gt; 'db_col_name', ...] 中查找名称。那么剩下的风险就是代码重构。通常,您可以通过在大表上使用 SQL 逻辑来减少数据库连接上的大量数据传输。
  • 在这种特殊情况下,您可以预先检查是否未设置任何字段,因此根本不需要执行更新语句。我会考虑在数据库连接上服务器负载较高的环境中这样做。
【解决方案2】:

您应该依赖准备好的语句。

仅使用白名单作为动态 SQL 构建列名。过滤掉空字符串''。插入匿名预处理语句参数? 并生成类型说明符字符串。然后将值作为绑定参数传递。

这个应该可以工作(还不能测试)。

<?php
declare (strict_types=1);

$km_user_id = 2;

// this array comes from the form
$form_array =
[
  'km_user_first_name'      => 'Antonio',
  'km_user_last_name'       => 'Acri',
  'km_user_address'         => 'via pola',
  'km_user_city'            => 'roma',
  'km_user_city_prov'       => '',
  'km_user_postcode'        => '',
  'km_user_email'           => '',
  'km_user_website'         => 'url',
  'km_user_telephone'       => '123456',
  'km_user_mobile'          => '',
  'km_user_fiscalcode'      => '',
  'km_user_document'        => '',
  'km_user_document_number' => '',
  'km_user_document_exp'    => '',
  'km_user_birth_place'     => '',
  'km_user_birth_date'      => '',
];

$white_list =
[
  'DEBUGkm_user_first_name'      => true, // DEBUG TEST filter
  'km_user_last_name'       => true,
  'km_user_address'         => true,
  'km_user_city'            => true,
  'km_user_city_prov'       => true,
  'km_user_postcode'        => true,
  'km_user_email'           => true,
  'km_user_website'         => true,
  'km_user_telephone'       => true,
  'km_user_mobile'          => true,
  'km_user_fiscalcode'      => true,
  'km_user_document'        => true,
  'km_user_document_number' => true,
  'km_user_document_exp'    => true,
  'km_user_birth_place'     => true,
  'km_user_birth_date'      => true,
];


// filter by whitelist and remove  ''  but NOT  '0'
$non_empty = array_intersect_key(array_filter($form_array, function($v){return $v !== '';}), $white_list);

if(!empty($non_empty))
{
  $cols   = '`' . implode('` = ?, `', array_keys($non_empty)) . ' = ?';
  $query  = "UPDATE `users` SET $cols WHERE `user_id` = ?";
  $values = array_values($non_empty);
  array_push($values, $km_user_id);

  $stmt = mysqli_prepare($db_user_conn, $query);
  mysqli_stmt_bind_param($stmt, str_repeat('s', count($non_empty)).'i', ...$values);
  mysqli_stmt_execute($stmt);
  // TODO: error handling
}

km_user_first_name 不应更新,因为它不在白名单中。测试时去掉前缀DEBUG

【讨论】:

    【解决方案3】:

    我希望我能意识到您的问题(如果没有,请随时发表评论)。

    如果您想将表单数组作为主要值,并且仅当它为空时从第二个数组中获取值,您可以在 array_filterarray_merge 上使用组合。

    考虑以下示例:

    $form = array("km_user_first_name" => "Alice", "km_user_address" => "");
    $row = array("km_user_first_name" => "Boby", "km_user_address" => "via pola");
    $res = array_merge($row, array_filter($form));
    

    这将输出:

    Array
    (
        [km_user_first_name] => Alice
        [km_user_address] => via pola
    )
    

    我知道我使用PHP documentation 中所说的第二个form 数组(感谢@Nick):

    如果输入数组有相同的字符串键,那么后面的值 因为那个键会覆盖前一个键

    希望有帮助!

    【讨论】:

    【解决方案4】:

    为什么要创建另一个数组?您可以真正编辑已有的数组。 例如 : 您从数据库中获取索引数组 用值填写表单,以便用户可以看到旧信息。当用户编辑时让我们说出他的名字myArray ['name'] = $_POST ['name']

    【讨论】:

      猜你喜欢
      • 2011-10-02
      • 1970-01-01
      • 1970-01-01
      • 2022-01-04
      • 2021-10-11
      • 2011-10-09
      • 2017-09-26
      相关资源
      最近更新 更多