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

解決済

回答 2

投稿 編集

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

お世話になります。

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

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

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

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

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

追記いたしました

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

//コントローラーA

<?php

class controllerA extends BaseController{

public function __construct(){

    $this->fileModel = new fileModel();
    $this->transact = new transactModel();
    $this->mailer = new mailerModel();
    $this->systemModel = new systemModel();

}

function methodCA(){

 if(isset($_FILES['file']['name'])){

  $file = $_FILES['file']['name'];

  //ステータスコードがあればファイルチェックメソッドに移行
  if(isset($_GET['statusCode']) && $_GET['statusCode']!=''){

  //ファイルチェック
  list($inspectedResult,$message) = $this->fileModel->fileInspection($file,$_GET['statusCode']);

  //ファイルチェックを通過
  if($inspectedResult == TRUE){
  $filename = substr($file,0,9);

  //格納ディレクトリを指定
  $dir = _UPLOAD_DIR.'manuscripts/'.$filename.'/';

  //ファイル名を変更 - ハッシュ値へ
  $filehash = hash_file("sha1",$_FILES["file"]["tmp_name"]);

  //ファイルを格納
  $this->fileModel->storeFile($filename,$dir,$filehash);
  echo '<p>'.$message.'</p>';

  //ファイルアップロード情報の記録:**このメソッドがうまく機能しないのです**
  $this->fileModel->registerFileHistory($filename,$filehash,$_FILES['file']['name'],$_GET['statusCode'],CURRENT);

  //ステータスコードを変更する手続きへ
  $this->transact->proceedStatusCode($_GET['statusCode'],$filename);

 }else{

  //ファイルチェックの結果、不適切だと認められた場合
    echo '<p>'.$message.'</p>';
  }
}

 }else{

    echo "ファイルがない・・・";
 }

}


}


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

class fileModel extends BaseModel{

//このメソッドを実行するとエラーになります。
public function registerFileHistory($articleID,$vName,$aName,$statusCode,$date){

        $this->pdo->beginTransaction();

    try{

        $sql="INSERT INTO cl_file_inventry(articleID,virtualFileName,actualFileName,statusCode,dateUpdated) VALUES (:ID,:vName,:aName,:statusCode,:date)";
        $stmh=$this->pdo->prepare($sql);
        $stmh->bindValue(':ID',$articleID,PDO::PARAM_STR);
        $stmh->bindValue(':vName',$vName,PDO::PARAM_STR);
        $stmh->bindValue(':aName',$aName,PDO::PARAM_STR);
        $stmh->bindValue(':statusCode',$statusCode,PDO::PARAM_STR);
        $stmh->bindValue(':date',$date,PDO::PARAM_STR);

        $stmh->execute();
        $stmh->closeCursor();

        $this->pdo->commit();

    }catch(PDOException $Exception){
        $this->pdo->rollBack();
        print "エラー:".$Exception->getMessage();
    }

}

}

//・・・・以下、いくつかのメソッド


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

<?php

class BaseModel{

    protected $pdo;

    public function __construct(){
        $this->db_connect();
    }

    //----------------------------------------------------
    // データベース接続
    //----------------------------------------------------
    private function db_connect(){
        try {
          $this->pdo = new PDO(_DSN, _DB_USER, _DB_PASS,
        array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET CHARACTER SET `utf8`")
    );
          $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
          $this->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

        }catch(PDOException $Exception){
          die('エラー :' . $Exception->getMessage());
        }
    }



}

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+3

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

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/03/06 15:39

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

    キャンセル

  • 2018/03/06 16:02

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

    キャンセル

  • 2018/03/06 17:04

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

    そうすると、何故他のファイルと同様にBaseModelというクラスから継承しているのに、pdo接続がこのファイルに限ってうまくいっていないのか、という点が問題になります。。。。
    取り急ぎご報告申し上げます。

    キャンセル

check解決した方法

0

皆様

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

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

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

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

つまり、

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

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

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

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

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