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

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

ただいまの
回答率

88.92%

MySQL : insertがうまくいかない

受付中

回答 2

投稿

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

tk0x2bc

score 42

PHPからMySQLに接続し、何個かテスト用にデータをinsertしようとしました。

function debugPrint($var) {
  echo '<pre>';
  print_r($var);
  echo '</pre>';
}

function create_hash($raw) {
  if ($raw === '' || is_null($raw)) {
    $hashed = password_hash(time() * rand(), PASSWORD_BCRYPT, array('cost' => 10));
  } else {
    $hashed = password_hash($raw, PASSWORD_BCRYPT, array('cost' => 10));
  }
    return $hashed;
}

$list = [
  ['user1', 'user1', 'admin'],
  ['user2', 'user2', 'staff'],
  ['user3', 'user3', 'staff'],
  ['user4', '', 'parttime'],
  ['user5', '', 'parttime'],
  ['user6', '', 'parttime'],
];

foreach ($list as $row) {
  $stmt = $dbh->prepare("insert into users (username, password, role, created_at, updated_at) values (?, ?, ?, now(), now())");
  $stmt->execute([$row[0], create_hash($row[1]), $row[2]]);
}

$stmt = $dbh->query("select * from users");
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

debugPrint($rows);

このようにphpからinsertを行おうとしたのですが、$list[0]に対応するデータしかinsertされません。phpをひさしぶりに触るというのもあるのですが、何がおかしいのかわかりません。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+1

データベースを以下のように定義して、

CREATE TABLE `test_database`(
    `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
    `username` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
    `password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
    `role` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
    `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
    `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci


質問者さんのコードをこちらで動作するようにして動作させたところ

<?php
$dsn = "mysql:dbname=sample01;host=localhost;charset=utf8";
$user = "username";
$password = "password";
$options = [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_EMULATE_PREPARES => false,
];

try {
    $dbh = new PDO($dsn, $user, $password, $options);
} catch (PDOException $exception) {
    echo $exception->getMessage();
    exit();
}

function create_hash($raw)
{
    if ($raw === '' || is_null($raw)) {
        $hashed = password_hash(time() * rand(), PASSWORD_BCRYPT, array('cost' => 10));
    } else {
        $hashed = password_hash($raw, PASSWORD_BCRYPT, array('cost' => 10));
    }
    return $hashed;
}

function debugPrint($var)
{
    echo '<pre>';
    print_r($var);
    echo '</pre>';
}

$list = [
    ['user1', 'user1', 'admin'],
    ['user2', 'user2', 'staff'],
    ['user3', 'user3', 'staff'],
    ['user4', '', 'parttime'],
    ['user5', '', 'parttime'],
    ['user6', '', 'parttime'],
];

foreach ($list as $row) {
    try {
        $stmt = $dbh->prepare("insert into `test_database` (username, password, role, created_at, updated_at) values (?, ?, ?, now(), now())");
        $stmt->execute([$row[0], create_hash($row[1]), $row[2]]);
    } catch (PDOException $exception) {
        echo $exception->getMessage();
        exit();
    }
}

$stmt = $dbh->query("select * from `test_database`");
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

debugPrint($rows);


正常に動作しているように見えるのですが、一度SQLなどでエラーが発生していないか、データベースへ接続する箇所のコードは合っているかなどをもう一度確認していただけませんか?
以下、SELECTの結果です。

Array
(
    [0] => Array
        (
            [id] => 1
            [username] => user1
            [password] => $2y$10$zLRvAtx8E3vDrXR01M7Bf..sCepi.ErzkOqfRJ76aXAnCr3HU2OXG
            [role] => admin
            [created_at] => 2017-05-08 00:11:55
            [updated_at] => 2017-05-08 00:11:55
        )

    [1] => Array
        (
            [id] => 2
            [username] => user2
            [password] => $2y$10$eGRbwfGTllNhAP.IJ57PBuD5scZ3Kl.GufxiekaRxBw1lGGbousy6
            [role] => staff
            [created_at] => 2017-05-08 00:11:55
            [updated_at] => 2017-05-08 00:11:55
        )

    [2] => Array
        (
            [id] => 3
            [username] => user3
            [password] => $2y$10$KEsVgUjEjDqx.PGj1Sred.q568JZ18zc0g6bQ2LcQWZS7uSRuleOq
            [role] => staff
            [created_at] => 2017-05-08 00:11:55
            [updated_at] => 2017-05-08 00:11:55
        )

    [3] => Array
        (
            [id] => 4
            [username] => user4
            [password] => $2y$10$hJaHNdmS0ZvYifR9RvQ7/.NR6fbqJ/ex.byNiNITSGpMwoIA439Iq
            [role] => parttime
            [created_at] => 2017-05-08 00:11:55
            [updated_at] => 2017-05-08 00:11:55
        )

    [4] => Array
        (
            [id] => 5
            [username] => user5
            [password] => $2y$10$5T6DJLXWkPWk6popEy5PneOPwfposSu2UbMrXE4yZy6cpDQjZulza
            [role] => parttime
            [created_at] => 2017-05-08 00:11:55
            [updated_at] => 2017-05-08 00:11:55
        )

    [5] => Array
        (
            [id] => 6
            [username] => user6
            [password] => $2y$10$5y6ucEvixJGoxlO9H0TAROlGD6.D3Tk2ZaeXlZc/h8OWw5U27qu22
            [role] => parttime
            [created_at] => 2017-05-08 00:11:55
            [updated_at] => 2017-05-08 00:11:55
        )

)

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/05/08 00:38

    回答ありがとうございます。DB接続部分などかなり注意して見ましたが、deleteやselectは普通通りに実行でき、おかしいところは無いように思えました。当然ながら例外なども発生しておらず、どこをどう直したらいいのかわからない状態です。回答者様のようにinsertできることを想定しているのですが、、、

    キャンセル

  • 2017/05/08 00:43 編集

    テーブルのidがauto_incrementになっているかどうかを確認してみてください。auto_increment担っていない場合、追加はされないと思います。もしそれでも解決しなかった場合、私の回答文のSQLとPHPのコードを質問者さんの環境で動かしてみて動作するか確認してみていただけませんか?

    キャンセル

  • 2017/05/08 00:51

    idはauto_incrementになっていました。回答者様のコードは私の環境でも動作しました。もう一度私のコードを確認してみたいと思います。
    丁寧にご回答頂いてありがとうございます。

    キャンセル

0

prepare は使いまわすことが前提なので、foreach の外に出して下さい。
foreach 内で値が適切に渡っているか確認するのは、var_dump($row) を挿入することで確認できます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/05/08 00:41

    $list[0]がどんどん追加されていきます。foreach内でvar_dump($row)が正常に表示されているのですが、insert部分で$list[0]以外の$rowが無視されているような感じです。これまでに経験したことが無いような動きです。

    キャンセル

  • 2017/05/08 00:56

    後は try catch 使ってエラーが出るか確認するぐらいですかねぇ^^;
    環境作ってないんで、確認取れませんが、s8_chu さんの結果見ても動きそうなんですよね。

    キャンセル

  • 2017/05/08 01:00

    try catchでもエラーは出てないので、他のところに何か誤りがあるかと思っています。ちょっとすぐには解決しようにないのでゆっくりはじめから書き直して確認したいと思います。回答ありがとうございました。

    キャンセル

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

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

関連した質問

同じタグがついた質問を見る