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

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

ただいまの
回答率

90.47%

  • PHP

    20812questions

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

  • PDO

    337questions

    PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

[PDO]DB接続をクラス化してSELECTの結果を受け取りたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,364

GoNa

score 3

初心者で申し訳ございません。
PDOの扱いなのか、PHPのスコープが理解できていないのかもわかっていない状態です。
お答えいただくと助かります。

前提・実現したいこと

処理のオブジェクト指向化進めているのですが、PDO,SQLを投げるマッパークラス,メインと
処理を分けようとしています。

PDOの接続(DBクラス)はマッパークラスのインスタンスを生成時(Singletonパターン適用)に
メンバに保持しています。
SELECTメソッド(マッパークラス)からDBクラスのSELECTメソッドを呼び出して実行。
結果ステートメントを返り値として呼び出し元(メイン)で使用したいと考えています。
メインの1行目の処理でSELECTの結果が変数に入れたいのですが、入ってくれません。

発生している問題・エラーメッセージ

メインに結果ステートメントが返ってきた時点で結果が入っていません。

該当のソースコード

//------------- メイン ---------------------------------------
//データが存在していればテンポラリからデータを反映させる
$stmt   =   $this->tradingsMapper->getDistinctData( array( 'deal_day' ) );
//print_r( $stmt );

$cnt = 0;
//今から書き込もうとしているデータを一旦削除する(最新のデータを正とする)
try
{
    while ( $row = $stmt->fetch( PDO::FETCH_OBJ ) )
    {
        print_r( $row );
        echo $row->deal_day . 'データを削除します。' . "\n";
        $result = $this->tradingsMapper->deleteTradings( array( $row->deal_day ) );
        if ( $result[1] != 0 )
        {
            throw new Exception( $result[2] );
        }
        print( $row->deal_day . "のデータを" . $this->dbh->getProcCnt() . "件削除しまた。\n");
        $cnt++;
    }
}
catch( Exception $e )
{
    throw new Exception( $e );
    print('削除に失敗しました。' . $e->getMessage());
}

//------------- マッパークラス ---------------------------------------
class tradingsMapper extends _dataMapper
{
    private         $TABLE_NAME = 'tradings';
    private static  $instance;
    private         $dbh;

    private function __construct()
    {
        $this->dbh  = databaseHandler::getInstance();
    }

   public static function getInstance()
    {
        if ( !isset( self::$instance) )
        {
            self::$instance   =   new self();
        }
        return  self::$instance;
    }
    ・
    ・
    ・
    public function getDistinctData( $column_name )
    {
        $qty    =   count( $column_name );
        $sql    =   '';
        $sql    .=  'SELECT  DISTINCT ';
        for ( $cnt=0; $cnt<$qty; $cnt++ )
        {
            echo $cnt . "\n";
            $sql    .=  ($cnt === 0) ? '        ? ' : ',       ? ';
        }
        $sql    .=  'FROM    ? ';

        try
        {
            $bind   =   $column_name;
            $cnt    =   array_push( $bind , $this->TABLE_NAME );
print_r( $bind );
print( $sql . "\n" );
            $stmt =   $this->dbh->getData( $sql , $bind );
        }
        catch( Exception $e )
        {
            $stmt =   NULL;
        }
print_r( $stmt );
        return  $stmt;
    }
    ・
    ・
    ・
}

//------------- DBクラス ---------------------------------------
class databaseHandler
{
    private $pdo;
    private static $instance;

    private function __construct()
    {
        $this->connectDatabase();
    }

    public static function getInstance()
    {
        if ( !isset( self::$instance ) )
        {
            self::$instance =   new self();
        }
        return  self::$instance;
    }
    ・
    ・
    ・
    private function connectDatabase()
    {
        try
        {
            $this->pdo  =   new PDO( DBTYPE . ":dbname=" . DBNAME . ";host=" . DBHOST , DBUSER , DBPASS );
            $this->pdo->query( "SET NAMES " . DBCHARSET );

            $this->pdo->beginTransaction();
        }
        catch( PDOException $e )
        {
            print('データベースに接続できませんでした。' . $e->getMessage());
            die();
        }
    }

    public function getData( $sql , $data = null )
    {
print_r( $data );
        $stmt = $this->pdo->prepare( $sql );
        if ( $data !== null )
        {
            $stmt->execute( $data );
        }
        else
        {
            $stmt->execute();
        }
print_r( $stmt );
        $this->cnt = $stmt->rowCount();

        return $stmt->fetch();
    }
    ・
    ・
    ・
}

試したこと

元々、分離せず作っていたので元に戻してメイン内で実行して結果が返ってくることを確認しました。
SQLの生成部分を汎用化したので、生成されるSQLの構文チェックを行っています。

補足情報(言語/FW/ツール等のバージョンなど)

PHP5.6,PDOでの開発で、
環境はCentOS7,Apache2.4.6,MariaDB5.5.47です。

メインの1行目
$stmt   =   $this->tradingsMapper->getDistinctData( array( 'deal_day' ) ); 
でステートメントにSELECT結果が取得されません。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

checkベストアンサー

+1

getDistinctDataメソッド内で構築しているSQL文が、構文エラーとなっています。

構築後のSQL文は以下のようになりますが、

SELECT  DISTINCT         ? ,       ? , ... FROM    ? 


MySQLでは、識別子(テーブル名やカラム名のこと)にプレースホルダを使用することはできません。
https://dev.mysql.com/doc/refman/5.6/ja/prepare.html

パラメータマーカーは、SQL キーワードや識別子などではなく、データ値を指定するべき場所にしか使用できません。


ちなみにPDOは、デフォルトの設定ではエラーが発生しても例外を投げてくれません。
http://php.net/manual/ja/pdo.error-handling.php

PDO::ERRMODE_SILENT

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

そうするためには、PDOオブジェクトを作成後に

$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);


を実行する、などの措置が必要です。
http://php.net/manual/ja/pdo.setattribute.php

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/17 00:09

    ありがとうございます。問題だった部分は動作しました。
    まだ、ほかの部分でエラーが出ていますがご教授いただいた
    規則でデバッグしてゆきます。
    今回は非常に勉強になりました。

    キャンセル

0

ざっとみたところまずいとこはわかりませんでした。
下記を先頭に追記してエラー情報を表示してみてください。

ini_set( 'display_errors', 1 );

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/05/15 15:32

    ありがとうございます。
    実行した結果、
    Fatal error: Call to a member function fetch() on boolean in /***/***.php on line 161
    と出てメインの
    while ( $row = $stmt->fetch( PDO::FETCH_OBJ ) )部分でエラーとなってしまいました。もう一度検証したいと思います。

    キャンセル

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

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

関連した質問

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

  • PHP

    20812questions

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

  • PDO

    337questions

    PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。