• 締切済み

PDOで文字列が正しく書けない

PHP5.5(Windows 32bit) with PDO(PostgreSQL) + PostgreSQL 9.3(64bit) + Windows 7 です。 id(integer PK), text1(text), text2(text) の列を持つテーブル test に対して  INSERT INTO test (id, text1, text2) VALUES (41, '\', '<?xml version="1.0"?>') を pgp admin で実行すると正常に行がインサートされます。ところが PDO の prepare にこの SQL を単純に渡して実行すると text2 に <$1xml version="1.0"$2> というおかしな文字列がセットされてしまいます。 どうも 直前の列データが '\' というように、末尾が \ になっている文字列を渡す時だけ 次の列データ '<?xml version="1.0"?>' の中の ? がプレースホルダーとして処理されるっぽいのです。 どう考えてもPDOのバグのような気がするのですが、お心当たりのバグや回避方法などありましたら よろしくお願い致します。

みんなの回答

  • shimix
  • ベストアンサー率54% (865/1590)
回答No.2

>prepare にこの SQL を単純に渡して実行 「単純に渡して実行」するのに、? を含む文字列を渡しているんですか? プレースホルダが存在しないならprepareを使わずにqueryで直接実行すべきです。 $pdo->query('INSERT INTO test (id, text1, text2) VALUES (41, \'\\', \'<?xml version="1.0"?>\')'); プレースホルダ(prepare/execute)を使うなら $pdo->prepare("INSERT INTO test (id, text1, text2) VALUES (?, ?, ?)"); $pdo->execute(array(41, '\', '<?xml version="1.0"?>')); で書きますよね?

tknakamuri
質問者

補足

SQL自体は問題ないですよね? またSQL中のシングルクォートに囲まれた 「文字列」の中の「?」はプレースホルダ にはならないはずですよね? 実際、'\' が 'a' なら text2に ?を含んだ 文字列がそのままセットされます。 prepareが \ をエスケープ文字として処理しているような 気がしますが、まちがいでしようか? #posgreSQL9 は \ をエスケープ文字として #扱いません。postgreSQL8ではエスケープ文字です。 prepare を使っているのは、実はCakephp のモデルのsaveメソッドでこの問題を見つけた からなんです。Cakephpはパラメータを SQLに埋め込んで展開してから prepareを呼ぶという妙ちきりんなことを やるようです。

回答No.1

バグといってしまっては進歩がありませんよ。書いているコードが間違っているだけです。 どのようなコードを書いているのか提示してください。プレースホルダを使っていないコードになっていませんか?

tknakamuri
質問者

補足

実際には CakePHP で $data1 = ['Test' => []]; $data1['Test']['id'] = $id; $data1['Test']['text1'] = $this->data['text1']; $data1['Test']['text2'] = $xml->asXML(); $success = $this->Test->save($data1); # $xml は SimpleXML のオブジェクト。 としているだけなんです。画面上のテキストボックス text1 に \ だけを入力して、 Post時コントローラーで上記コードを実行すると、text2 に XML ヘッダが壊れた データが設定されるという問題に悩んでます。 質問で示したは CakePHP が生成した SQL で、 DboSource.php の _execute メソッドで pdo の prepare に渡されたものです。 prepare のオプションパラメータは array(), execute のパラメータも array() です。 execute 実行直後でデバッガで実行を止め、DB をのぞくとすでに化けたデータが入っています。 text1 に a など \ で終わらない文字列を入れれば正常に動作します。 ひょっとすると PDO の設定でしょうか?

関連するQ&A