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

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

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

20095閲覧

PHPのトランザクションエラーの原因がわかりません。

dog57

総合スコア131

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

1クリップ

投稿2018/02/20 10:41

編集2018/02/23 01:23

PHPで編集機能を作成していたところ、トランザクションエラーが発生しましたが、
原因が特定できません。

一体何が原因なのでしょうか?

エラー

Fatal error: Uncaught PDOException: There is no active transaction in /var/www/html/Portfolio/public_html/account_edit_insert.php:163 Stack trace: #0 /var/www/html/Portfolio/public_html/account_edit_insert.php(163): PDO->rollBack() #1 {main} thrown in /var/www/html/Portfolio/public_html/account_edit_insert.php on line 163

account_edit_insert.php

<?php ini_set("display_errors", 1); error_reporting(E_ALL); session_start(); // 文字化け対策 header("Content-type: text/html; charset=UTF-8"); require_once('./functions.php'); require_once('../config/db.php'); // ログインしていなければ login_form.php に遷移 require_logined_session(); // 初期化 $errors = array(); // POST時 if (filter_input(INPUT_SERVER, 'REQUEST_METHOD') == 'POST') { $_SESSION["name"] = filter_input(INPUT_POST, 'name'); $_SESSION["email"] = filter_input(INPUT_POST, 'email'); $_SESSION["password"] = filter_input(INPUT_POST, 'password'); $_SESSION["tel"] = filter_input(INPUT_POST, 'tel'); $name = $_SESSION["name"]; $email = $_SESSION["email"]; $password = $_SESSION["password"]; $tel = $_SESSION["tel"]; // // バリデーション // // 入力チェック if (empty($_SESSION["name"])) { $errors[] = "名前が入力されていません。"; } if (empty($_SESSION["email"])) { $errors[] = "E-mailが入力されていません。"; } if (empty($_SESSION["password"])) { $errors[] = "パスワードが入力されていません。"; } if (empty($_SESSION["tel"])) { $errors[] = "電話番号が入力されていません。"; } // 名前の文字数チェック if (strlen($_SESSION["name"]) >= 60) { $errors[] = "氏名が長すぎます。"; } // パスワード文字数チェック(8文字以上かどうか) if (preg_match("/^[a-zA-Z1-9]{1,7}$/", $_SESSION['password'])) { $errors[] = "パスワードは8文字以上で入力してください。"; } // 電話番号の文字数チェック(10文字 or 11文字) if (strlen($_SESSION['tel']) >= 1 && strlen($_SESSION['tel']) <= 9 && preg_match("/^[0-9]+$/", $_SESSION['tel'])) { $errors[] = "電話番号は10文字か11文字で入力してください。"; } elseif (strlen($_SESSION['tel']) >= 12 && preg_match("/^[0-9]+$/", $_SESSION['tel'])) { $errors[] = "電話番号は10文字か11文字で入力してください。"; } // メールアドレス形式チェック if (!preg_match("/^([a-zA-Z0-9])+([a-zA-Z0-9._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9._-]+)+$/", $_SESSION['email']) && $_SESSION['email'] !== '') { $errors[] = "メールアドレスに間違いがあります。"; } // 電話番号の形式チェック if (preg_match("/[-]+/", $_SESSION['tel'])) { $errors[] = "電話番号はハイフンなしで入力してください。"; } // 電番番号の数字チェック // メールアドレス形式チェック if (!preg_match("/^([a-zA-Z0-9])+([a-zA-Z0-9._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9._-]+)+$/", $_SESSION["email"]) && $_SESSION["email"] !== "") { $errorMsg[] = "メールアドレスに間違いがあります。"; } if (count($errors) > 0) { $_SESSION["errors"] = $errors; header("Location: account_edit.php"); } if (count($errors) === 0) { try { $dbh = new PDO($dsn, $user, $password); // プリペアドステートメント $statement = $dbh->prepare("UPDATE users SET name = :name, email = :email, password = :password, tel = :tel WHERE id = :id"); // トランザクション開始 $dbh->beginTransaction(); if ($statement) { // プレースホルダへ実際の値を設定する $statement->bindValue(':name', $_SESSION['name'], PDO::PARAM_STR); $statement->bindValue(':email', $_SESSION['email'], PDO::PARAM_STR); $statement->bindValue(':password', $_SESSION['password'], PDO::PARAM_STR); $statement->bindValue(':tel', $_SESSION['tel'], PDO::PARAM_STR); $statement->bindValue(':id', $_SESSION['id'], PDO::PARAM_STR); // クエリ実行 $statement->execute(); // トランザクションコミット $dbh->commit(); } } catch (PDOException $e) { $dbh->rollBack(); print('Error:' .$e->getMessage()); $errors["error"] = "データベース接続失敗しました。"; } } } // // Twig // // Composerで作成されたautoload.phpを読み込む require_once('../vendor/autoload.php'); // Twig_Loader_Filesystemを使う。account_edit_insert.phpからのtemplatesディレクトリを指定。(相対パス) $loader = new Twig_Loader_Filesystem('../templates'); // $loaderをTwigの環境設定としてTwig instance を生成 $twig = new Twig_Environment($loader); // render // render echo $twig->render('account_edit_insert.html', array( 'errors' => $errors, 'name' => $name, 'email' => $email, 'password' => $password, 'tel' => $tel ) );

・接続DBは portfolioデータベースの中の usersテーブル
イメージ説明
イメージ説明

追記 エラー

Error:SQLSTATE[HY000] [1045] Access denied for user 'andrew'@'localhost' (using password: YES)

mysql 権限
イメージ説明
mysql テーブル
イメージ説明

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/02/20 11:27

該当ソースコードの他のソースで正常にトランザクション処理ができていてこのソースだけできていないのか、それとも全部できないのか。また、接続先データベースの情報も欲しいです。そもそもトランザクション処理に対応しない設定(?)で構築されていたりしないか、とか。
dog57

2018/02/20 11:58

他のソースコードでは、エラーはでません。このソースコードだけできていません。どういったDB情報を追加したらよいでしょうか?
dog57

2018/02/20 12:02

DB情報を画像で追加しました!
退会済みユーザー

退会済みユーザー

2018/02/20 13:05 編集

机上デバックレベルで参加所でおきえるな。
guest

回答2

0

ベストアンサー

おそらくnew PDOの箇所で例外が発生していると思います。
なぜ、そう言えるかですが、以下に説明されているように、PDOは明示的にPDO::ERRMODE_EXCEPTIONを指定しない限り、例外は発生しないからです。

PHP: エラーおよびエラー処理 - Manual

PDO::ERRMODE_SILENT
デフォルトのモードです。ステートメントおよびデータベースオブジェクトの エラーについて、PDO は単にそのエラーコードのみを設定します。

注意:
PDO::__construct() は、接続に失敗した場合は常に PDOException をスローします。 これは、現在設定されている PDO::ATTR_ERRMODE が何であっても同じです。例外を処理しないと、fatal エラーとなります。

では、なぜrollbackに失敗しているようなエラーメッセージになっているかですが、以下のように、エラーメッセージを表示する前にrollbackメソッドを呼んでいるからです。この時点でもエラーになり、そのエラーが表示されています。

PHP

1 } catch (PDOException $e) { 2 $dbh->rollBack(); 3 print('Error:' .$e->getMessage()); 4 $errors["error"] = "データベース接続失敗しました。"; 5 } 6

さしあたり、rollback処理を削除して、エラーメッセージを表示させてください。どっちみち、今のスクリプトでは、例外発生時は接続に失敗しているので、rollbackの必要はないはずです。
あるいは、意図したような例外処理にするには、以下を追加することです。

PHP

1$dbh = new PDO($dsn, $user, $password, array( 2 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION 3 ));

投稿2018/02/21 22:11

ockeghem

総合スコア11701

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dog57

2018/02/22 10:20 編集

ありがとうございます。 次は、質問投稿欄の1番下に追記したエラーが出ました。 DBに関する設定は大丈夫だと思っていまして、どこか書き方が間違っているかと自分では思っています。 どんな原因が考えられますでしょうか?
退会済みユーザー

退会済みユーザー

2018/02/23 00:58

「DBに関する設定は大丈夫だ」と第三者が見ても思えるような情報提供がないのでなんともいえませんが、 エラーメッセージ的にはandrewってユーザーのアクセスを拒否しているので、 mysql内のユーザーandrewが登録されていないとか、パスワード間違いか、権限不足かと思われます。 os上ユーザーのパスワードと、mysql内ユーザーのパスワードはまた違う扱いだろうと思いますし、 同じパスワードを使いまわしたりは通常はしないものと思われます。 DB接続のみのシンプルなphpコードを書いて、 本当にDB接続ができるのかを試したら良いと思います。
退会済みユーザー

退会済みユーザー

2018/02/23 02:31

ここまでいくとユーザーの作り方を失敗してるな
guest

0

#1. DB接続失敗時の例外

PDO::__construct() は、 指定されたデータベースへの接続に失敗した場合、 PDOException を投げます。

#2. プリコンパイル時の例外

もしデータベースサーバーが正常に文を準備する場合、 PDO::prepare() は PDOStatement オブジェクトを返します。 もしデータベースサーバーが文を準備できなかった場合、 PDO::prepare() は FALSE を返すか PDOException を発行します (エラー処理 の方法に依存します)。

#3. トランザクション処理開始失敗時の例外

トランザクションが既に開始されている場合や、ドライバがトランザクションに対応していない場合に PDOException をスローします。

あたりは見た目で気づきましょう

投稿2018/02/20 13:09

編集2018/02/21 02:00
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/02/21 01:15

public bool PDO::beginTransaction ( void ) 成功した場合に TRUE を、失敗した場合に FALSE を返します。 →失敗してもPDOExceptionをthrowしないから、別途検出ロジック必要。っと勝手に補足させていただきます。
退会済みユーザー

退会済みユーザー

2018/02/21 01:29

beginTransaction http://php.net/manual/ja/pdo.begintransaction.php トランザクションが既に開始されている場合や、ドライバがトランザクションに対応していない場合に PDOException をスローします。
退会済みユーザー

退会済みユーザー

2018/02/21 03:39

お手数おかけしてすみません。
dog57

2018/02/23 11:27

解決致しました。 ご協力ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問