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

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

ただいまの
回答率

90.12%

PHPファイルからINSERT(SQL文)を実行しても追加されない

受付中

回答 4

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 323

yamayama3965

score 5

前提・実現したいこと

現在PHPの勉強中で簡単な家計簿を作成しています。
DBへのINSERT文がうまくいっていないようです。
日付を取得してはいるが、それが入らないためにうまくいっていないのかと・・・

発生している問題・エラーメッセージ

PHPのファイルからDBへINSERTしても追加されません。
DBとの接続ができているかSELECT文を実行したところ、(40〜46行目)
予めテストとして入れておいた内容は取得できました。

エラーメッセージ等は発生しておらず、
処理が完了した際は処理完了後のメッセージが表示されます。

該当のソースコード

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>家計簿登録</title>
</head>
<body>

<p>家計簿</p>

<h2>支出の登録</h2>
<form action="" method="post" enctype="multipart/form-data">
    <select name="category">
        <?php
        $category = [
            "食費",
            "雑費",
            "生活費",
            "あそび"
        ];
        foreach($category as $item){
            echo '<option value ="'.$item.'">'.$item.'</option>';
        }
        ?>
    </select>
<input type="text" name="name"><br>
<input type="text" name="price">円<br>
<input type="submit" value="登録する" name="send">

</form>

</body>
</html>

<!-- DBに追加 -->
<?php
$pdo = new PDO('mysql:host=localhost; dbname=moneynote; charset=utf8', 'root', '');


// foreach($pdo->query('SELECT * FROM `record` WHERE `no` = 3') as $row){
// echo $row['no'];
// echo $row['day'];
// echo $row['category'];
// echo $row['name'];
// echo $row['price'];
// }


if(isset($_POST['send'])){
    $day = date("Y-m-d");
    $category = $_POST['category'];
    $name = $_POST['name'];
    $price = $_POST['price'];
    $sql = 'INSERT INTO `record`(`no`, `day`, `category`, `name`, `price`) VALUES (NULL, cast($day as data), $category, $name, $price);';
    $pdo->query($sql);
     echo "追加しました";
}

var_dump($day);



?>
<!-- DBに追加 ここまで -->

試したこと

SQL文の変数に値を直接入れて、phpmyadminから直接SQL文を実行すると内容は追加されました。

補足情報(FW/ツールのバージョンなど)

環境はmacでlammpを使用しています。
localhost:8080で表示しており、DBはphpmyadminを使用しています。

SQLの構造は以下の通りです。
テーブル:record

名前 データ型 照合順序 NULL デフォルト値 その他
no int(4) いいえ なし AUTO_INCREMENT
day date いいえ なし
category varchar(20) いいえ なし
name varchar(20) いいえ なし
price int(5) いいえ なし
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • m.ts10806

    2019/07/07 17:43

    タイトルは質問内容に寄せた要件(起きている問題など)を記載してください。

    キャンセル

回答 4

+1

シングルクォーテーション内では変数は展開されません。
またSQLに文字列を投入する場合、'で囲う必要があります。
ただ、このままですと入力情報をそのまま投入しているのでSQLインジェクションの脆弱性があります。
パラメーターでSQLセット(prepare)→値のセット(bindValue)→実行(execute)の流れにされたほうが良いでしょう。
また、try-catchでPDOExceptionを拾う作りも入れましょう。

もろもろ含めて下記のような記事は読んで実装に活かしましょう。
PHPでデータベースに接続するときのまとめ

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/08 05:08

    PHPで実行する前にDBに対して実行して想定通りの結果を得られるか確かめてみてください。
    DBはPHPからすると外部の概念であるため、直接実行して成功しなければもちろんPHPから実行しても動きません。
    SQLとはいってもPHPからすると単なる文字列の集合体に過ぎませんので、通常文字列を扱うときと同じように組む必要があります。
    echoで$sqlを出力してでてきた文字列がどのようなものか確かめて、それがDBに対して直接実行して成功するか確認するところからですね。

    キャンセル

  • 2019/07/08 21:49

    echo で出力した$sqlをDBに対して直接実行するとエラーが出ましたが、$categoryと$nameに入る文字列をダブルクォーテーションで囲めば成功しました。
    PHPでSQL文を実行する場合変数にダブルクォーテーションは使えないと思うのですが・・・やはりこれが原因でしょうか。

    キャンセル

  • 2019/07/23 10:11

    返信気づきませんでした。すみません。

    > echo で出力した$sqlをDBに対して直接実行するとエラーが出ましたが、$categoryと$nameに入る文字列をダブルクォーテーションで囲めば成功しました。

    ダブルクォーテーションではSQL的には値は文字列としては解釈されないと思います。

    >PHPでSQL文を実行する場合変数にダブルクォーテーションは使えないと思うのですが

    ちょっと意味が分からないです。PHPの変数とはあくまで文字列であって、SQLもその文字列の一端ですよ。

    キャンセル

0

最後に commit をしたら正常に insert されますでしょうか。
https://www.php.net/manual/ja/pdo.commit.php

直接 SQL を実行した場合、オートコミットのため正常に insert されているのかと思います。

ご参考ください。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/07 15:47

    INSERT分実行の後に「$pdo->commit();」を追記したところ、以下のエラーが生じました。

    Fatal error: Uncaught PDOException: There is no active transaction in /opt/lampp/htdocs/moneynote/money.php:56 Stack trace: #0 /opt/lampp/htdocs/moneynote/money.php(56): PDO->commit() #1 {main} thrown in /opt/lampp/htdocs/moneynote/money.php on line 56

    また、DBにもデータは追加されませんでした。

    キャンセル

  • 2019/07/07 17:44

    トランザクション張ってないとコミットは意味ないですね。

    キャンセル

0

下記のような形でSQLのエラー情報を確認してみて下さい。

$statement = $pdo->query($sql);

print_r($statement->errorInfo());

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/07 21:49

    Fatal error: Uncaught Error: Call to a member function errorInfo() on boolean

    上記のメッセージが表示されました。
    これって型が違うから入らないってことでしょうか?

    キャンセル

  • 2019/07/07 22:25 編集

    SQLの実行結果でfalseが帰ってきているようなので、やはりエラーが出ていると思います。下記でエラー内容を確認してみて下さい。

    $pdo->query($sql);
    print_r($pdo->errorInfo());

    キャンセル

  • 2019/07/07 22:30

    気になることがあと2点ほどあります。他の方も指摘しているシングルクオートの問題です。
    $sql = 'INSERT INTO `record`(`no`, `day`, `category`, `name`, `price`) VALUES (NULL, cast($day as data), $category, $name, $price);';

    $sql = "INSERT INTO `record`(`no`, `day`, `category`, `name`, `price`) VALUES (NULL, cast($day as data), $category, $name, $price);";
    に変更。

    あと、cast($day as data)は
    cast($day as date)の間違いでしょうか?

    ちなみに、この場合はキャストしなくても大丈夫だと思います。

    キャンセル

  • 2019/07/08 21:42

    ご指摘いただいたSQL文に変更し、エラー確認文を追記しました。

    Array ( [0] => 42S22 [1] => 1054 [2] => Unknown column '食費' in 'field list' ) 追加しました

    上記の内容が表示されました。
    また、cast($day as data)はcast($day as date)の間違いです・・・。
    初歩的なミスですみません・・・。

    キャンセル

0

$sql=のとこの最後 $price);'; この部分、もしこのまま書かれているなら )の次の;がシンタックスエラーではありますね。チェックしてみて書いてあるなら削除してください。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/07/07 21:50

    SQL文は最後に;がいると思うので一つ目の;はSQL文の終わり、二つ目の;は変数に代入の終わりを示しているのですがこの場合いらないのでしょうか?

    キャンセル

  • 2019/07/08 05:49

    少し勘違いされているのではないかと思いますよ。;は何文の最後だからとかではなく、その処理の最後(はい、これはここまでね みたいな意味)を表すものなので、この場合は変数にクォーテーションで囲まれたものを代入するという処理の最後に一つだけ入れる形となります。

    キャンセル

  • 2019/07/08 09:24 編集

    mari.rinnさん
    動かしてみればわかりますが、シンタックスエラーじゃないですよ。
    yamayama3965さんの仰っている通り、SQLの;とPHPの;で文末として意味合いが別のものです。

    キャンセル

  • 2019/07/08 09:34

    ええ?そうなんですか〜?私の方が勘違いでしたか〜!
    それは大変失礼いたしました〜!
    質問者様、ごめんなさい!!

    皆様もお目汚し失礼しました。

    キャンセル

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

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