簡體   English   中英

更新多對多聯接表的最佳實踐?

[英]Best Practice for Updating a Many-to-Many Join Table?

這是一個關於如何在多對多連接表中最佳地分配或更新多個條目的問題。 簡而言之,能夠修改文章或博客的類別或標簽。

在我正在構建的這個應用程序中,我有一個Category表(類別)和Article表(稱為musings)。

因為每個文章都可以屬於許多類別(並且每個類別可以分配給許多文章),所以我有一個關於此關系的聯接表(category_musings)。 我已經設置了約束 - 因此刪除文章會刪除連接表中的所有關聯條目。 但是,如果當前已將類別分配給文章,則禁止刪除該類別。

我想要達到的目標:

我希望最終用戶能夠更新/修改/刪除給定文章的多個類別(沉思)。

我的工作是如此:

我已經找到了一種方法,可以使用以下函數在多樣式下拉列表中顯示當前類別值

首先,我得到所有類別的列表

//Return list of categories
public function categories($column)
{
$sql = "SELECT * FROM category";
$query = $this->connection->prepare($sql);
$query->execute();

return $query->fetchAll(\PDO::FETCH_COLUMN, $column);;
}

然后是當前分配給特定冥想的類別

//Return categories selection for each musing
public function getMusingCategoryList($id)
{
$sql = "SELECT category AS categories
              FROM musings 
              JOIN category_musings ON musings.musing_id=category_musings.musing_id
              JOIN category ON category_musings.category_id=category.category_id
              WHERE category_musings.musing_id=:musing_id";
$query = $this->connection->prepare($sql);

$values = [
':musing_id' => $id,
];
$query->execute($values);

return $query->fetchAll(\PDO::FETCH_COLUMN,0);
}

兩個返回數組然后我傳遞給另一個函數來創建我的下拉列表。 這是前端的PHP代碼

$data = new \norm_musing\MusingData();
$Musing = $data->getMusing($_GET['id']);

$name = 'multi_dropdown';
$options = $data->categories("1");
$selected = $data->getMusingCategoryList($_GET['id']);

$result = $data->multi_dropdown( $name, $options, $selected );

這是下拉創建功能,我稍后將其與所有其他相關的現場數據一起傳遞給表單

//Create dropdown for categories
public function multi_dropdown( $name, array $options, array $selected=null, $size=4 )
{
    /*** begin the select ***/
    $dropdown = '<select class="form-control" name="'.$name.'[]" id="'.$name.'" size="'.$size.'" multiple>'."\n";

    /*** loop over the options ***/
    foreach( $options as $key=>$option )
    {
            /*** assign a selected value ***/
            $select = in_array( $option, $selected ) ? ' selected' : null;

            /*** add each option to the dropdown ***/
            $dropdown .= '<option value="'.$key.'"'.$select.'>'.$option.'</option>'."\n";
    }

    /*** close the select ***/
    $dropdown .= '</select>'."\n";

    /*** and return the completed dropdown ***/
    return $dropdown;}

這將生成一個String,其中包含必要的Form HTML代碼,用於創建下拉列表,並選擇當前值(詳細)。 並且所有用戶必須能夠按住CTRL並同時用鼠標單擊,如果他們想要進行更改。

但是現在我必須找到一種方法來更新Join表,如果用戶更改了選擇(或忽略它們)。

下拉框作為數組返回

$selection = $_POST['multi_dropdown']. 

例如,有6個類別 - 在列表中選擇1和4 - 數組值為[0,3]

為了詳細,我可以理解發生了什么,我創建這個PHP代碼來處理我的表單響應

if (isset($_POST['id']) && !empty($_POST['id'])) 
{
$aCategories = $_POST['multi_dropdown'];
if(!isset($aCategories)) 
{
echo("<p>You didn't select any categories!</p>\n");
}
else
{
$nCategories = count($aCategories);
$categoryID = $data->categories("0");

echo("<p>You selected $nCategories categories: ");
for($i=0; $i < $nCategories; $i++)
{
  echo($aCategories[$i] . " ");
  echo($options[$aCategories[$i]] . " ");
  echo("(id: " . $categoryID[$aCategories[$i]] . ") | ");
}
echo("</p>");
$nCount = $_POST['count'];
$newSelected = $data->getMusingCategoryList($_POST['id']);
echo("<p>Originally you had $nCount categories: ");
for($i=0; $i < $nCount; $i++)
{
  echo($newSelected[$i] . " ");
}
echo("</p>");

exit;}}

哪個產生這樣的輸出(id是類別表中的主鍵)

    You selected 2 categories: 0 Aging (id: 3) | 2 Health (id: 4) |

    Originally you had 1 categories: Happiness 

我的問題:

我應該簡單地刪除連接表中與Musing ID匹配的所有條目 - 然后插入新選擇的INSERT嗎? 如果沒有進行任何更改,那將是浪費的,所以首先我可能需要進行某種數組比較。

這里最好的做法是什么?

是否有一種更簡單的方法允許用戶為文章添加和更新多個類別或標簽(如博客條目或在這種情況下是沉思)?

我相信這個問題的最佳實踐方法是利用MySQL的“INSERT IGNORE INTO”或者“REPLACE INTO”(但我認為這會引發2個問題)。

請參閱http://bogdan.org.ua/2007/10/18/mysql-insert-if-not-exists-syntax.html以供參考。

這是我的解決方案 - 我不太明白REPLACE INTO或INSERT IGNORE INTO如何實現同樣的目標

//Delete all categories for a given musing ID
public function deleteMusingCats( $id ) {

   $sql="DELETE FROM category_musings WHERE musing_id = :musing_id";
   $query = $this->connection->prepare($sql);
   $values = ['musing_id' => $id];
   $query->execute($values);

   }


//Insert new category for musing
public function updateMusingCats( $a, array $b, $n ) {  

$stmt = $this->connection->prepare("
                 INSERT INTO category_musings (category_id, musing_id) 
                 VALUES (:catID, :musID);
                                  ");  

for ($i=0; $i < $n; $i++) 
{
  $stmt->bindValue(':catID', $b[$i], \PDO::PARAM_INT);
  $stmt->bindValue(':musID', $a, \PDO::PARAM_INT);
  $stmt->execute();
}

return $i;
}   

如果發送到表單的數組和從表單接收回的數組之間有變化,我只會調用它。

if (isset($_POST['id']) && !empty($_POST['id'])) 
{
    // Simple number array of the list items selected
    $aCategories = $_POST['multi_dropdown']; 

    if(!isset($aCategories))   {
        // No categories selected. Abort!
        header("Location: /norms_musings");
    } else {
        $nCategories = count($aCategories); // Number of categories selected
        $categoryID = $data->categories("0");  // Create complete category ID array

        for($i=0; $i < $nCategories; $i++) 
        /* Create array of selected categories the number value from the
        dropdown list corresponding to the place in the full category list array */
            $a[]=$options[$aCategories[$i]]; 
            $b[]=$categoryID[$aCategories[$i]]; // Create array of selected category IDs
        }

        $nCount = $_POST['count'];
        $newSelected = $data->getMusingCategoryList($_POST['id']);

        $equal = ($a==$newSelected);

        if ($equal) {
            // No Changes Made!
            header("Location: /norms_musings");
            exit;
        } else {
            $data->deleteMusingCats($_POST['id']);
            $arrayDiff = (array_diff($a,$newSelected));
        }

        if ($data->updateMusingCats($_POST['id'],$b,$nCategories)) {
            header("Location: /norms_musings");
            exit;
        } else {
            echo "An error occurred";
            exit;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM