前提・実現したいこと
PHPで複数のタグを中間テーブルを利用してDBに登録する方法が知りたいです。
現在自作のphpアプリを製作中です。
タグ以外のDB登録は実装できています。
複数選択できるタグを中間テーブルを用いてDBに登録する方法が知りたいです。
今のイメージとしては、
投稿ボタンが押される
↓
入力したタグはセレクトで取得する
↓
3つのテーブルは外部結合する
↓
投稿テーブルと中間テーブルにデータを追加
こんな流れなのかな?と思っています。
該当のソースコード
投稿フォーム(post.php)
php
1<a href="index.php">リスト一覧へ</a> 2<?php 3 4// 直リンクの禁止 5if (empty($_SERVER["HTTP_REFERER"])) { 6 header('Location: /'); 7 exit; 8} 9 10session_start(); 11require_once(ROOT_PATH .'/Models/Post.php'); 12require_once(ROOT_PATH .'function.php'); 13ini_set('display_errors', "On"); 14$obj = new Post(); 15 16$err = []; 17 18 if($_SERVER['REQUEST_METHOD'] === 'POST'){ 19 20 $title = filter_input(INPUT_POST, 'title'); 21 $text = filter_input(INPUT_POST, 'text'); 22 $tags = filter_input(INPUT_POST, 'tags'); 23 $category = filter_input(INPUT_POST, 'category'); 24 $price = filter_input(INPUT_POST, 'price'); 25 以下バリデーションは省略 26 27 // エラーがなければ、DBにデータを保存し、リスト一覧にページ遷移 28 if(count($err) === 0) { 29 $result = $obj->createList($_POST, $save_path); 30 $_SESSION['list_msg'] = "リストの投稿に成功しました!"; 31 header('Location: index.php'); 32 exit; 33 } 34 } 35?> 36 37<!DOCTYPE html> 38<html lang="en"> 39<head> 40 <meta charset="UTF-8"> 41 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 42 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 43 <script src="https://cdn.jsdelivr.net/npm/@yaireo/tagify/dist/tagify.min.js"></script> 44 <script src="https://cdn.jsdelivr.net/npm/@yaireo/tagify/dist/tagify.polyfills.min.js"></script> 45 <link href="https://cdn.jsdelivr.net/npm/@yaireo/tagify/dist/tagify.css" rel="stylesheet" type="text/css" /> 46 <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1" crossorigin="anonymous"> 47 <link href="https://use.fontawesome.com/releases/v5.6.1/css/all.css" rel="stylesheet"> 48 <link rel="stylesheet" href="/css/posts.css"> 49 <title>リスト投稿画面</title> 50</head> 51<body> 52<?php include(ROOT_PATH .'Views/common/header.php'); ?> 53 <div class="p-wrapper"> 54 <div class="p-container"> 55 <h2 id="p-title">リストを投稿する</h2> 56 <form action="" method="POST" enctype="multipart/form-data" id="p-form"> 57 <!-- タイトル --> 58 <div class="mb-3"> 59 <label for="kome"><font color="red">*</font></label> 60 <label for="title" class="form-label">タイトル</label> 61 <?php if(isset($err['title'])): ?> 62 <p class="err"><font color="red"><?php echo $err['title'] ?></font></p> 63 <?php endif; ?> 64 <input type="text" class="form-control" id="title" name="title" value="<?php if(isset($title)) echo h($title) ?>" placeholder="タイトルを入力してください(30文字以内)"> 65 </div> 66 <!-- タグ --> 67 <div class="tag-lebel"> 68 <label for="kome"><font color="red">*</font></label> 69 <label for="tag" class="form-label">タグ(最低1つは選択しましょう)</label> 70 <?php if(isset($err['tags'])): ?> 71 <p class="err"><font color="red"><?php echo $err['tags'] ?></font></p> 72 <?php endif; ?> 73 </div> 74 <div class="mb-3 tag-form"> 75 <input name="tags" class='tag_field' placeholder="+タグの候補を選択してください。(最大5つまで選択可能)" value='<?php if(isset($tags)) echo h($tags) ?>'> 76 </div> 77 <!-- サービス詳細 --> 78 <div class="mb-3"> 79 <label for="kome"><font color="red">*</font></label> 80 <label for="contents" class="form-label">詳細</label> 81 <?php if(isset($err['text'])): ?> 82 <p class="err"><font color="red"><?php echo $err['text'] ?></font></p> 83 <?php endif; ?> 84 <textarea class="form-control" id="contents" name="text" rows="20" placeholder="サービスの内容、利用者のメリット、アピールしたい実績などを3000文字以内で具体的に書いてください。具体的でわかりやすいほど、リストを見た企業がリクエストをしてくれる確率がアップします。"><?php if(isset($text)) echo h($text) ?></textarea> 85 </div> 86 <!-- カテゴリー --> 87 <h6 id="p-category"><label for="kome"><font color="red">*</font></label>カテゴリーを選択してください</h6> 88 <?php if(isset($err['category'])): ?> 89 <p class="err_one"><font color="red"><?php echo $err['category'] ?></font></p> 90 <?php endif; ?> 91 <select class="form-select" id="category-select" name="category"> 92 <?php if(isset($_POST['category'])): ?> 93 <option selected><?php echo $obj->setCategoryName($category); ?></option> 94 <?php else: ?> 95 <option selected value="0">カテゴリーを選択してください</option> 96 <?php endif; ?> 97 <option value="1">求人</option> 98 <option value="2">人材育成・研修</option> 99 <option value="3">集客・マーケティング</option> 100 <option value="4">Webサイト制作</option> 101 <option value="5">Webコンテンツ制作</option> 102 <option value="6">イラスト</option> 103 <option value="7">営業・コールセンター代行</option> 104 <option value="8">ビジネス相談・経営コンサル</option> 105 <option value="9">士業(税理士・行政書士など)</option> 106 <option value="10">翻訳・語学</option> 107 <option value="11">クリーニング</option> 108 <option value="12">音楽・ナレーション</option> 109 <option value="13">その他</option> 110 </select> 111 <!-- サービスの参考価格 --> 112 <h6 id="p-price"><label for="kome"><font color="red">*</font></label>サービスを利用する際の参考価格</h6> 113 <?php if(isset($err['price'])): ?> 114 <p class="err_one"><font color="red"><?php echo $err['price'] ?></font></p> 115 <?php endif; ?> 116 <div class="mb-3"> 117 <input type="text" class="form-control" id="p-price_form" name="price" placeholder="29800" value="<?php if(isset($price)) echo h($price) ?>"> 118 </div> 119 <!-- 画像 --> 120 <h6 id="p-image">画像を追加してください</h6> 121 <?php if(isset($err['img'])): ?> 122 <p class="err_one"><font color="red"><?php echo $err['img'] ?></font></p> 123 <?php endif; ?> 124 <input type="hidden" name="MAX_FILE_SIZE" value="1048576"> 125 <input type="file" class="form-control" id="p-image_upload" name="img" value="<?php if(isset($_FILES['img']['name'])) echo $_FILES['img']['name'] ?>"> 126 <!-- リスト投稿ボタン --> 127 <div class="p-btn"> 128 <button type="submit" class="btn btn-primary" id="p-btn_btn" name="b">リストを投稿する</button> 129 </div> 130 </form> 131 </div> 132 </div> 133 <?php include(ROOT_PATH .'Views/common/footer.php'); ?> 134<script type="text/javascript" src="/js/script.js"></script> 135</body> 136</html>
tagのjavascript(script.js)
var input = document.querySelector('input[name="tags"]'), // init Tagify script on the above inputs tagify = new Tagify(input, { whitelist: ["急募","アフターフォロー","低価格","要相談"], maxTags: 5, dropdown: { maxItems: 50, // <- mixumum allowed rendered suggestions classname: "tags-look", // <- custom classname for this dropdown, so it could be targeted enabled: 0, // <- show suggestions on focus closeOnSelect: false // <- do not hide the suggestions dropdown once an item has been selected } }); // "remove all tags" button event listener document.querySelector('.tags--removeAllBtn') .addEventListener('click', tagify.removeAllTags.bind(tagify)) // Chainable event listeners tagify.on('add', onAddTag) .on('remove', onRemoveTag) .on('invalid', onInvalidTag); // tag added callback function onAddTag(e){ console.log(e, e.detail); console.log( tagify.DOM.originalInput.value ) tagify.off('add', onAddTag) // exmaple of removing a custom Tagify event } // tag remvoed callback function onRemoveTag(e){ console.log(e, e.detail); } // invalid tag added callback function onInvalidTag(e){ console.log(e, e.detail); }
投稿をDBに登録するロジック(Post.php)
<?php require_once(ROOT_PATH .'/Models/Db.php'); ini_set('display_errors', "On"); class Post { /** * リストの投稿をDBに保存 * @param string $postDate * @param string $save_path * @return bool $result */ public function createList($postDate, $save_path) { $result = false; $sql = 'INSERT INTO posts (title, text, category_id, price, img) VALUES (:title, :text, :category_id, :price, :img)'; $title = $postDate['title']; $text = $postDate['text']; $category = $postDate['category']; $price = $postDate['price']; try { $stmt = connect()->prepare($sql); $stmt->bindValue(':title', $title, PDO::PARAM_STR); $stmt->bindValue(':text', $text, PDO::PARAM_STR); $stmt->bindValue(':category_id', (int)$category, PDO::PARAM_INT); $stmt->bindValue(':price', (int)$price, PDO::PARAM_INT); $stmt->bindValue(':img', $save_path, PDO::PARAM_STR); $result = $stmt->execute(); return $result; } catch(\Exception $e) { return $result; } }
試したこと
中間テーブルのやり方とは別に投稿のDBにtagを追加し、中間テーブル使わずに強引にやってみた。
$sql = 'INSERT INTO posts (title, text, category_id, price, img,tag) VALUES (:title, :text, :category_id, :price, :img, :tag)'; ... $stmt->bindValue(':tag', $tag, PDO::PARAM_STR); ...
このように複数のタグはDBに保存できたが、何やらvalueがついていた。
こういった強引なやり方ではなく中間テーブルを持ちたやり方はどのようにすればいいのでしょうか?
サンプルコードとかあったら嬉しいです。
回答1件
あなたの回答
tips
プレビュー