1

也许今天是漫长的一周,但我开始绕圈子试图找出解决这个问题的逻辑。

为了使用经典的订单和项目示例,我们有一个网络表单,它将现有订单的数据制成表格,例如保存在数据库中。

现在,此表单需要能够在“保存”订单后从订单中添加/“标记为已删除”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)?也许有更好的方法?

另一种可能解释的方法是显示数据库记录。此示例中的原始内容为:

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

在 POST 之后,此 OrderID 中的 ItemID 将类似于:

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

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

编辑:我发现JavaScript 同步两个数组(对象)/查找 delta,但我还不够精通翻译 Javascript 和地图。虽然它让我几乎到了那里。

4

1 回答 1

2

好吧,当您在数据库中有项目并且您收到包含更改的项目集的新文档时,您显然必须更新数据库。最简单的方法之一是删除所有以前的项目并插入新列表。但是,如果项目与其他数据相关,则不能这样做。因此,您必须应用这种比较两个列表的技术。您在数据库中有项目,在文档更改后您有来自客户端的项目,并且使用以下命令,您可以将要插入数据库的内容、只需要更新的内容和要从数据库中删除的内容分开。下面是一个简化的例子。

$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_keyarray_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]);
}
于 2018-08-31T23:37:59.147 回答