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

时间:2013-08-07 20:56:20

标签: database arrays comparison pseudocode

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

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

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

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

$_POST['items'] = ItemID的修改(如果有的话)(例如[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和地图。虽然它让我几乎到了那里。

1 个答案:

答案 0 :(得分: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"}
}
编号为15的

项被删除,16,17,18被更改(或不更改,无论如何您将对其进行更新),并添加了新项。在服务器上,您可以使用以下三种方式进行比较: array_diff_key array_intersect_key

因此,最后,在我的情况下,此服务器端代码的外观。第一个循环是在数组键上,第二个是动态地执行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]);
}