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

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

ただいまの
回答率

90.62%

  • PHP

    19870questions

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

  • MySQL

    5701questions

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

mysqli関数でプリペアドステートメントを利用してselect文を実行した際の結果の取得について

解決済

回答 1

投稿

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

orange0190

score 1590

かなり長いと思いますが、ご了承ください。
以下のコードは自作のライブラリの一部で、PHPでmysqli関数利用の場合、mysql関数利用の場合(mysql関数が非推奨なのは承知しているが念のため)、PDO利用の場合、それぞれでmysqlのデータベースでselect文を実行するものになります。
この関数の返り値は「数字添字配列形式の実行結果の数字添字配列」となるのですが、それを「オブジェクト形式の実行結果の数字添字配列」で返したいです。
mysql利用およびPDO利用の場合ではできるのですが、mysqli利用の場合でオブジェクト形式にできません。

どうかご教授をお願いします。mysqliは手続き型でお願いします。

    //------------------------------------------------------------------------------
    // SELECT文を実行する
    //
    // パラメータ
    //        $_tableName:テーブル名
    //        $_items:取得する項目 配列で入力
    //        $_andWhere:ANDで結ぶ条件 array(array(対象, 条件, 評価値),...)の形で入力
    //        $_orWhere:ORで結ぶ条件 array(array(対象, 条件, 評価値),...)の形で入力
    //        $_order:ORDER BY の文 array(array(対象, タイプ),...)の形で入力
    //        $_limit:LIMITの数値
    //        $_offset:OFFSETの数値
    //
    // 返り値
    //        mixed SQLの実行に成功したなら数字添字配列形式の実行結果の数字添字配列 失敗したならfalse
    //------------------------------------------------------------------------------
    public function select($_tableName = '', $_items = null, $_andWhere = null, $_orWhere = null, $_order = null, $_limit = '', $_offset = '')
    {
        //タイプ取得
        $_type = $this->dbType;
        //テーブル名をチェック
        if(!$_tableName){
            $this->dbErr = __LINE__ . ' : Bad arguents. in $_tableName';
            $this->dbErrNo = $this->dbType . '_' . SEL_TBL_ERR;
            throw new DBException($this->dbErr, $this->dbErrNo);
        }
        //SELECT文を作成開始
        $_sql = 'SELECT ';
        //取得アイテムを羅列
        if(!$_items or $_items === '*'){
            //取得アイテムに指定がない場合には、全アイテムを取得
            $_sql .= '*';
        } else {
            if(!is_array($_items)){
                //取得アイテムが配列じゃない場合には例外を発生させる
                $this->dbErr = __LINE__ . ' : Bad arguents. $_item will need to be in the array in "select($_tableName, $_items, $_andWhere, $_orWhere, $_order, $_limit, $_offset)".';
                $this->dbErrNo = $this->dbType . '_' . SEL_ITEM_ERR;
                throw new DBException($this->dbErr, $this->dbErrNo);
            }
            for($_i = 0; $_i < count($_items); $_i++){
                $_items[$_i] = $this->backQuote($_items[$_i]);
            }
            //取得アイテムを結合してSQL文に追加
            $_sql .= join(', ', $_items);
        }
        //SQL文にテーブル名を追加
        $_sql .= ' FROM ' . $this->backQuote($_tableName);
        
        //条件の部分を作成
        $_condition = '';
        $_conditionAnd = '';
        $_conditionOr = '';
        
        $_replaceVal = array();
        
        //ANDで結合する条件
        if($_andWhere){
            if(!is_array($_andWhere)){
                //配列じゃない場合はパラメータエラーを返す
                $this->dbErr = __LINE__ . ' : Bad arguents. $_andWhere will need to be in the associative array in "select($_tableName, $_items, $_andWhere, $_orWhere, $_order, $_limit, $_offset)".';
                $this->dbErrNo = $this->dbType . '_' . SEL_WHERE_ERR;
                throw new DBException($this->dbErr, $this->dbErrNo);
            }
            foreach($_andWhere as $_val){
                if($_conditionAnd !== ''){
                    $_conditionAnd .= ' AND ';
                }
                //条件文を作成
                $_sqlWhere = $this->sqlWherePrepare($_replaceVal, $_val[0], $_val[1], $_val[2]);
                if(!$_sqlWhere){
                    //作成した条件文が不正
                    $this->dbErr = __LINE__ . ' : Bad arguents. It is not possible to make a conditional statement.';
                    $this->dbErrNo = $this->dbType . '_' . SEL_WHERE_ERR;
                    throw new DBException($this->dbErr, $this->dbErrNo);
                }
                $_conditionAnd .= $_sqlWhere;
            }
        }
        if($_conditionAnd !== ''){
            if($_condition !== ''){
                $_condition .= ' AND (' . $_conditionAnd . ')';
            } else {
                $_condition = ' WHERE (' . $_conditionAnd . ')';
            }
        }
        
        //ORで結合する条件
        if($_orWhere){
            if(!is_array($_orWhere)){
                //配列じゃない場合はパラメータエラーを返す
                $this->dbErr = __LINE__ . ' : Bad arguents. $_orWhere will need to be in the associative array in "select($_tableName, $_items, $_andWhere, $_orWhere, $_order, $_limit, $_offset)".';
                $this->dbErrNo = $this->dbType . '_' . SEL_WHERE_ERR;
                throw new DBException($this->dbErr, $this->dbErrNo);
            }
            foreach($_orWhere as $_val){
                if($_conditionOr !== ''){
                    $_conditionOr .= ' OR ';
                }
                //条件文を作成
                $_sqlWhere = $this->sqlWherePrepare($_replaceVal, $_val[0], $_val[1], $_val[2]);
                if(!$_sqlWhere){
                    //作成した条件文が不正
                    $this->dbErr = __LINE__ . ' : Bad arguents. It is not possible to make a conditional statement.';
                    $this->dbErrNo = $this->dbType . '_' . SEL_WHERE_ERR;
                    throw new DBException($this->dbErr, $this->dbErrNo);
                }
                $_conditionOr .= $_sqlWhere;
            }
        }
        if($_conditionOr !== ''){
            if($_condition !== ''){
                $_condition .= ' AND (' . $_conditionOr . ')';
            } else {
                $_condition = ' WHERE (' . $_conditionOr . ')';
            }
        }
        
        //条件文をSQL文に追加
        if($_condition !== ''){
            $_sql .= $_condition;
        }
        
        //ORDER BYの部分を作成
        $_orderBy = '';
        if($_order){
            if(!is_array($_order)){
                //配列じゃない場合はパラメータエラーを返す
                $this->dbErr = __LINE__ . ' : Bad arguents. $_order will need to be in the associative array in "select($_tableName, $_items, $_andWhere, $_orWhere, $_order, $_limit, $_offset)".';
                $this->dbErrNo = $this->dbType . '_' . SEL_ORDER_ERR;
                throw new DBException($this->dbErr, $this->dbErrNo);
            }
            foreach($_order as $_val){
                if(!is_array($_val)){
                    //配列じゃない場合はパラメータエラーを返す
                    $this->dbErr = __LINE__ . ' : Bad arguents. $_order will need to be in the associative array in "select($_tableName, $_items, $_andWhere, $_orWhere, $_order, $_limit, $_offset)".';
                    $this->dbErrNo = $this->dbType . '_' . SEL_ORDER_ERR;
                    throw new DBException($this->dbErr, $this->dbErrNo);
                }
                if(count($_val) != 2){
                    //要素数が2じゃない場合はパラメータエラーを返す
                    $this->dbErr = __LINE__ . ' : Bad arguents. The number of elements in the elements of $_order must be 2.';
                    $this->dbErrNo = $this->dbType . '_' . SEL_ORDER_ERR;
                    throw new DBException($this->dbErr, $this->dbErrNo);
                }
                
                if($_orderBy === ''){
                    $_orderBy = $this->backQuote($_val[0]) . ' ' .$_val[1];
                } else {
                    $_orderBy .= (', ' . $this->backQuote($_val[0]) . ' ' .$_val[1]);
                }
            }
        }
        
        //SQL文にORDER BY を追加
        if($_orderBy !== ''){
            $_sql .= ' ORDER BY ' . $_orderBy;
        }
        
        //LIMIT OFFSETの部分を作成
        $_limitPart = '';
        if($_limit !== ''){
            if($_offset !== ''){
                $_limitPart = ' LIMIT ' . $_offset . ', ' . $_limit;
            } else {
                $_limitPart = ' LIMIT ' . $_limit;
            }
        }
        
        //SQL文にLIMIT OFFSETを追加
        if($_limitPart !== ''){
            $_sql .= $_limitPart;
        }
        
        //SQLを実行する  **********************ここ以降を教えてほしいです。
        if($_type == 1){
            //mysqliの場合
            //プリペアドステートメントの準備
            $_stmt = mysqli_stmt_init($this->dbCon);
            //プリペアドステートメントの作成
            if(!$_result = mysqli_stmt_prepare($_stmt, $_sql)){
                $this->dbErr = __LINE__ . ' : SQL execution failure. Because "' . mysqli_stmt_error($_stmt) . '"';
                $this->dbErrNo = $this->dbType . '_' . SEL_EXEC_ERR;
                throw new DBException($this->dbErr, $this->dbErrNo);
            }
            //置き換える値の種類を設定
            $_paramStr = '';
            for($_i = 0; $_i < count($_replaceVal); $_i++){
                $_varType = gettype($_replaceVal[$_i]);
                switch($_varType){
                    case 'string':
                        $_paramStr .= 's';
                        break;
                    case 'integer':
                        $_paramStr .= 'i';
                        break;
                    case 'double':
                        $_paramStr .= 'd';
                        break;
                    default:
                        break;
                }
            }
            //任意の数の引数を引き渡したいのでcall_user_func_arrayを利用
            //call_user_func_arrayへ渡す引数の設定
            $_stmtParams = array($_stmt, $_paramStr,);
            for($_i = 0; $_i < count($_replaceVal); $_i++){
                $_stmtParams[] = &$_replaceVal[$_i];
            }
            if(count($_replaceVal) > 0){
                if(!$_result = call_user_func_array('mysqli_stmt_bind_param', $_stmtParams)){
                    $this->dbErr = __LINE__ . ' : ' . mysqli_stmt_error($_stmt);
                    $this->dbErrNo = $this->dbType . '_' . SEL_EXEC_ERR;
                    throw new DBException($this->dbErr, $this->dbErrNo);
                }
            }
            //ここでSQLを実行
            if(!$_result = mysqli_stmt_execute($_stmt)){
                $this->dbErr = __LINE__ . ' : SQL execution failure. Because "' . mysqli_stmt_error($_stmt) . '"';
                $this->dbErrNo = $this->dbType . '_' . SEL_EXEC_ERR;
                throw new DBException($this->dbErr, $this->dbErrNo);
            }
            $_fieldCount = mysqli_stmt_field_count($_stmt);
            $_binds = array($_stmt);
            $_bindsParam = array();
            for($_i = 0; $_i < $_fieldCount; $_i++){
                $_binds[] = &$_bindsParam[$_i];
            }
            if(!$_result = call_user_func_array('mysqli_stmt_bind_result', $_binds)){
                $this->dbErr = __LINE__ . ' : SQL execution failure. Because "' . mysqli_stmt_error($_stmt) . '"';
                $this->dbErrNo = $this->dbType . '_' . SEL_EXEC_ERR;
                throw new DBException($this->dbErr, $this->dbErrNo);
            }
            $_resultRows = array();
            while(mysqli_stmt_fetch($_stmt)){
                $_row = array();
                for($_i = 0; $_i < $_fieldCount; $_i++){
                    $_row[] = $_binds[$_i + 1];
                }
                $_resultRows[] = $_row;
            }
            mysqli_stmt_close($_stmt);
            return $_resultRows;
        } else if($_type == 2) {
            //mysqlの場合
        } else if($_type == 3) {
            //PDOの場合
        } else {
            $this->dbErr = __LINE__ . ' : You can not run the SQL.';
            $this->dbErrNo = $this->dbType . '_' . SEL_EXEC_ERR;
            throw new DBException($this->dbErr, $this->dbErrNo);
        }
    }
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

mysqli_stmt_execute の後で mysqli_stmt_get_result して mysqli_fetch_object すると良いと思います。

$db = mysqli_connect("localhost", "test", "pass", "test");
$sql = "select id from t";
$stmt = mysqli_prepare($db, $sql);
mysqli_stmt_execute($stmt);
$result = mysqli_stmt_get_result($stmt);
$rows = array();
while ($row = mysqli_fetch_object($result)) {
    $rows[] = $row;
}
var_dump($rows);

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2015/05/18 13:49

    ありがとうございます。
    おかげでオブジェクト形式での取得ができました。

    キャンセル

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

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

関連した質問

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

  • PHP

    19870questions

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

  • MySQL

    5701questions

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

  • トップ
  • PHPに関する質問
  • mysqli関数でプリペアドステートメントを利用してselect文を実行した際の結果の取得について