PHP & Mysql обновляет отношения многие ко многим с помощью формы флажка - PullRequest
7 голосов
/ 23 апреля 2009

У меня есть структура таблицы «многие ко многим» и обновляются формы флажков.

Цель состоит в том, чтобы связать таблицу пользователей с таблицей проектов с таблицей users_project. Таким образом, может быть много пользователей для одного проекта и много проектов для пользователя.

Форма на каждой странице редактирования пользователя будет выглядеть примерно так

<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>

Вот примеры трех таблиц.

таблица пользователей

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

таблица проектов

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

таблица user_projects

эта таблица связывает две вышеуказанные таблицы на основе их идентификатора

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

Я сделал флажок для добавления и редактирования этих значений. На каждой странице пользователя отображаются все проекты в таблице проектов. Затем запрашивает таблицу user_projects и находит список совпадений, чтобы добавить проверки к флажкам.

Но как мне отредактировать эти значения в базе данных? Как я узнаю, снял ли пользователь ранее отмеченный флажок или установил пустой флажок, и обновил ли базу данных, не зацикливая запрос на совпадение в таблице пользователей для 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 
            } 
        } 
    } 
} 

Это совсем не кажется хорошей идеей , так как мне пришлось бы запрашивать базу данных хотя бы один раз для каждого проекта в таблице проекта. Должно быть лучшее решение для того, что я считаю общей проблемой. Я знаю, что просто думаю об этом неправильно.

ПРИМЕЧАНИЕ. Я думал о том, чтобы просто сериализовать массив и вставить его в столбец пользователя, но это недопустимо, поскольку я не смогу связать проект с пользователем, единственным пользователем, чтобы проектировать и победить цель.

Я бы хотел, чтобы это было реализовано без какой-либо хитрости в JavaScript.

Ответы [ 4 ]

2 голосов
/ 23 апреля 2009

Поскольку количество ваших проектов достаточно мало для отображения в одной таблице, я полностью поддерживаю переписывание соответствующей части таблицы 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 для записи ассоциации в одном операторе.

Вы также можете сбросить user_projects.id, если вам это не нужно, сэкономив треть пространства в таблице.

1 голос
/ 09 марта 2013

Вот как я решаю эту проблему:

  1. Прежде всего, я использую столбец active, чтобы проверить, удален ли элемент (0) или нет (1), поскольку это более безопасно, чем использование оператора DELETE sql

  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 используется во всех примерах

0 голосов
/ 23 апреля 2009

Вы можете сгруппировать действия и сократить сценарий до 3 запросов.

Получить текущую выбранную опцию, используя LEFT JOIN из Chad Birch anwser.

Перед циклом:

$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)); 
}
0 голосов
/ 23 апреля 2009

Ну, если предположить, что каждый пользователь имеет право работать над каждым проектом, на странице обработки формы вы хотите сделать что-то вроде этого:

$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 = ?)';

При левом присоединении это даст вам список всех проектов в системе, а второй столбец будет иметь значение, только если редактируемый вами пользователь уже находится в этом проекте. Для приведенных вами примерных данных это результат, который вы получите, запросив user_id 1:

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

Затем выполните цикл по результатам этого запроса и для каждого результата проверьте, было ли отправлено значение в $_POST для соответствующего project_id. Если значение было отправлено (флажок был установлен) и строка user_project_id пуста, вставьте строку в user_projects, чтобы добавить эту ссылку. Если значение не было отправлено (флажок снят) и установлена ​​строка user_project_id, удалите эту строку из user_projects, используя user_project_id в качестве ключа. В противном случае ничего не делать, они не изменились, как это было раньше.

Надеюсь, это понятно, дайте мне знать, если вы хотите, чтобы я углубился в детали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...