質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.11%

PHP 1つのページで登録も更新もするには

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,105

kuzurotto

score 403

下記のような経歴登録フォームがあったとします。
「業務経歴を追加する」を押すと同じフォームが生成されます。

イメージ説明

このページでは、入力するだけのページを想定して作っていたのですが、
登録するボタンを押すとそのままDBへ格納するSQL文が走ります。

しかし、
登録(INSERT)も更新(UPDATE)もこの1つのページでしてくれと言われているのですが
どうすればそれができるでしょうか?

更新ということは、DBから情報を取り出して、
このフォームのvalueにその情報を渡して再現できると思うのですが、

もともと、入力するだけのページを想定して作っていたので、
登録するを押すと、以前入力した情報と同じ内容が登録されてしまいます。(更新ではない)

1つのページで登録も更新もするにはどうしたらよろしいのでしょうか?
個人的には登録ページと更新ページは分けた方がいいのかなとは思うんですが...

マイナビ転職サイトの更新ページを参考にしているんですが
例えば、自己PRには私が以前入力したものが表示されています。

この自己PRをちょっと変更して「変更内容を保存する」を押すと多分ですが、
UPDATEのSQLが走ってると思います。

でも、志望動機に関してはまだ何も入力したことがないので、
何か入力して「変更内容を保存する」を押すと多分ですが、
INSERTのSQLが走ってると思います。

そこがどういうロジックになってるのかが分からないのです...

パッと思いついたのが
単純にDBの内容を取得してemptyとかで判定して
なければINSERT
あればUPDATE

なんですが、こういう風にしているだけなのでしょうか?

イメージ説明

宜しくお願いします。


追記

回答ありがとうございます。

ON DUPLICATE KEY UPDATEを使ってテストしているのですが、
これを実行すると上から2行目がテスト1に変わることは分かりました。

$sql = "INSERT INTO user_vitae(
user_id,
projectTitle,
projectsContents
) VALUES (?, ?, ?)
ON DUPLICATE KEY UPDATE
user_id = ?,
projectTitle = ?,
projectsContents = ?
";
        for($i=0;$i<count($_POST['projectTitle']);$i++) {
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute([
$_SESSION['id'],
$_POST['projectTitle'][$i],
$_POST['projectsContents'][$i],
$_SESSION['id'],
$_POST['projectTitle'][$i],
$_POST['projectsContents'][$i]
            ]);

イメージ説明

しかし、案件名をUNIQUEにしているので、例えば
「test1」登録しておいて、
案件名を「test2」に変えたいなぁ~ってなったら、
更新ではなく新規登録になってしまいます。

これはどう防げばよいのでしょうか?

入力を必要としないカラムはこうなってます...

イメージ説明

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+2

【取得時】

SELECTで取得を試みて,データがあればそれを,無ければ空欄を表示するだけです.

【挿入時または更新時】

REPLACEあるいはINSERT ... ON DUPLICATE KEY UPDATE構文が使えます.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/07/11 09:30

    他の方の回答のように,取得してきたときの結果を元にINSERTとUPDATEを分岐するのもナシではないですが,取得のためのコードと挿入/更新のためのコードが密結合になってしまってスパゲティコードの要因になるので,完全に分離するためにREPLACEなどを利用することをおすすめします.なお,REPLACEとINSERT...ON DUPLICATE KEY UPDATEの違いは,カラムがデフォルト値を持っているときに発生しますので,どちらを使うべきかよく検討してください.

    キャンセル

  • 2016/07/11 10:08

    そんな方法もあるのですね!
    ありがとうございます!

    キャンセル

+1

更新のときは、そのデータが、DBのどのレコードか示すキーを
セッションに持つなり、フォームに埋め込むなりして、フォームがPOSTされたときに
それを受け取って更新するんですから、それがないときはINSERTするだけですよね。

更新の仕組み作れば分かりますよね。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/07/11 10:19

    ログイン時にidをセッションに保存しております。
    ありがとうございます。

    キャンセル

+1

こちらの質問が参考になると思います。
https://teratail.com/questions/40485

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/07/11 10:21

    ありがとうございます。
    拝見させていただきます。

    キャンセル

0

UPDATEするには主キーが必要になってくると思うので、主キーがあればUPDATE
なければINSERTみたいな感じでifで条件分岐するのが見やすいかもしれません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/07/11 10:08

    参考になります!
    ありがとうございます!

    キャンセル

  • 2016/07/11 10:47

    ユニークキーと主キー(プライマリキー)は違いますよ。
    変更するために参照するのはidなどのAIがついた数字のキーにしたほうが何かと便利です。
    (forやwhileで回せるので)

    キャンセル

  • 2016/07/11 11:24

    YuyaKoshimizuさんがおっしゃっています方法は、
    ON DUPLICATE KEY UPDATEではなく
    普通のifということですよね?

    キャンセル

0

先に主キーでupdateして処理件数がゼロなら、insertという手があります。
その場合、select文を実行しなくて済みます。

http://www.sacnoha.com/?p=1531

私なら、updateからinsertの部分をストアドにします。

upsertのsql文を使うのも良いのですが、他のDBによって結構書き方が違いますし、sql文自体の可読性が悪いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/07/11 10:23

    ありがとうございます。
    参考になります。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.11%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる