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

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

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

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

Q&A

解決済

3回答

3873閲覧

プレースホルダー絡みのFatal error

earnest_gay

総合スコア615

PHP

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

0グッド

0クリップ

投稿2016/06/24 08:34

11行は$stmt = $pdo->query("SELECT pref,city FROM user_data ORDER BY id DESC LIMIT ?, 5;");
の分部で、プレースホルダーを5にしてみるとエラーはでないのでプレースホルダーが絡んだエラーだとは思うのですが、分かる方いらっしゃいましたら原因を教えてください...

$page = $_GET["page"]; $stmt = $pdo->query("SELECT pref,city FROM user_data ORDER BY id DESC LIMIT ?, 5;"); $stmt->execute([$page * 5]);

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '?, 5' at line 1' in C:\xampp\htdocs\xxx\test.php:11 Stack trace: #0 C:\xampp\htdocs\xxx\test.php(11): PDO->query('SELECT pref,cit...') #1 {main} thrown in C:\xampp\htdocs\xxx\test.php on line 11

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

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

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

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

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

guest

回答3

0

ベストアンサー

こちらの質問について、まだ、理解されていませんでしたか?
prepareとexecuteとqueryの使い分けについて

"SELECT pref,city FROM user_data ORDER BY id DESC LIMIT ?, 5;

「?」 に変数を割り当てしたいわけですから、prepare execute の出番ではありませんか?

ただし、 プレースホルダに ? を使う場合、'' で文字列として割り当てられるため、LIMIT句には利用できません。


以下の場合、prepare() + execute() ではなく、query() で十分な例ですが、WHERE句で拡張するものだろうから、初めからこのように実装。

php

1<?php 2$page = filter_input(INPUT_GET, 'page'); 3$start = (int) $page * 5; 4$sql = sprintf("SELECT pref,city FROM user_data WHERE 1 ORDER BY id DESC LIMIT %d, 5", $start); 5$stmt = $pdo->prepare($sql); 6$stmt->execute();

一人前のプログラマが行き詰まった時に当たり前にやっているRSAPって何?

新米プログラマが身につけておきたいデバッグに必要な3つのこと

投稿2016/06/24 08:50

編集2016/06/24 10:06
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

earnest_gay

2016/06/24 08:56

昨日の質問を思い出しました。 >>プレースホルダに ? を使う場合、'' で文字列として割り当てられるため、LIMIT句には利用できません。 文字列として割り当てられるためというのがちょっと分からないですが、こういった使い方はできないんですね...
退会済みユーザー

退会済みユーザー

2016/06/24 08:58

思い出してください! せっかく回答したのに、悲しくなります。
earnest_gay

2016/06/24 09:05

masaya_ohashiさん リンク先のものはなんなのでしょうか?英語は全然ダメで... Kosuke_Shibuyaさん すいません。 executeした時点で文字列になるという認識でいいのでしょうか?
earnest_gay

2016/06/24 09:12

分からないなりに色々試しましたが、こちらで読み込めました! $page = $_GET["page"]; $stmt = $pdo->prepare("SELECT pref,city FROM user_data ORDER BY id DESC LIMIT :while, 5"); $stmt->bindValue(':while', $_GET['page'] * 5, PDO::PARAM_INT); $stmt->execute();
退会済みユーザー

退会済みユーザー

2016/06/24 09:14

rentoさん 「英語は全然ダメで...」これではダメです。辞書を使ってでも読んでください。英語が苦手は言い訳になりません。回答者は翻訳家ではありませんし、サポートセンターじゃありません。「英語が苦手」というのでしたらプログラミングは諦めてください。それくらい当たり前にできなきゃいけないレベルです。
退会済みユーザー

退会済みユーザー

2016/06/24 09:24

rentoさん while という命名はイケてないと思います。
masaya_ohashi

2016/06/24 09:26 編集

厳しいことを言うようですが、Kosuke_Shibuyaさんの言うとおりで、プログラマは英語が読めないと将来ついていけなくなります。私も英語は苦手でしたが、Excite翻訳先生やGoogle翻訳先生の力添えの元、原文と日本語を見比べるうちにある程度翻訳なしでも自力で読めるようになりました。やらなきゃ覚えません。できないできないと拒否していては、いつまで経ってもここでおんぶにだっこです。そして、ずっとここにおんぶにだっこでいると、そのうちみんなから突き放されるかと思います。せめて自分で歩けるようになり、躓いたときにここに頼る、くらいの力をつけてくれることを望みます。もちろん一朝一夕で身につくものではないので、せめて努力しておいてください。 で、そのやり方でGoodです。成長を見ました。ただ、whileという名前で置き換えるのは意味がおかしいと思うので、page等のほうがふさわしいでしょう。 訂正 pageよりもoffsetのほうが…いや、でも予約後のOFFSETとかぶるしまずいか…_offsetとかですかね
earnest_gay

2016/06/24 09:29

2点分からないことがあります。 sprintf("・・・・・ ORDER BY id DESC LIMIT %d, 5", $page); ①[$page * 5]の5はどこにいったのか? --------------------------------------------------------------------- ② LIMIT 取り出す位置,取り出す件数 から LIMIT %d, 5", $page ではなく LIMIT %d,$page, 5", ではないのか?
KiyoshiMotoki

2016/06/24 09:29

横から失礼します。 masaya_ohashi様 > executeでまとめて渡しちゃうとだめなようですが、 これがだめな理由は、execute メソッドでパラメータを渡した場合、すべて文字列として扱われるためです。 http://php.net/manual/ja/pdostatement.execute.php  input_parameters   実行される SQL 文の中のバインドパラメータと同数の要素からなる、 値の配列。すべての値は PDO::PARAM_STR として扱われます。 ちなみに、 > bindValueを使えばINTとして割り当てるとかできます。 についても、  $stmt->bindValue(1, "5", PDO::PARAM_INT); のように文字列を渡してしまうと、やはりエラーになります。 (ご提示のリンクでも、第二引数をキャストすることで実行可能になっています) さらにちなみに(w)、  PDO::ATTR_EMULATE_PREPARES = false にしておくと、(意図する結果が得られるかは別として)上記いずれの方法でも実行可能です。
earnest_gay

2016/06/24 09:34 編集

英語についても話すことはできなくても読めるようには努めます! しばらくは迷惑かけるかもしれませんが、できるだけ自分でなんとかして、本当に分からないことは質問させていただきたいと思います。
退会済みユーザー

退会済みユーザー

2016/06/24 09:33

rentoさん ①については、間違っていたので首星済み。ソースをご覧ください。 ②実行してみればわかることなので、回答しません。
退会済みユーザー

退会済みユーザー

2016/06/24 09:38

@rentoさん 厳しいかもしれませんが、「慣れ」です。自分はあまり英語だけらといって抵抗はない方ですが、以外と全部は読んでいないです。全部を理解しなくても、大抵ソースコードを見てわかるようになりますので、解説なんてほとんど読んでいません。 結局どこが問題で、どうソースコードを直せばいいのか、がわかれば事足りるわけです。とにかく手を動かして実験を繰り返せばいいんです。
earnest_gay

2016/06/24 09:44

Kosuke_Shibuyaさん ありがとうございます。 自分の性格もあるのかもしれませんが、一貫性タイプといいますか、全て理解してからじゃないと物凄く気持ち悪く感じてしまうのです... 昔はこうでもなく、 「とりあえずここいぢったらあそこが変わったから、次はここいぢってこうしとけばいいか」みたいな感じでポンポンできてたんですけどね...
退会済みユーザー

退会済みユーザー

2016/06/24 09:56

@rentoさん 例えば、②の質問ですが、先に書いたとおり、試せばどうなるかはわかることですね。これをいちいち聞かれても回答者は何を答えればいいのでしょう。「エラーになります」としか答えようがありません。 しかもそれはあなたが実行さえすれば、誰の手を煩わせることなく、同じ結果が得られます。エラーになる原因はなぜか?と問われたら、回答者は答えを書くことができます。その差なんです。 回答者ってかなり気を使って回答を書いています。変な先入観や思い込みは捨てて、書いてあることを書いてあるままに読んでください。 どうもrentoさんの反応を見ていると、書いてあることを書いてあるままに読んでいない印象を受けます。
earnest_gay

2016/06/24 10:24

Kosuke_Shibuyaさん 今回は試せばよかったのですが、電車内や移動中に質問していることもあり、動作確認できない状態もあります。 帰ってから実行してみればいいのですが、移動の時間を使って質問しておくことで帰ってからの時間を有意義に使うこともできるため、そういった質問の仕方もしていたりするところがあります。 >>エラーになる原因はなぜか?と問われたら、回答者は答えを書くことができます。 質問の仕方が悪いときもありますが、実行できるときは実行しますが上記の事情も察知していただきたいです。すいません。
earnest_gay

2016/06/24 10:33

こちらへの返信で申し訳ないのですがmasaya_ohashiさんへです。 下記の記述でGoodとのことですが $page = filter_input(INPUT_GET, 'page'); $stmt = $pdo->prepare("SELECT pref,city FROM user_data ORDER BY id DESC LIMIT :while, 5"); $stmt->bindValue(':while', $_GET['page'] * 5, PDO::PARAM_INT); $stmt->execute(); --------------------------------------------------------------------------------------- $page = filter_input(INPUT_GET, 'page'); $stmt = $pdo->prepare("SELECT pref,city FROM user_data ORDER BY id DESC LIMIT :while, 5"); $stmt->bindValue(':while', $_GET['page'] * 5, PDO::PARAM_INT); $stmt->execute(); var_dump($stmt); $page = filter_input(INPUT_GET, 'page'); $start = (int) $page * 5; $sql = sprintf("SELECT pref,city FROM user_data WHERE 1 ORDER BY id DESC LIMIT %d, 5", $start); $stmt = $pdo->prepare($sql); $stmt->execute(); var_dump($stmt); 結果 object(PDOStatement)#2 (1) { ["queryString"]=> string(64) "SELECT pref,city FROM user_data ORDER BY id DESC LIMIT :while, 5" } object(PDOStatement)#3 (1) { ["queryString"]=> string(68) "SELECT pref,city FROM user_data WHERE 1 ORDER BY id DESC LIMIT 10, 5" } となってしまっています。 エラーはなく読み込めていますが、 $_GET['page'] * 5が渡されていない理由についてお聞きしたくて、再確認の意味も含めて返信しています。
退会済みユーザー

退会済みユーザー

2016/06/24 10:37

↑object(PDOStatement)#2 (1) { ["queryString"]=> string(64) "SELECT pref,city FROM user_data ORDER BY id DESC LIMIT :while, 5" } 仕様上、そのように出力されるだけで、バインドされて出力されるわけではありません。
yambejp

2016/06/24 11:50

$page = filter_input(INPUT_GET, 'page'); してるんだから $stmt->bindValue(':while', $_GET['page'] * 5, PDO::PARAM_INT); じゃなくて $stmt->bindValue(':while', $page * 5, PDO::PARAM_INT); じゃない?
guest

0

PDOのqueryでは、受け取ったSQL文をそのまま実行します。

プレースホルダを使う場合は、prepareしてからexecute、という流れです。

投稿2016/06/24 08:43

maisumakun

総合スコア145121

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

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

earnest_gay

2016/06/24 08:48

回答ありがとうございます。 こういうことだと思うんですが、変わらずです... $page = $_GET["page"]; $stmt = $pdo->prepare("SELECT pref,city FROM user_data ORDER BY id DESC LIMIT ?, 5"); $stmt->execute([$page * 5]);
guest

0

PDOに渡すクエリに;は不要でしたね。別質問で適当なクエリ書いて申し訳ないです。

投稿2016/06/24 08:44

masaya_ohashi

総合スコア9206

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

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

earnest_gay

2016/06/24 08:53

いえ、自分の吸収不足なところがありますので...
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問