比较两个数组以添加或删除数据库中的记录

问题描述 投票:0回答:1

也许今天是漫长的一周,但我开始试图弄清楚如何解决这个问题的逻辑。

要使用经典的订单和商品示例,我们有一个网络表单,可以列出现有订单的数据,例如保存在数据库中。

现在,此表单需要能够在订单“保存”后从订单中添加/“标记为已删除”ItemID。提交表单时,我有两个数组:

$ogList =有问题的OrderID的原始ItemID。 (例如[123, 456, 789]

$_POST['items'] = ItemIDs的修改,如果有的话(例如[123, 789, 1240, 944]

目的是比较两个数组和:

1)添加新的ItemID(之前从未与此OrderID相关)

2)标记'删除'那些不是$ _POSTed的ItemID的日期。

从订单中删除现有ItemID并添加$ _POSTed列表的简单方法不适用于业务原因。

PHP的array_diff()并没有真正告诉我哪些是“新的”。

那么最好的方法是什么?看来我正在看一个嵌套的foreach()循环ala:

foreach($_POST['items'] as $posted){
   foreach($ogList as $ogItem){
      if($posted == $ogItem){
         Open to ideas here.
     }
   }
 }

......那里可能有条件的break(1)?也许有更好的方法?

另一种可能解释的方法是显示db记录。这个例子中的原文是:

+--------+-------------+
| itemID | dateRemoved |
+--------+-------------+
|    123 |           0 |
|    456 |           0 |
|    789 |           0 |

在POST之后,此OrderID中的ItemID将如下所示:

+--------+-------------+
| itemID | dateRemoved |
+--------+-------------+
|    123 |           0 |
|    456 |  1368029148 |
|    789 |           0 |
|   1240 |           0 |
|    944 |           0 |

这有意义吗?任何建议,将不胜感激!

编辑:我发现JavaScript sync two arrays (of objects) / find delta,但我不够精通足以翻译Javascript和地图。虽然它让我几乎到了那里。

database arrays comparison pseudocode
1个回答
0
投票

好吧,如果你有数据库中的项目并且你收到了更改了一组项目的新文档,你显然必须更新数据库。最简单的方法之一是删除所有以前的项目并插入新列表。但是,如果项目与其他数据相关,则无法执行此操作。所以你必须应用这种比较两个列表的技术。你有数据库中的项目,你有更改文件后客户端的项目和波纹管命令,你可以分开数据库中插入的内容,你只需要更新什么以及从数据库中删除什么。下面是一个简化的例子。

$a = [1,2,3,4,5];   //elements in database
$b = [2,3,4,6];     //elements after document save

$del = array_diff($a, $b);
//for delete 1, 5

$ins = array_diff($b, $a);
//for insert 6

$upd = array_intersect($a, $b);
//for update 2, 3, 4

如您所见,这只是比较元素,但如果要插入实际数据,则必须切换到关联数组并比较键。你需要数组看起来像这样:

{
    "15":{"employee_id":"1","barcode":"444","is_active":"1"},
    "16":{"employee_id":"1","barcode":"555","is_active":"1"},
    "17":{"employee_id":"1","barcode":"666","is_active":"1"},
    "18":{"employee_id":"1","barcode":"777","is_active":"1"}
}

在这里,您具有从数据中提取的ID并放置在数组键位置。在服务器端,该阵列可以通过PDO获得:

$sth->fetchAll(PDO::FETCH_UNIQUE|PDO::FETCH_ASSOC);

请注意,这将从结果集中删除第一列。因此,如果您希望ID位于两个位置,请使用:“SELECT id AS arrkey,id,... FROM ...”。

在服务器端,当你创建数组时,你不需要所有数据,只需获取id-s。这一切都需要比较,因为关键只是重要的:

[16=>16, 17=>17, 18=>18, 19=>19, 20=>20];

在客户端,使用JavaScript,您必须制作相同的结构化对象数组,以便在服务器上进行比较。当您在客户端上有新项目时,只需使用Math.random()来生成随机密钥,因为这无关紧要。

let cards = {};
cards[Math.random()] = {
    employee_id: something,
    barcode: something,
    is_active: something
}

之后,从客户端你会得到这样的数组:

{
    "16":{"employee_id":"1","barcode":"555","is_active":"1"},
    "17":{"employee_id":"1","barcode":"666","is_active":"1"},
    "18":{"employee_id":"1","barcode":"777","is_active":"1"},
    "0.234456523454":{"employee_id":"1","barcode":"888","is_active":"1"}
}

ID 15的项目被删除,16,17,18被更改(或不更改,无论如何都会更新它们),并添加新项目。在服务器上,您可以应用3方式比较:array_diff_key和array_intersect_key。

所以,最后,这个服务器端代码在我的情况下看起来如何。第一个循环是在数组键上,而secound是动态地创建UPDATE / INSERT语句。

//card differences
$sql = 'SELECT card_id AS arrkey, card_id FROM card WHERE (employee_id = ?)';
$sth = $this->db->prepare($sql);        
$sth->execute([$employee_id]);
$array_database = $sth->fetchAll(PDO::FETCH_UNIQUE|PDO::FETCH_ASSOC);            
$array_client = json_decode($_POST['...'], true);

//cards update            
foreach (array_intersect_key($array_database, $array_client) as $id => $data) {
    $query = 'UPDATE card SET';
    $updates = array_filter($array_client[$id], function ($value) {return null !== $value;}); //clear nulls
    $values = [];
    foreach ($updates as $name => $value) {
        $query .= ' '.$name.' = :'.$name.','; 
        $values[':'.$name] = $value; 
    }
    $query = substr($query, 0, -1); // remove last comma

    $sth = $this->db->prepare($query . ' WHERE (card_id = ' . $id . ');');
    $sth->execute($values);
}

//cards insert
foreach (array_diff_key($array_client, $array_database) as $id => $card) {
    $prep = array();
    foreach($card as $k => $v ) {
        $prep[':'.$k] = $v;
    }
    $sth = $this->db->prepare("INSERT INTO card ( " . implode(', ',array_keys($card)) . ") VALUES (" . implode(', ',array_keys($prep)) . ")");
    $sth->execute($prep); 
}

//cards delete
foreach (array_diff_key($array_database, $array_client) as $id => $data) {
    $sth = $this->db->prepare('DELETE FROM card WHERE card_id = ?');        
    $sth->execute([$id]);
}
© www.soinside.com 2019 - 2024. All rights reserved.