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

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

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

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

Q&A

解決済

4回答

3138閲覧

LIMIT句でのsprintf関数について

earnest_gay

総合スコア615

PHP

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

0グッド

0クリップ

投稿2016/06/24 10:43

LIMIT句についてです。

php

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

【結果】
object(PDOStatement)#3 (1) { ["queryString"]=> string(68) "SELECT pref,city FROM user_data WHERE 1 ORDER BY id DESC LIMIT 10, 5" }

正常に動いてるのでいいのですが

LIMIT 取り出す位置,取り出す件数
の順で記述していくのに

LIMIT %d, 5", $start
ではなく
**LIMIT %d,$start, 5" **
にすると
LIMIT 取り出す位置,取り出す件数
のはずなのにエラーになってしまいます。

その原因と
LIMIT 取り出す位置,取り出す件数
の順で記述するはずなのに
LIMIT %d, 5", $start
で記述して結果が
DESC LIMIT 10, 5
になっている理由について教えてください。

LIMIT %d, 5", $start
なら
DESC LIMIT 5,10
になるはずだと思うのです。

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

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

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

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

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

guest

回答4

0

区切る位置がおかしいですね…

php

1sprintf("... LIMIT %d, 5", $start)

これは%dの位置に整数キャストして$startを当てはめる使い方をしています.sprintfのマニュアルを読めば

php

1sprintf("... LIMIT %d,$start, 5")

これがおかしいことぐらいすぐに気づくと思うんですが…
(%dが使われていないのでエラーになります)

なお,プレースホルダを使うかsprintfを使うかの選択ですが,これは状況次第というところでしょう.PDOはどうしても生のままだと整数の取り扱いが苦手なので,部分的にsprintfの力を借りるのはよくあることです.ただ,これがコーディング作法として良いかと言われると微妙なところです.

もしプレースホルダで書くなら

php

1$page = max(0, (int)filter_input(INPUT_GET, 'page')); 2$start = $page * 5; 3$sql = "SELECT pref,city FROM user_data WHERE 1 ORDER BY id DESC LIMIT ?,5"; 4$stmt = $pdo->prepare($sql); 5$stmt->bindValue(1, $start, PDO::PARAM_INT); 6$stmt->execute();

となります.(念のため負の数は0になおしています)

投稿2016/06/24 10:55

編集2016/06/24 11:00
mpyw

総合スコア5223

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

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

退会済みユーザー

退会済みユーザー

2016/06/24 11:11

$page = max(0, (int)filter_input(INPUT_GET, 'page')); max() を使うのは、新たな気づきです!人のソース読むのは楽しいですね!
earnest_gay

2016/06/24 11:14

回答ありがとうございます。 max()で負の数にならないようにしてますが、$_POST['page']が負の数になることはあるんでしょうか? -------------------------------------------------------------------------- $page = max(0, (int)filter_input(INPUT_GET, 'page')); $start = $page * 5; $sql = "SELECT pref,city FROM user_data WHERE 1 ORDER BY id DESC LIMIT ?,5"; $stmt = $pdo->prepare($sql); $stmt->bindValue(1, $start, PDO::PARAM_INT); $stmt->execute(); この結果 object(PDOStatement)#2 (1) { ["queryString"]=> string(66) "SELECT pref,city FROM user_data WHERE 1 ORDER BY id DESC LIMIT ?,5" } になっており、うまくバインドできていないように伺えるのですが...
mpyw

2016/06/24 12:27

>> $_POST['page']が負の数になることはあるんでしょうか? 普通にWebブラウザでアクセスしてくる限りはないですが,任意のプログラムからHTTPリクエストを飛ばせることを考慮すると「やろうと思えばできる」といえます.LIMIT/OFFSETが負の値でもエラーにならなければ問題ないのですが,なったような記憶があったので,絶対に何があってもエラーが発生しないように書いている…というところです. >> うまくバインドできていないように伺えるのですが... queryStringプロパティからはバインドした結果は見えません.
earnest_gay

2016/06/24 13:39

1つ目については分かりました! 2つ目ですが、queryStringプロパティとは何で、なぜバインドした結果は見えないのでしょうか?
mpyw

2016/06/24 23:04

queryStringプロパティはprepareの第1引数がそのまま格納されたものです.バインドしか結果は内部的に保持されていて,外からは見えないのです. (PDOクラスおよびPDOStatementクラスの実装はC言語で書かれており,そこで保持している状態変数全てがPHP側に晒されているわけではありません)
guest

0

こんにちは

sprintfの使い方として形式は

php

1string sprintf ( string $format [, mixed $args [, mixed $... ]] ) 2string $format = "SELECT pref,city FROM user_data WHERE 1 ORDER BY id DESC LIMIT %d, 5" 3$args = $start

に相当します。

php

1"SELECT pref,city FROM user_data WHERE 1 ORDER BY id DESC LIMIT 5, 10"

と表示したいなら

php

1sprintf ( "SELECT pref,city FROM user_data WHERE 1 ORDER BY id DESC LIMIT 5,%d",$start);

になるかと思います。

http://www.phpbook.jp/func/string/index7.html

投稿2016/06/24 10:55

kogure

総合スコア299

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

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

earnest_gay

2016/06/24 11:08

詳しくありがとうございます!
guest

0

ベストアンサー

以下のふたつが同じことであることは、ご理解できますか?

<?php $start = 10; $recordCount = 5; $sql = sprintf("SELECT pref,city FROM user_data WHERE 1 ORDER BY id DESC LIMIT %d, %d", $start, $recordCount); var_dump($sql);

php

1<?php 2$start = 10; 3$sql = sprintf("SELECT pref,city FROM user_data WHERE 1 ORDER BY id DESC LIMIT %d, 5", $start); 4 5var_dump($sql);

投稿2016/06/24 10:50

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

earnest_gay

2016/06/24 11:08

今理解できました! ありがとうございます。
guest

0

sprintfではなくプリペアドステートメントを使用されたほうが良いです。


質問文を見る限りsprintfの使い方を勘違いされています。
PHP: sprintf - Manual
マニュアルときちんと読んでsprintfの動作を理解されることをおすすめします。

投稿2016/06/24 10:46

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

退会済みユーザー

総合スコア0

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

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

earnest_gay

2016/06/24 11:05

回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問