1

私は次のコードを持っています:

    function insertrow($tablename,$record){
        $columns = $this->gettablecol($tablename);
        $types = $this->getbindtypestring($columns);    
        array_unshift($record, $types);                                             
        if(count($columns) && $types){              
            $query = 'INSERT INTO '.$tablename.' VALUES (?'.str_repeat(',?',count($columns)-1).')';
            if($stm = $this->linkid->prepare($query)){                  
                $res = call_user_func_array(array(&$stm,"bind_param"), $params);                    
                $stm->execute();                    
                print_r($stm);
                $stm->close();                                      
            }
        }
    }

$record配列は次のようになります。

    (
        [0] => sssisssssssssssi
        [recordid] => TEST1
        [recdate] => 2012-10-31 08:45:49
        [lastmod] => 2012-10-31 08:45:49
        [delflag] => 0
        [cusname] => Dilbert
        [address1] => 181 Somewhere
        [address2] => 
        [city] => St. Petersburg
        [state] => FL
        [zipcode] => 33713
        [telephone] => 8135551212
        [faxnumber] => 8135551313
        [webaddress] => 
        [taxid] => 260708780
        [pinnumber] => 12345
        [isactive] => 0 
)

しかし、$ stmは、データがないことを教えてくれます。

mysqli_stmt Object
(
    [affected_rows] => 0
    [insert_id] => 0
    [num_rows] => 0
    [param_count] => 16
    [field_count] => 0
    [errno] => 2031
    [error] => No data supplied for parameters in prepared statement
    [sqlstate] => HY000
    [id] => 1
)

$record配列が何らかの形で不正になっているようです。任意の洞察をいただければ幸いです。


こんにちはビル、ヘッズアップをありがとう。私はあなたのアドバイスを受けて、APIをPDOに切り替えました。しかし、私の問題は解決されていません。insertrowメソッドを次のように変更しました。

    function insertrow($tablename,$record){         
        $this->connect();
        $columns = $this->gettablecol($tablename);      
        if(count($columns)){                
            $query = 'INSERT INTO '.$tablename.' VALUES (?'.str_repeat(',?',count($columns)-1).')';
            try{
                $stm = $this->linkid->prepare($query);                  
                $stm->execute($record);
            }catch(PDOException $e){
                $this->errormsg = $e.getMessage();
                $this.errhandler();
                exit();
            }           
        }
    }

レコードは次のようになります。

Array
(
    [recordid] => TEST1
    [recdate] => 2012-11-01 09:12:50
    [lastmod] => 2012-11-01 09:12:50
    [delflag] => 0
    [cusname] => Dilbert
    [address1] => 181 Somewhere
    [address2] => 
    [city] => St. Petersburg
    [state] => FL
    [zipcode] => 33713
    [telephone] => 8135551212
    [faxnumber] => 8135551313
    [webaddress] => 
    [taxid] => 260708780
    [pinnumber] => 12345
    [isactive] => 0
)

$recordの値を新しい配列にコピーしました。

$newrec = array();
foreach($record as $row){
   $newrec = $row;
}

それはこのように見えました:

 Array
(
    [0] => TEST1
    [1] => 2012-11-01 09:01:32
    [2] => 2012-11-01 09:01:32
    [3] => 0
    [4] => Dilbert
    [5] => 181 Somewhere
    [6] => 
    [7] => St. Petersburg
    [8] => FL
    [9] => 33713
    [10] => 8135551212
    [11] => 8135551313
    [12] => 
    [13] => 260708780
    [14] => 12345
    [15] => 0
)

そしてそれを$stm->execute($ newrec)に渡しましたが、機能せず、例外もスローされませんでした。他に何か見ることができますか?

この時点で、$ record配列の受け渡しを削除し、値をハードコーディングしました。

$stm->execute(array('TEST2','2012-10-10 00:00:00','2012-10-10 00:00:00',0,'1','2','3','4','5','6','7','8','9','0','11',0));

準備と実行の両方がtrueに戻っても、まだレコードがテーブルに挿入されていません。

パラメータを特定のデータ型にバインドする必要がありますか?

4

1 に答える 1

2

bind_paramを使用することの難しさは、再利用可能なデータベースアクセス層を開発するときにMysqliを使用するのが嫌いな理由です。それは可能ですが、PHPの参照により、不必要に難解になっています。

解決策については、 mysqli_preparevsPDOの私の答えを参照してください

基本的に、渡す配列は、スカラーの配列ではなく、参照の配列である必要があります。

DBALを開発するときは、PDOを使用する方がはるかに簡単であることがわかりました。何もバインドする必要はありません。配列をPDOStatement::execute()に渡すだけです。


編集をやり直してください:

PDOがお役に立てたと思います。しかし、結局のところ、それが元の問題の根本的な原因ではなかった可能性があります。私の提案が野生のガチョウの追跡だった場合はお詫び申し上げます。しかし、少なくとも今はPDOを使用しているので、これはキャラクター構築の経験になっています。:-)

あなたのコードで私が気づいた2つのことですが、これらが問題であるかどうかはわかりません。

$ columns配列の数に基づいていくつかのパラメータープレースホルダーを追加しますが、これが$ record配列と同じ数であることをどのように知っていますか?パラメータプレースホルダーの数とexecute()に指定する値の数の間に不一致がある場合は、エラーです。

以下を確認する必要があります。

if (count($columns) != count($record)) { 
  // report error
}

または、$record配列にキーとして指定されている列のみを含めるようにすることもできます。

$columns_to_insert = array_intersect($columns, array_keys($record));

ちなみに(これはエラーではなく、単なるヒントです)、文字列の連結と1つずつエラーが発生するリスクを回避するために、次のようなパラメータープレースホルダーのシーケンスを生成します。

join(",", array_fill(0, count($record), "?"))

もう1つ気付いたのは、execute()の戻り値をチェックしていないことです。それが戻った場合はエラーがあり、エラーの性質を調査するfalse必要があります。

例外をキャッチしていますが、PDOのデフォルトのモードは例外をスローすることではなく、エラーを示すために関数の戻り値を設定するだけです。そのように使用できます。そうでない場合は、例外スローモードを明示的に有効にする必要があります。

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

その設定は、PDO接続の間グローバルです。行を挿入するたびにそれを行う必要はありません。

于 2012-11-01T02:10:26.523 に答える