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

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

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

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

PHP

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

Q&A

解決済

2回答

3604閲覧

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

GoNa

総合スコア11

PDO

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

PHP

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

0グッド

1クリップ

投稿2016/05/15 02:37

編集2016/05/15 06:03

初心者で申し訳ございません。
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結果が取得されません。

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

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

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

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

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

guest

回答2

0

ベストアンサー

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

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

sql

1SELECT 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オブジェクトを作成後に

php

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

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

投稿2016/05/15 16:40

KiyoshiMotoki

総合スコア4791

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

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

GoNa

2016/05/16 15:09

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

0

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

PHP

1ini_set( 'display_errors', 1 );

投稿2016/05/15 06:23

takasima20

総合スコア7458

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

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

GoNa

2016/05/15 06:32

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問