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

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

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

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

PHP

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

Q&A

解決済

2回答

5260閲覧

beginTransactionのエラー:特定のファイルにだけ発生する原因

TakahashiManabu

総合スコア11

MySQL

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

PHP

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

0グッド

0クリップ

投稿2018/03/06 06:06

編集2018/03/06 08:06

お世話になります。

あるシステムの開発をPHPベースでしておりまして、特定のクラスファイル(Aとします)において、あるメソッドを実行すると「Fatal error: Call to a member function beginTransaction() on null in・・・」というエラーが出ました。

そこで実行されているSQL文を別のクラスファイル(Bとします)に移し、そのオブジェクトのメソッドとして実行すると正常に処理されます。

そうすると、Aのクラスファイル原因がありそうですが、Aのクラスには別のメソッドも明記されており、それらは正常に機能します。(追記:検証の結果、Aのクラスファイルにおいては、DBに接続しようとするメソッドにおいて、全てPDO接続がNULLとなっていました)

特定のクラスファイルにおいてのみ、特定のメソッドがエラーとなり、それは別のクラスファイルにおいてなら実行可能であるというような状況だとすると、どのような原因でそうなるのかが分からず苦労しております。ちなみに、Aのクラスファイルも、Bのクラスファイルも、ベースとなるファイルを継承し、pdo接続を可能としております。

ソースを提示したいのですが、とてつもなく膨大でどこまで記載すればよいかわからず、ここまでの状況を取り急ぎ報告いたします。もし、上記のエラーコードが発生する原因にお心当たりがあれば、ご教示いただけますと幸いです。

追記いたしました

下記に簡単ながらコードを記述いたします。
はじめにコントローラーとなるクラスファイルです。

PHP

1//コントローラーA 2 3<?php 4 5class controllerA extends BaseController{ 6 7public function __construct(){ 8 9 $this->fileModel = new fileModel(); 10 $this->transact = new transactModel(); 11 $this->mailer = new mailerModel(); 12 $this->systemModel = new systemModel(); 13 14} 15 16function methodCA(){ 17 18 if(isset($_FILES['file']['name'])){ 19 20 $file = $_FILES['file']['name']; 21 22 //ステータスコードがあればファイルチェックメソッドに移行 23 if(isset($_GET['statusCode']) && $_GET['statusCode']!=''){ 24 25 //ファイルチェック 26 list($inspectedResult,$message) = $this->fileModel->fileInspection($file,$_GET['statusCode']); 27 28 //ファイルチェックを通過 29 if($inspectedResult == TRUE){ 30 $filename = substr($file,0,9); 31 32 //格納ディレクトリを指定 33 $dir = _UPLOAD_DIR.'manuscripts/'.$filename.'/'; 34 35 //ファイル名を変更 - ハッシュ値へ 36 $filehash = hash_file("sha1",$_FILES["file"]["tmp_name"]); 37 38 //ファイルを格納 39 $this->fileModel->storeFile($filename,$dir,$filehash); 40 echo '<p>'.$message.'</p>'; 41 42 //ファイルアップロード情報の記録:**このメソッドがうまく機能しないのです** 43 $this->fileModel->registerFileHistory($filename,$filehash,$_FILES['file']['name'],$_GET['statusCode'],CURRENT); 44 45 //ステータスコードを変更する手続きへ 46 $this->transact->proceedStatusCode($_GET['statusCode'],$filename); 47 48 }else{ 49 50 //ファイルチェックの結果、不適切だと認められた場合 51 echo '<p>'.$message.'</p>'; 52 } 53} 54 55 }else{ 56 57 echo "ファイルがない・・・"; 58 } 59 60} 61 62 63}

次にモデルを司るクラスファイルです。

PHP

1class fileModel extends BaseModel{ 2 3//このメソッドを実行するとエラーになります。 4public function registerFileHistory($articleID,$vName,$aName,$statusCode,$date){ 5 6 $this->pdo->beginTransaction(); 7 8 try{ 9 10 $sql="INSERT INTO cl_file_inventry(articleID,virtualFileName,actualFileName,statusCode,dateUpdated) VALUES (:ID,:vName,:aName,:statusCode,:date)"; 11 $stmh=$this->pdo->prepare($sql); 12 $stmh->bindValue(':ID',$articleID,PDO::PARAM_STR); 13 $stmh->bindValue(':vName',$vName,PDO::PARAM_STR); 14 $stmh->bindValue(':aName',$aName,PDO::PARAM_STR); 15 $stmh->bindValue(':statusCode',$statusCode,PDO::PARAM_STR); 16 $stmh->bindValue(':date',$date,PDO::PARAM_STR); 17 18 $stmh->execute(); 19 $stmh->closeCursor(); 20 21 $this->pdo->commit(); 22 23 }catch(PDOException $Exception){ 24 $this->pdo->rollBack(); 25 print "エラー:".$Exception->getMessage(); 26 } 27 28} 29 30} 31 32//・・・・以下、いくつかのメソッド 33

最後に、ベースとなるモデルファイルです。

PHP

1<?php 2 3class BaseModel{ 4 5 protected $pdo; 6 7 public function __construct(){ 8 $this->db_connect(); 9 } 10 11 //---------------------------------------------------- 12 // データベース接続 13 //---------------------------------------------------- 14 private function db_connect(){ 15 try { 16 $this->pdo = new PDO(_DSN, _DB_USER, _DB_PASS, 17 array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET `utf8`") 18 ); 19 $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 20 $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 21 22 }catch(PDOException $Exception){ 23 die('エラー :' . $Exception->getMessage()); 24 } 25 } 26 27 28 29} 30 31?>

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

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

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

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

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

guest

回答2

0

Fatal error: Call to a member function beginTransaction() on null

和訳すると、「nullに対してbeginTransaction()メソッドを呼び出した」ということになります。つまり、Aの方では、呼ぼうとしたオブジェクトがnullになっています。

投稿2018/03/06 06:16

maisumakun

総合スコア145121

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

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

TakahashiManabu

2018/03/06 06:24

早速のご回答有難う御座います! 呼ぼうとしたオブジェクトはベースのファイルに記述しているpdo接続で$this->pdoとしているのです。 これがnullとなっているという理解でよろしいでしょうか? そうすると、クラスAに記載している別のSQLもpdo接続できないことになるのですが、実際には機能しているのです・・・・
退会済みユーザー

退会済みユーザー

2018/03/06 06:37

pdo接続のタイミングが想定とずれているのではないでしょうか。
TakahashiManabu

2018/03/06 06:39

m6u様 pdo接続のタイミング・・・・ですか?その点は考えもしなかったです。。。 具体的にそれをどのように見極めるためにはどの点を踏まえればよいでしょう?
退会済みユーザー

退会済みユーザー

2018/03/06 07:02

ソースコードを見ていないので簡単なことしか言えませんが、var_dump() を仕込むとか、PHP: エラー処理関数 - Manual <http://php.net/manual/ja/ref.errorfunc.php> を駆使するとか。IDE類を活用してステップ実行するのも手ですね。もうエラーでつまずかない!PHP言語でデバッグを行う方法 | TechAcademyマガジン <https://techacademy.jp/magazine/11647>
TakahashiManabu

2018/03/06 08:04

m6u様 コメント有難う御座います。 取り急ぎ、モデルを司るクラスの各メソッドにおいて、$this->pdoがどうなっているのかvar_dumpしてみましたところ、なんと、全てのメソッドにおいてNULLが出ていました。すなわち、ある特定のメソッドの身がpdo接続できないということではなく、そのクラスファイルではpdoオブジェクトがない状態になっていたのです。 そうすると、何故他のファイルと同様にBaseModelというクラスから継承しているのに、pdo接続がこのファイルに限ってうまくいっていないのか、という点が問題になります。。。。 取り急ぎご報告申し上げます。
guest

0

自己解決

皆様

自己解決致しました。以下、原因を報告致します。

原因となっていたものは、上記モデルクラスを司るfileModelにおいて、コンストラクタを設定していたことに起因します。コンストラクタを設定していた理由は、関連するクラスを使いまわせるよう予めオブジェクトを生成しておくためでした。

通常、コントローラーを司るクラスにおいて、関連するモデルのオブジェクトを生成していましたが、このfileModelにおいては他のモデルクラスと異なりコンストラクタを設定してしまっていたのです。

これにより、fileModelオブジェクトが生成された際、すぐさまBaseModelを継承してpdoオブジェクトも生成されることになります。BaseModelにおいては、pdoオブジェクトはコンストラクタを通じて生成されます。

つまり、

継承元(BaseModel)においてコンストラクタを通じてpdoオブジェクトが生成
継承先(fileModel)においてコンストラクタを通じて別のオブジェクトが生成

という具合に、コンストラクタどうしが衝突する・・・みたいなことになっていたのです。
これによって、結果としてpdoはNULLとなってしまっていた、という事象が生じたようでした。

以上わかる範囲内でお伝えいたします。

ご尽力くださいました皆様、本当に有難う御座いました。

投稿2018/03/06 09:05

TakahashiManabu

総合スコア11

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問