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

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

ただいまの
回答率

88.04%

phpでCSVファイルを確認画面つきでMySQLへのインポートする方法

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 4,590

score 58

php にてCSVファイルアップロード→CSVの内容を確認画面で表示→MySQLへインポートというものを作りたいと思い、下記を参考に作成してみました。

CSVアップロードからのMySQLへのデータ挿入

■問題点
・確認画面でCSVファイルの内容は表示されるものの、MySQLへデータが挿入されません。

・確認画面/完了ページの切り替えをhiddenのmodeを使ってやろうとしているのですが、それが間違いなのでしょうか。

(確認画面の表示処理とDBへの登録処理がごちゃごちゃになってきてしまい、非常にわかりにくくなってきてしまいました。)

<?php

$mode = (string) filter_input ( INPUT_POST, 'mode' );

if ( isset($_FILES['csvfile']['error']) && is_int($_FILES['csvfile']['error']) ) {

    try {

        // エラーチェック
        switch ($_FILES['csvfile']['error']) {
            case UPLOAD_ERR_OK:
                // エラーなし
                break;
            case UPLOAD_ERR_NO_FILE:
                //ファイル未選択
                throw new RuntimeException ('File is not selected');
            case UPLOAD_ERR_INI_SIZE:
            case UPLOAD_ERR_FORM_SIZE:
                // 許可サイズを超過
                throw new RUntimeException ('File is too large');
            default:
                throw new RUntimeException ('Unknown error');
        }

        // 一時ファイル名
        $tmp_name = $_FILES['csvfile']['tmp_name'];

        $detect_order = 'ASCII,JIS,UTF-8,CPS51932,SJIS-win';
        setlocale(LC_ALL, 'ja_JP.UTF-8');

        // 文字コードを変換
        $buffer = file_get_contents($tmp_name);

        if ( !$encoding = mb_detect_encoding( $buffer, $detect_order, true ) ) {
            // 文字コードの自動判定に失敗
            unset ($buffer);
            throw new RuntimeException('Character set detection failed');
        }

        file_put_contents ( $tmp_name, mb_convert_encoding($buffer, 'UTF-8', $encoding) );
        unset ($buffer);


        $dsn = "mysql:dbname=guestbook;host=localhost;charset=utf8";
        $pdo = new PDO ( $dsn, 'test', 'test' );
        $pdo->setAttribute ( PDO::ATTR_EMULATE_PREPARES, false );
        $pdo->setAttribute ( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
        $sql = "INSERT INTO ms_member (username, password, reg_date) VALUES (?, ?, NOW())";
        $stmt = $pdo->prepare($sql);

        // トランザクション処理
        $pdo->beginTransaction();

        try {
            $fp = fopen( $tmp_name, 'rb' );
            //var_dump($tmp);

            // 確認用テーブル表示
            if ( $mode === "confirm" ) {
                echo "<table border=\"1\">\n";
                    while ( $rows = fgetcsv( $fp, "1024") ) {
                        echo "<tr>\n<td>{$rows[0]}</td>\n";
                        echo "<td>{$rows[1]}</td>\n";
                        echo "<td>{$rows[2]}</td>\n";
                        echo "<td>{$rows[3]}</td>\n</tr>\n";
                    }
                echo "</table>\n";

            // 完了
            } else if ( $mode === "finish" ) {
                while ( $rows = fgetcsv( $fp ) ) {
                    if ( $row === array(null) ){
                        // 空行はスキップ
                        continue;
                    }

                    $stmt->bindValue (1, $row[0], PDO::PARAM_STR);
                    $stmt->bindValue (2, $row[1], PDO::PARAM_STR);
                    $stmt->bindValue (3, $row[2], PDO::PARAM_INT);

                    $executed = $stmt->execute($row);
                }
                if ( !feof($fp) ) {
                    // ファイルポインタが終端に達していなければエラー
                    throw new RuntimeException ( 'CSV parsing error' );
                }
                fclose($fp);
                $pdo->commit();
            }

        } catch (Exception $e) {

            if ( $mode === "finish" ) {
                fclose($fp);
                $pdo->rollBack();
                throw $e;
            }

        }

        if ( $mode === "finish" ) {
            if ( isset($executed) ) {
                $err_msg = 'Import Successful';
                header ( 'Location: ./finish.html' );
            } else {
                $err_msg = 'There was nothing to import';
            }
        }

    } catch (Exception $e) {
        $err_msg = $e->getMessage();
    }
}

header ( 'Content-Type: text/html; charset=utf-8' );
?>
<!DOCTYPE html>
<html lang="ja">
<head>
    <title>csvアップロード</title>
</head>
<body>

    <?php if (isset($err_msg)) {
        echo "<p style=\"color:red;\">" . $err_msg . "</p>";
    }?>

    <?php
    // POSTされていない状態
    if ( !$mode ) {
        echo <<<EOD
        <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="csvfile" size="30"><br>
        <input type="submit" value="アップロード確認">
        <input type="hidden" name="mode" value="confirm">
        </form>
EOD;

    // 確認画面
    } else if ( $mode === 'confirm' ) {
        echo <<<EOD
        <form action="" method="post">
        <input type="submit" value="アップロード完了">
        <input type="hidden" name="mode" value="finish">
        </form>
EOD;
    }
    ?>

</body>
</html>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

ぱっと見た限り、
確認画面ではファイルがアップロードするフォームが無いので、
確認画面からの送信では常にファイルが無い状態になるんじゃないかと思います。

最初にアップロードされたタイミングで一時的にファイルをサーバ側で保存して、
sessionか何かで確認画面後のアクセスと紐づけられるようにしたり、
CSVの中身をhiddenで確認画面後のフォームに入れる等、
何らかの方法で最初の送信画面と確認画面とでデータの受け渡しの仕組みを作る必要があります。

同じファイルでやってしまっているので混乱されているようにも見えるので、
一度違うファイルで作ってみると、わかりやすくなるかと思いますよ。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/06/05 19:17

    ありがとうございます。確かに一旦分けて整理した方が良さそうですね。。

    キャンセル

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

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

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