0

編集:タイトルに「質問」という単語を含めることは許可されていません。Qマークは「疑問符」を意味します

編集2:ダミーの顧客レコードから個人の連絡先情報を削除する必要があることに気づきました

最近のプロジェクトのメンテナンスを減らすために、いくつかの基本的な機能を作ろうとしています。これらの中には、次の単純な関数があります。これにより、更新クエリを変更することなく、後日データベースに列を追加できます。

function update( $table, $fields ) {
    global $db; // A slightly modified PDO object
    if( count( $fields ) > 0 ) {
        $query = "UPDATE `" . $table . "` SET ";
        foreach( $customer as $key => $value ) {
            $query .= "`" . $key . "` = ?, ";
        }
        $query = substr( $query, 0, -2 );
        $query .= " WHERE `id` = " . $_REQUEST['id'];
        $db->prepare( $query );
        $db->execute( $fields );
    } else { return true; }
}

この関数は、1つまたは2つのフィールドを渡したときに機能していましたが、さらに渡そうとした瞬間に失敗しました。$fields受け取ったクエリ、値、エラーは次のとおりです。

クエリ:

string 'UPDATE `customers` SET `5v` = ?, `contactaddress` = ?, `contactaddress2` = ?, `contactcity` = ?, `contactemail` = ?, `contactname` = ?, `contactphone` = ?, `contactstate` = ?, `contactzip` = ?, `corrugated` = ?, `name` = ?, `permalok` = ?, `residential` = ?, `secureseam` = ?, `tax` = ? WHERE `id` = 1' (length=301)

$ fields:

array
  '5v' => string '120' (length=3)
  'contactaddress' => string '999 Street Dr' (length=13)
  'contactaddress2' => string 'Apt 2' (length=7)
  'contactcity' => string 'City' (length=9)
  'contactemail' => string 'steven.abarnett@gmail.com' (length=25)
  'contactname' => string 'Steven Barnett' (length=14)
  'contactphone' => string '(555) 555-5555' (length=14)
  'contactstate' => string 'KY' (length=2)
  'contactzip' => string '55555' (length=5)
  'corrugated' => string '90' (length=2)
  'name' => string 'Steven's Metals' (length=15)
  'permalok' => string '130' (length=3)
  'residential' => string '100' (length=3)
  'secureseam' => string '130' (length=3)
  'tax' => string '6' (length=1)

エラー:

string 'Statement execution failed: SQLSTATE[HY093]: Invalid parameter number: parameter was not defined' (length=96)

このエラーをグーグルで検索すると、疑問符のパラメーターではなく、名前付きパラメーターの問題のように聞こえます。なぜこのエラーが発生するのですか?

更新

私はデバッグと実験を続け、エラーを追跡しました。失敗したのはステートメントの実行ではなく、後で結果をフェッチしようとしたことです。

変更したPDOオブジェクトでは、execute()メソッド内に次のコードがあります。

    // Load from database
    try {
        $this->stmt->execute( $args );
        $this->lastid = $this->dbh->lastInsertId();
        $this->data = $this->stmt->fetchAll();
    } catch (PDOException $e) {
        $this->error = 'Statement execution failed: ' . $e->getMessage();
        return false;
    }

echoセクションの各行の間にステートメントを配置するtry{}と、最初の2行は問題なく実行されますが、3行目は例外をスローしています。

電話をかけると、クエリが一般的なエラーで失敗する理由はありますPDOStatement::fetchAll()か?

最終更新:

結局のところ、PDOとMysqlは6年間うまく機能していません。一般的な解決策は、を呼び出すたびにPDOStatementオブジェクトの設定を解除することのようですがPDOStatement::execute()、これはうまくいきませんでした。この問題は、MySQLがレコードセット内のレコードを指すカーソルを一度に1つしか開くことができないという事実に起因しているため、別の提案された解決策は、ORPDOStatement::fetchAll()の代わりにを使用PDOStatement::fetch()してを呼び出すことPDOStatement::closeCusor()です。繰り返しますが、これは私にはうまくいきませんでした。私の問題は、、、、およびクエリ中INSERTにカーソルを作成するMySQLの特定のインストールに起因します(これらはすべてデータを返しません)。これは、nullデータを指しているため閉じることができません。UPDATEDELETE

PDOStatement::fetchAll()私の解決策は、データを返すクエリを実行しているときにのみ呼び出すことでした。queryhashキャッシュ(PDOクラスに加えた大きな変更)で使用された変数がありfalse、これらの3つのクエリタイプに設定されています(キャッシュを延期するのではなく、データベースにクエリを送信する必要があるため)。execute()この変数をチェックfetchAll()し、falseに設定されていない場合にのみ呼び出すように、関数を変更しただけです。

4

2 に答える 2

4

連想配列ではなく、インデックス配列を使用する必要があります。

array(
    '120',
    '750 Shaker Dr',
    'Apt 505',
    'Lexington', 
    'steven.abarnett@gmail.com', 
    'Steven Barnett', 
    '(859) 402-7760', 
    'KY',
    '40504', 
    '90',
    "Steven's Metals",
    '130',
    '100',
    '130',
    '6'
)
于 2012-05-17T15:13:46.413 に答える
4

PHP 5.2以降、に渡される配列はexecute()、ステートメント文字列内のキーと同じキーを持っている必要があります。を使用したので、PDOは、連想配列ではなく、?数値でインデックス付けされた配列が渡されることを期待しています。execute()配列を作成するとき$fieldsは、各値を正しい順序で追加するだけで、キーを指定しないでください。または、次のように数値インデックス付き配列に抽出しますarray_values()

$db->execute(array_values($fields));

上のドキュメントを参照してくださいPDOStatement::execute()

5.2.0 input_parametersのキーは、SQLで宣言されているキーと一致する必要があります。PHP 5.2.0より前では、これは黙って無視されていました。

于 2012-05-17T15:14:34.210 に答える