7

多対多のテーブル構造があり、チェックボックス フォームを更新しています。

目標は、users_project テーブルを使用して users テーブルを projects テーブルに関連付けることです。このようにして、プロジェクトごとに多くのユーザーが存在し、ユーザーごとに多くのプロジェクトが存在する可能性があります。

各ユーザー編集ページのフォームは次のようになります

<form action="#" method="post">
    <div>   
        <input type="checkbox" name="project_id[]" id="1" value="1">
        <label for="1">project 1</label>
        <br>

        <input type="checkbox" name="project_id[]" id="2" value="2">
        <label for="2">project 2</label>
        <br>
        <input type="hidden" name="editing">
        <input type="submit" id="submit" value="submit">
    </div>
</form>

3 つのテーブルの例を次に示します。

ユーザー テーブル

+----+-----------+
| id ¦ username  ¦
+----+-----------+
| 1  ¦ user 1    ¦
| 2  ¦ user 2    ¦
+----+-----------+

プロジェクト テーブル

+----+-----------+  
¦ id ¦ title     ¦
+----+-----------+  
| 1  ¦ project 1 ¦
| 2  ¦ project 2 ¦
+----+-----------+    

user_projects テーブル

このテーブルは、ID に基づいて上記の 2 つのテーブルを関連付けます

+----+-------------+---------+
| id ¦ project_id  ¦ user_id |
+----+-------------+---------+
| 1  ¦           1 ¦       2 |
| 2  ¦           2 ¦       1 |
+----+-------------+---------+

これらの値を追加および編集するためのチェックボックス フォームを作成しました。各ユーザー ページでは、プロジェクト テーブルにすべてのプロジェクトが表示されます。次に、user_projects テーブルにクエリを実行し、一致するリストを見つけて、チェックボックスにチェックを追加します。

しかし、これらの値をデータベースに編集するにはどうすればよいでしょうか? user テーブルで project_id と user_id の一致を求めるクエリをループせずに、ユーザーが以前にチェックしたボックスをオフにしたか空のボックスをオンにしてデータベースを更新したかどうかを知るにはどうすればよいですか?

これが、最終結果で達成したいことの大まかな概念です。

if ($_POST['editing']) { 
    $totalprojects = $_POST['editing']; 
    $query = " 
        SELECT *  
        FROM user_projects  
        WHERE user_id = user_id 
        AND project_id = project_id 
    "; 
    $result = $mysqli->query($query); 
    $count = $mysqli->affected_rows; 
    for($i=0; $i < $totalprojects; $i++) {  
        if ($count == 1) { 
            if ($box == checked){  
                //do nothing 
            } 
            else { 
                //delete from database 
            } 
        } 
        if ($count == 0) { 
            if ($box == checked){  
                //add to database 
            } 
            else { 
                //do nothing 
            } 
        } 
    } 
} 

プロジェクト テーブル内のすべてのプロジェクトに対して少なくとも 1 回はデータベースにクエリを実行する必要があるため、これはまったく良い考えとは思えません。私が一般的な問題であると想像するものには、より良い解決策があるに違いありません。私はこれについて間違った方法で考えていることを知っています。

注:配列をシリアル化してユーザー列に貼り付けることだけを考えましたが、プロジェクトをユーザーのみユーザーに関連付けてプロジェクトに関連付けることができず、目的を無効にすることができないため、これは受け入れられません。

これをJavaScriptの策略なしで実装したいと思います。

4

4 に答える 4

2

あなたのプロジェクトの数は 1 つの表に表示するには十分に小さいため、user_projects送信時に表の関連部分を書き直すことに完全に賛成です。

BEGIN TRANSACTION;
DELETE FROM user_projects WHERE user_id = $uid;
INSERT INTO user_projects (project_id, user_id)
    VALUES ($proj1, $uid), ($proj2, $uid), ...;
COMMIT TRANSACTION;

拡張INSERT構文を使用して関連付けを 1 つのステートメントで記述していることに注意してください。

user_projects.id不要な場合は削除して、テーブルのスペースを 3 分の 1 節約することもできます。

于 2009-04-23T16:57:31.450 に答える
1

それが私がこの問題を解決する方法です:

  1. まず、activeDELETE sqlステートメントを使用するよりも安全であるため、列を使用してアイテムが削除されているか(0)、削除されていないか(1)を確認しています。

  2. 次に、user_id列とproject_id列をUNIQUEとして定義する必要があります

    ALTER TABLE `user_projects` ADD UNIQUE INDEX(user_id, user_project_id)
    
  3. コード

    $uid = $_POST['uid'];
    $pids = $_POST['project_id'];
    
    // "deleting" all entries
    $chb = $db->prepare("UPDATE `user_projects` SET `active`=0 WHERE `user_id`=?");
    $chb->execute(array($uid));
    
    //updating checked checkboxes
    foreach ($pids as $pid) {
    $chb = $db->prepare("INSERT INTO `user_projects` VALUES (?, ?, 1) ON DUPLICATE KEY UPDATE `active`=1");
    $chb->execute(array($uid, $pid));
    

    }

-すべての例でPDOが使用されています

于 2013-03-08T21:13:01.240 に答える
0

すべてのユーザーがすべてのプロジェクトで作業する資格があると仮定すると、フォーム処理ページで次のようにします。

$query = 'SELECT p.id AS project_id, u_p.id AS user_project_id '.
            'FROM projects AS p '.
                'LEFT JOIN user_projects AS u_p ON (u_p.project_id = p.id AND u_p.user_id = ?)';

左に参加すると、システム内のすべてのプロジェクトのリストが表示され、2 番目の列には、編集中のユーザーが既にそのプロジェクトにいる場合にのみ値が表示されます。user_idあなたが与えたサンプルデータの場合、これは1に対してクエリを実行して得られる結果です。

+------------+-----------------+
| project_id | user_project_id |
+------------+-----------------+
|          1 |                 |
|          2 |               2 |
+------------+-----------------+

次に、このクエリの結果をループし、各結果$_POSTについて、対応する の値が送信されたかどうかを確認しますproject_id。値が送信され (チェックボックスがオンになっている)、行user_project_idが空の場合は、行を挿入してuser_projectsこのリンクを追加します。値が送信されず (チェックボックスがオフ)、行が設定されている場合は、その行をキーとして使用しuser_project_idないように削除します。それ以外の場合は何もしません。以前と変わっていません。user_projectsuser_project_id

詳細を知りたい場合はお知らせください。

于 2009-04-23T16:50:29.923 に答える
0

アクションをグループ化し、スクリプトを 3 つのクエリに減らすことができます。

Chad Birch anwser から LEFT JOIN を使用して、現在選択されているオプションを取得します。

ループの前:

$delete_ids = array();
$add_ids = array();

ループ内:

// delete from database
$delete_ids[] = $project_id;

// add to database
$add_values[] = '('.$user_id.', '.$project_id.')';

そして for ループの後:

if (count($delete_ids) > 0) {
  mysql_query('DELETE FROM user_projects WHERE user_id = '.$user_id.' AND project_id IN ('.implode(', ', $delete_ids).')'); 
}

if (count($add_ids) > 0) {
  mysql_query('INSERT INTO user_projects (user_id, project_id) VALUES '.implode($add_values)); 
}
于 2009-04-23T16:54:37.153 に答える