也许今天是漫长的一周,但我开始试图弄清楚如何解决这个问题的逻辑。
要使用经典的订单和商品示例,我们有一个网络表单,可以列出现有订单的数据,例如保存在数据库中。
现在,此表单需要能够在订单“保存”后从订单中添加/“标记为已删除”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和地图。虽然它让我几乎到了那里。答案 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]);
}