跟踪选择和取消选择更新表时的选项

时间:2015-01-09 16:38:19

标签: php html mysql

我有三张桌子(我在这个问题中对其进行了简化):

Table 1

id | Name
-----------
1  | John
2  | Smith


Table 2

id | Title
-----------
1  | Developer
2  | Web Developer
3  | A New Title

Table 3 (links between 1 and 2)

idName | idTitle
-----------
1      | 1
1      | 2
2      | 1

我的问题在于更新页面。我的HTML为<select multiple> ... options ... </select>,我使用chosen来选择和取消选择选项。我只想用PHP做这件事。 假设我们有以下情况: 管理员想要删除'John'的'Developer'标题,并为'John'添加'New Title'。 他/她将取消选择标题ID 1并选择标识3.当他/她提交表单时,我将获得两个选择值:id 1(他选择的那个)和id 2(已经存在的那个)。但我不会得到身份3,因为他取消了它。

我正在努力的是:当用户发布新选择的值时,取消选择的值未随表单一起提交。我没办法跟踪取消选择的那些,所以我可以从我的表中删除它们。您如何使用新更改更新表格?您是否删除该表中已存在的内容并再次添加ID?有更好的选择吗?

更新: 似乎@wander的答案比其他答案的破坏性小。但是,@ wonder没有解释如何在他的答案中计算第4步。在新选择的选项,已存在的选定选项和取消选择的选项之间进行分组。

9 个答案:

答案 0 :(得分:4)

没有必要提交取消选择的那个。 e.g。

  1. John在数据库中保存了两个标题(Developer和Web Developer)。
  2. 管理员打开页面,选择&#39;新标题&#39;,取消选择&#39; Developer&#39;并点击提交。
  3. 现在在服务器端,我们可以得到
    • John存储在数据库中的标题列表:Developer and Web Developer
    • 用户提交的标题列表:Web开发人员和新标题
  4. 我们比较两个标题列表并弄清楚:我们将删除开发者标题并在John上添加新标题。

答案 1 :(得分:3)

您可以在选择菜单之前添加隐藏字段,这样也会导致0 / falsey值发送给PHP。

<input type="hidden" name="stuff[]" value="0" />
<input type="hidden" name="stuff[]" value="0" />
<input type="hidden" name="stuff[]" value="0" />
<select multiple name="stuff[]">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>

这类似于将未经检查的复选框发送到服务器的方式:

https://stackoverflow.com/a/1992745/268074(注意没有JS的答案)

答案 2 :(得分:3)

您可以将旧值转储到隐藏的选择中,以便在处理表单时获取它们。

<!-- Invisible select field -->
<select multiple name="oldData[]" style="display:none;" aria-hidden="true">
    <option value="1">1</option>
    <option value="2" selected>2</option>
    <option value="3" selected>3</option>
</select>

<!-- Real select field -->
<select multiple name="data[]">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
</select>

注意:@ Petah的回答让我受到启发,不要忘记向他投票: - )。

答案 3 :(得分:3)

假设我们有$old_titles列表,其中包含来自db的标题,以及来自提交的$new_titles个标题。

$add = array_diff($new_titles, $old_titles);
$delete = array_diff($old_titles, $new_titles);

$add - 要添加的标题列表,$delete - 要删除的标题列表。

添加操作:

$dbh->prepare('INSERT INTO table3(idName, idTitle) VALUES (:idName, :idTitle)');
foreach($add as $titleId) {
    $dbh->execute(['idName' => $userId, 'idTitle' => $titleId]);
}

删除操作:

$dbh->prepare('DELETE FROM table3 WHERE idName = :idName AND idTitle = :idTitle');
foreach($delete as $titleId) {
    $dbh->execute(['idName' => $userId, 'idTitle' => $titleId]);
}

答案 4 :(得分:1)

唯一更好的方法是最简单的方法,记住 KIS

在更新时你只需要执行以下操作

DELETE FROM table3 WHERE idName=??

然后在table3中再次插入所有选定的idTitles

答案 5 :(得分:1)

这可以在两个SQL语句中完成,而不知道取消选择了哪个值。遵循这两个步骤

1)在PHP中,创建一个逗号分隔的所有选定选项列表。例如:2, 3

2)然后执行以下语句:

 DELETE FROM tblLink WHERE idName = $id AND idTitle NOT IN ($list);
 INSERT IGNORE tblLink (idName, idTitle)
 SELECT $id, id FROM tblTitle WHERE id IN ($list);

注意:为了简化,我在我的示例中使用了$id$list。当您打算使用它时,您应该正确地准备和绑定参数。确保idName和idTitle是使其工作的主键。

答案 6 :(得分:1)

不确定为什么每个人都在使用隐藏的输入字段来跟踪现有数据。当您POST表单时,您只需从数据库中检索原始值即可。根据用户输入,这样更安全,因为即使隐藏的字段也可以更改。我知道在这种特殊情况下这并不重要,但我认为最好始终使用最佳实践。

现在PHP你有两种选择。第一个是删除所有关系,然后添加新关系。第二种方法是删除所有未发布的内容,并添加/更新其中的关系。

虽然第二种选择可能看起来像你说的“破坏性最小”,但它是最容易且最不容易出错的方式。我放弃这种策略的唯一原因是我会在关系表中存储额外的数据。 EG:添加日期(当某人进入某个功能时)或由用户添加。

你会怎么做(方法2)?

请记住,我使用的方法会尽可能地继续尝试。另一种方法是在发布虚假数据时暂停。

<?php
if (array_key_exists("relations",$_POST) && is_array($_POST["relations"])) {
  //no duplicates, you dont want to store the same function twice
  //only integers
  $list = array_unique(array_filter($_POST["relations"], "is_int"));
  $csv = implode(',', $list);

  //get the userid hoewever you normally would
  $userId = 1

  //Delete existing
  $query = "DELETE FROM Table3 WHERE idname=".$userId
  //insert all posted functions
  //I select the id's from the actual table so it will never inserted a none existing ID.
  //this approach never has duplicates, so the duplicate check in the beginning is redundant now, but I leave it incase I change this.
  $query = "INSERT INTO Table3 (idName, idTitle) SELECT ".$userId.", Id FROM Table2 WHERE id IN (".$csv.")".

  //execute queries
} else {
  //nothing posted, delete all relations
}
?>

现在,如果您只想插入新数据并删除不存在的

<?php
if (array_key_exists("relations",$_POST) && is_array($_POST["relations"])) {
  //no duplicates, you dont want to store the same function twice
  //only integers
  $list = array_unique(array_filter($_POST["relations"], "is_int"));
  $csv = implode(',', $list);

  //get the userid hoewever you normally would
  $userId = 1

  //Delete existing
  $query = "DELETE FROM Table3 WHERE idname=".$userId." AND idTitle NOT IN (".$csv.")"
  //only insert new functions
  //I select the id's from the actual table so it will never inserted a none existing ID.
  //this approach never has duplicates, so the duplicate check in the beginning is redundant now, but I leave it incase I change this.
  $query = "INSERT INTO Table3 (idName, idTitle) SELECT ".$userId.", Id FROM Table2 WHERE id IN (".$csv.") AND id NOT IN (SELECT idTitle FROM table3 WHERE idName=".$userId.")".

  //execute queries
} else {
  //nothing posted, delete all relations
}
?>

答案 7 :(得分:1)

我认为您必须先检查应该执行哪些操作。这是一个可以在http://sandbox.onlinephpfunctions.com/code/0fa11b3c9f846e344c912f5a3e994eea5e9cac34运行的小例子。 首先在表3上运行select for idName = 1,输出将是idTitle的数组(1,2)。在下面的示例中,$ array1是这样的select语句的输出,$ array2是必须更新,删除或插入的相同idName的新idTitle的数组。例如,如果用户的新idTitles比以前的idTitles更多或更少,那么你应该对它进行某种控制,以便决定你将运行到数据库的查询。

$array1 = array(1,7,3,5);// initial idTitles try it on the above link (php sandbox) with more or less values 
$array2 = array(1,4,3,6);//new idTitles try it on the above link (php sandbox) with more or less values
$count1=count($array1);
$count2=count($array2);

$diff=$count1-$count2;
if ($diff==0) {
  $result1=array_values(array_diff_assoc($array2,$array1));
  $result2=array_values(array_diff_assoc($array1,$array2));
  $countr=count($result1);// or $result2 it is the same since they have the same length
  $cr=0;
  while($cr < $countr) {
  print_r("update tblname set val=$result1[$cr] where id=theid and val=$result2[$cr]\n");
  $cr++;
  }
}
if ($diff!=0) {
  $result1=array_diff($array2,$array1);
  $result2=array_diff($array1,$array2);
    if(count($result2)>0) {
      foreach($result2 as $r2) {
      print_r("delete from tblname where id=theid and val=$r2\n");
      }
    }
  foreach($result1 as $r1) {
  print_r("insert into tblname where id=theid and val=$r1\n");
  }
}

答案 8 :(得分:0)

我怎么做会扩展第一张表

id |名称|标题ID

1 |约翰| 1,2

2 |史密斯| 1,3

每次更新行时,我只需更换title_ids字段即可完成。