PHP Mysql について

初歩的な質問で申し訳ないのですが、
クエリーを発酵する際に、
$sql = "SELECT * FROM users WHERE userid = '". $_POST['userid']. "'";
のように書けば動くということがわかりました。

しかし、『'". $_POST['userid']. "'』の部分の
『"』やら、そのあとの半角スペースや、『.』が必要な理由というか、
なんの作用をもたらしているのかがわかりません。
『'$_POST['userid']'』だったらうまく動作しなかったので、手当たり次第
検索して、見つけたソースをそのまま使用したら上手く動いただけです。

これについて、解説したページ等ありますでしょうか?

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2012/06/09 10:58:59

ベストアンサー

id:windofjuly No.3

回答回数2625ベストアンサー獲得回数1149

ダブルクォートで囲まれた中にあるシングルクォートは文字として取り扱われるため、
userid という文字列ではなく 'userid' という文字列だと誤認してしまうというのが原因です。

そのため質問文にあるように、複数のパーツに分けて求めたものを結合するという手間をかけています。
その他にも方法はありますが、現在では質問文にあるような書き方が主流です。

(a)質問文のように分離する方法
$sql = "SELECT * FROM users WHERE userid = '" . $_POST['userid'] . "'";
変数は変数だけで独立して扱うので、
エディタ上での検索や置換などの編集作業が容易になります。
文字列の結合演算子である . を(人間が)見逃してエラーになるなんてことにもなるので、
. の前後に半角スペースをいれるなどの工夫もしています。

(b)中括弧を使って変数名であることを明示する方法
$sql = "SELECT * FROM users WHERE userid = '${_POST['userid']}'";
1つの変数をあらわす方法が複数(${_POST['userid']}と$_POST['userid'])になり、
再度コードを読み直したり、書き直したりする際にミスをしやすくなるため、
最近ではこの方法を使っている人をあまり見なくなってきました。

(c)シングルクォートを使わない方法(非推奨)
$sql = "SELECT * FROM users WHERE userid = '$_POST[userid]'";
下記ページの「配列ですべきこととしてはならないこと」に詳しいので下記参照
http://php.net/manual/ja/language.types.array.php

他3件のコメントを見る
id:windofjuly

mysqliでprepareを使った例

単体テスト用のhtmlフォーム付きにしておいたので、
"host", "user", "pass", "db"の設定と入力チェック部分を、
そちらの環境に合わせるだけで動くはずです
(テストですから入力チェックの部分をコメントアウトしてもかまいません)
(今回の回答用に新規作成し、動作テストしたものを貼り付けてます)

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
    <meta http-equiv="content-style-type" content="text/css">
    <title>test</title>
</head>
<body>
    <form action="<?=$_SERVER['PHP_SELF'] ?>" method="post">
            <input type="text" name="userid" size="30"><br />
            <input type="submit" value="送信" />
    </form>
<?php
// 入力値の存在チェック
if (!isset($_POST['userid'])) die('useridが送られてきていません。');
// 入力値の適正チェック(アルファベットで始まる2-6桁の文字列のみ受付とする)
if (!preg_match('!^[a-zA-Z][a-zA-Z0-9]{1,5}$!', $_POST['userid'])) die('useridが不適切です。');
// 入力値の受け入れ
$userid = $_POST['userid'];

//
// mysqlドライバ利用に近い形(手続き型)での記述例
//
// SQL準備
// *も使えるけれど、下記のようにカラムを指定しておけば、
// データベース側の構造が変わってもプログラム改変は不要となり、
// プログラミング中の記述ミスなども発見しやすくなるため、
// プログラム中にSQLを書く場合にはカラム指定必須と覚えておきましょう
$sql = "SELECT userid, username FROM users WHERE userid = ?";
// コネクト
$mysqli = mysqli_connect('host', 'user', 'pass', 'db');
// SQL送信
$stmt = mysqli_prepare($mysqli, $sql) or die('プリペア送信に失敗しました。SQL:' . $sql);
// パラメータの送信
mysqli_stmt_bind_param($stmt, 's', $userid) or die('パラメータ送信に失敗しました');
// SQL実行
mysqli_stmt_execute($stmt) or die('クエリ実行に失敗しました');
// SQL実行結果を受け取る変数を用意
// SQL中で出力指定されたカラムの並びに準拠します
mysqli_stmt_bind_result($stmt, $re_userid, $re_name) or die('変数接続に失敗しました');
// 結果取得と出力
while (mysqli_stmt_fetch($stmt)) {
    echo $re_userid, $re_name , '<br />';
}
// クローズ
mysqli_stmt_close($stmt);

//
// オブジェクト指向型での記述例
//
// SQL準備
$sql = "SELECT userid, username FROM users WHERE userid = ?";
// コネクト
$mysqli = new mysqli('host', 'user', 'pass', 'db');
// SQL送信
$stmt = $mysqli->prepare($sql) or die('プリペア送信に失敗しました。SQL:' . $sql);
// パラメータの送信
$stmt->bind_param('s', $userid) or die('パラメータ送信に失敗しました');
// SQL実行
$stmt->execute() or die('クエリ実行に失敗しました');
// SQL実行結果を受け取る変数を用意
$stmt->bind_result($re_userid, $re_name) or die('変数接続に失敗しました');
// 結果取得と出力
while ($stmt->fetch()) {
    echo $re_userid, $re_name , '<br />';
}
// クローズ
$mysqli->close();
2012/06/09 01:42:02
id:gwrite

ご丁寧にありがとうございます。さらには、送信したポイントを返却までしていただいて、ご親切にありがとうございました。

まだまだ、人力検索のお世話になること多いと思いますので、その際は、またよろしくお願いできましたらと思います。

2012/06/09 10:58:47

その他の回答2件)

id:taknt No.1

回答回数13539ベストアンサー獲得回数1198

『"』
文字列の指定に必要です。


『.』
文字列の連結をします。

半角スペースは 特には 関係ないと思います。

SQLを指定していますが、その文字列を変数を交えて 記述しているということです。


ただ、このような書き方だと セキュリティ上問題が発生する恐れがあります。
それについては ↓を参照してください。

http://ja.wikipedia.org/wiki/SQL%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3

id:taknt

なお
"と'の違いですが
"は PHP上での文字列の指定
'は SQL上での文字列の指定となります。

2012/06/08 12:26:33
id:gwrite

連結演算子ですか。そういえばあったような気がします。
ありがとうございました。

2012/06/08 22:09:57
id:gyoh_k No.2

回答回数12ベストアンサー獲得回数6

.(ドット) は、PHPで文字列を足す演算子です。

$param = "abc" . "def";
この場合、$paramは"abcdef" になります。


仮に、$_POST['userid'] が変数でなく、ユーザーID "abcd"を検索する場合、
SQLは以下のようになります。

$sql = "SELECT * FROM users WHERE userid = 'abcd'";

$sql = "SELECT * FROM users WHERE userid = '" . "abcd" . "'";

$sql = "SELECT * FROM users WHERE userid = '". $_POST['userid']. "'";

なお、実務のプログラミングでこの書き方をすると、
あっという間に読みづらいプログラムになってしまうため、
プレースホルダという機能を使ったほうがよいです。

他3件のコメントを見る
id:gwrite

プレースホルダ使うようにします。
 が、レンタルサーバでPEARが動かないという壁にもぶち当たっています。
また、『'" . "abcd" . "'』の時点で、よくわからなくなりました。
両端のシングルクォートはわかるのですが、ダブルクォーテーションが何をどう囲っているのか理解できません。

2012/06/08 22:13:13
id:gyoh_k

一般的にプログラミング言語では、文字列をダブルクォーテーション(またはシングルクォーテーション)で囲みます。
たとえば、以下の構文はエラーになります。
$param = あいうえお;
また、以下のように、ダブルクォーテーションとシングルクォーテーションを併用させることもできません。
$param = "あいうえお';
以下の書き方だとOKです。
$param = "あいうえお";

文字列でなく、数値の場合はクォーテーションで囲む必要はありません。
$param = 123;

なお、「123」のような数値としても文字列としても扱えるデータの場合、
ダブルクォートで囲うこともできます。
$param = "123";

どちらにするかは、プログラム内で数値として扱いたいか、
文字列として扱いたいかによって決めるとよいと思います。

レンタルサーバでPEARが動かない件については、
初学者の方だと結構大変かも、ですね。
サーバの種類によっても設定内容が違ったりするので、
有効な解決策をお答えすることはできませんが、
数日かけるつもりでトライしていただければと思います。

2012/06/09 08:32:12
id:windofjuly No.3

回答回数2625ベストアンサー獲得回数1149ここでベストアンサー

ダブルクォートで囲まれた中にあるシングルクォートは文字として取り扱われるため、
userid という文字列ではなく 'userid' という文字列だと誤認してしまうというのが原因です。

そのため質問文にあるように、複数のパーツに分けて求めたものを結合するという手間をかけています。
その他にも方法はありますが、現在では質問文にあるような書き方が主流です。

(a)質問文のように分離する方法
$sql = "SELECT * FROM users WHERE userid = '" . $_POST['userid'] . "'";
変数は変数だけで独立して扱うので、
エディタ上での検索や置換などの編集作業が容易になります。
文字列の結合演算子である . を(人間が)見逃してエラーになるなんてことにもなるので、
. の前後に半角スペースをいれるなどの工夫もしています。

(b)中括弧を使って変数名であることを明示する方法
$sql = "SELECT * FROM users WHERE userid = '${_POST['userid']}'";
1つの変数をあらわす方法が複数(${_POST['userid']}と$_POST['userid'])になり、
再度コードを読み直したり、書き直したりする際にミスをしやすくなるため、
最近ではこの方法を使っている人をあまり見なくなってきました。

(c)シングルクォートを使わない方法(非推奨)
$sql = "SELECT * FROM users WHERE userid = '$_POST[userid]'";
下記ページの「配列ですべきこととしてはならないこと」に詳しいので下記参照
http://php.net/manual/ja/language.types.array.php

他3件のコメントを見る
id:windofjuly

mysqliでprepareを使った例

単体テスト用のhtmlフォーム付きにしておいたので、
"host", "user", "pass", "db"の設定と入力チェック部分を、
そちらの環境に合わせるだけで動くはずです
(テストですから入力チェックの部分をコメントアウトしてもかまいません)
(今回の回答用に新規作成し、動作テストしたものを貼り付けてます)

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
    <meta http-equiv="content-style-type" content="text/css">
    <title>test</title>
</head>
<body>
    <form action="<?=$_SERVER['PHP_SELF'] ?>" method="post">
            <input type="text" name="userid" size="30"><br />
            <input type="submit" value="送信" />
    </form>
<?php
// 入力値の存在チェック
if (!isset($_POST['userid'])) die('useridが送られてきていません。');
// 入力値の適正チェック(アルファベットで始まる2-6桁の文字列のみ受付とする)
if (!preg_match('!^[a-zA-Z][a-zA-Z0-9]{1,5}$!', $_POST['userid'])) die('useridが不適切です。');
// 入力値の受け入れ
$userid = $_POST['userid'];

//
// mysqlドライバ利用に近い形(手続き型)での記述例
//
// SQL準備
// *も使えるけれど、下記のようにカラムを指定しておけば、
// データベース側の構造が変わってもプログラム改変は不要となり、
// プログラミング中の記述ミスなども発見しやすくなるため、
// プログラム中にSQLを書く場合にはカラム指定必須と覚えておきましょう
$sql = "SELECT userid, username FROM users WHERE userid = ?";
// コネクト
$mysqli = mysqli_connect('host', 'user', 'pass', 'db');
// SQL送信
$stmt = mysqli_prepare($mysqli, $sql) or die('プリペア送信に失敗しました。SQL:' . $sql);
// パラメータの送信
mysqli_stmt_bind_param($stmt, 's', $userid) or die('パラメータ送信に失敗しました');
// SQL実行
mysqli_stmt_execute($stmt) or die('クエリ実行に失敗しました');
// SQL実行結果を受け取る変数を用意
// SQL中で出力指定されたカラムの並びに準拠します
mysqli_stmt_bind_result($stmt, $re_userid, $re_name) or die('変数接続に失敗しました');
// 結果取得と出力
while (mysqli_stmt_fetch($stmt)) {
    echo $re_userid, $re_name , '<br />';
}
// クローズ
mysqli_stmt_close($stmt);

//
// オブジェクト指向型での記述例
//
// SQL準備
$sql = "SELECT userid, username FROM users WHERE userid = ?";
// コネクト
$mysqli = new mysqli('host', 'user', 'pass', 'db');
// SQL送信
$stmt = $mysqli->prepare($sql) or die('プリペア送信に失敗しました。SQL:' . $sql);
// パラメータの送信
$stmt->bind_param('s', $userid) or die('パラメータ送信に失敗しました');
// SQL実行
$stmt->execute() or die('クエリ実行に失敗しました');
// SQL実行結果を受け取る変数を用意
$stmt->bind_result($re_userid, $re_name) or die('変数接続に失敗しました');
// 結果取得と出力
while ($stmt->fetch()) {
    echo $re_userid, $re_name , '<br />';
}
// クローズ
$mysqli->close();
2012/06/09 01:42:02
id:gwrite

ご丁寧にありがとうございます。さらには、送信したポイントを返却までしていただいて、ご親切にありがとうございました。

まだまだ、人力検索のお世話になること多いと思いますので、その際は、またよろしくお願いできましたらと思います。

2012/06/09 10:58:47
  • id:taknt
    >ダブルクォートで囲まれた中にあるシングルクォートは文字として取り扱われるため、
    userid という文字列ではなく 'userid' という文字列だと誤認してしまうというのが原因です。

    何の原因?

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません