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

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

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

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

Q&A

解決済

5回答

1485閲覧

よくわかるPHPの教科書のクオーテーションについての疑問

退会済みユーザー

退会済みユーザー

総合スコア0

PHP

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

0グッド

1クリップ

投稿2020/02/15 12:35

編集2020/02/15 12:38

よくわかるPHPの教科書でPHPを学習中です
メモアプリを作る過程で、input.phpで入力されたmemoの値をPOSTで呼び出し、それをデータベースにINSERTするという部分がわかりません。(コードでいうと上から3行目です)INSERTなどの文法はわかるのですが、クオーテーションが謎です。
なぜダブルクオーテーションで囲まれているところにシングルクオーテーションがさらにあるのかということがわかりません。
ダブルクオーテーションはなぜ必要なのでしょうか?
解説お願いいたします。

php

1 2 $db = new PDO("mysql:host=localhost;dbname=mydb","****","****"); 3 $memo=$_POST["memo"]; 4 $db->exec('INSERT INTO memos SET memo="'.$_POST['memo'].'",created_at=now()'); 5}catch(PDOException $e){ 6 echo "DB接続エラー" ;}

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

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

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

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

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

guest

回答5

0

根本的に、こんなコードは書いてはいけません。載せている教科書がよくない(脆弱性の教材にするなら別だけど)というレベルの話です。

データベースに与える値は、

  • 可能な限り、プリペアドステートメントを活用する(PDOだとprepareがあります)
  • 列名や文法要素になる場合は、ホワイトリストでチェックを行う
  • どうしようもないときは、手動でエスケープする

教科書だからこそ、こんな「エスケープすらせずに、$_POSTをそのまま混ぜ込む」ような、SQLインジェクション待ったなしのコードは排除してもらいたいものです。

投稿2020/02/15 13:39

maisumakun

総合スコア145184

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

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

guest

0

根本的な話、PHPの教科書はPHPマニュアルのみです。
書籍での学習が悪いとは言いませんが、あくまで「参考書」です。
書いている内容が正しいか、機能の確認は必ずPHPマニュアルで行ってください。

セキュリティについても結構なページ数を割いて整備されています。
現在質問者さんが直面されているクォーテーションの問題も文字列の項に詳細書かれています。

またネットの記事を参考にする場合は、Qiitaなどから評価の高い記事を選んだ方が良いでしょう。
データベース関係でよく参照されるのは下記。
PHPでデータベースに接続するときのまとめ

あと、これはSQLの話ですが、INSERT文の基本は下記です。
INSERT INTO テーブル名 VALUES(値1, 値2, ...);

INSERTでSETというと記憶の限りではMySQLしか出てこなかったと思いますし、検索してもおそらくMySQLしかでてきません。
もし今後業務で使うことを目指しているなら多くのDBがサポートしているスタンダードな形式を覚えた方が良いです。
場所やプロジェクトによるかもしれませんが、少なくとも私はMySQLを業務で使ってる場面にほとんど出会ってません。
(PostgreSQLが一番多く、次にOracleでした。)

投稿2020/02/15 22:32

m.ts10806

総合スコア80850

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

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

m.ts10806

2020/02/15 22:39 編集

よくわかるPHPの教科書 はPHP7対応版ですら2年近く前のものなので 積極活用すべきではないですね。 それに「もともと出ていた書籍がPHP7対応したもの」ってちょっと注釈加えただけの作りが古いもののほうが多いです。
faaa

2020/02/16 04:23

> PHP7対応版ですら2年近く前のものなので積極活用すべきではないですね。 なぜですか?
kyoya0819

2020/02/16 05:22 編集

読み間違いにより削除。
m.ts10806

2020/02/16 06:19 編集

faaaさん 2年前ということは執筆時点は3年以上前の仕様を元にして書かれていると思われます。それだけで「選択すべきではない理由」としては十分です。古すぎます。 あとは2行目も併せて読んでください。 それに・・・質問に提示のコードを何の解説もなく採用されているのであれば避けるべきなのは明白です。
faaa

2020/02/17 13:30

「よくわかるPHPの教科書」みたいなタイトルの本を恐らくは最初のテキストとして選ぶような状況の方であれば、15年くらい前の本でも十分じゃないでしょうか。って本気で思います。 いずれにしろ、続けるなら後何冊かは買うんでしょうし、今作っているものをすぐにネットで公開するというわけではないのですから。
kyoya0819

2020/02/17 13:37 編集

to ‘faaa’ ネットで公開する云々以前にそのような古い情報を記憶することになんのメリットがあるでしょうか? 「HTML4.01でも公開しないなら問題ないでしょ」 これと同じことを言ってます。
faaa

2020/02/17 14:23

はい。CSSなんて無かった頃のHTMLから学んでも良いと思います。
m.ts10806

2020/02/18 06:21

「この書き方が今でも通じる」という勘違いをしてしまうのはリスクでしかないので、書籍は新しいに越したことはないです。 就職の応募書類にソースコードがある場合はまず通らないでしょうね(自分なら通さない。ちゃんと理由はつけて返すけど) というか、PHPならPHPマニュアルを確認すべきというのが回答の前提です。 HTMLもJavaScriptもきちんと日本語化されたリファレンスもあり、サンプルコードもある。
kyoya0819

2020/02/18 13:43

関係ないのですが、 > PostgreSQLが一番多く、次にOracleでした。 というのは、 指示を受けた等の理由でしょうか? 効率や速度・機能の差などを考慮した上での選定でしょうか? お答えできる範囲で後学のためにお聞かせいただけると幸いです。
m.ts10806

2020/02/18 13:48

>指示を受けた等の理由でしょうか? んー、基本的に会社がそれ使うって前提でプロジェクトを組んでるのもあると思います。 回答に書いてるようにあくまで「場所やプロジェクトによるかもしれません」です。 たまたま私が関わったところや地域がその傾向にあるだけかもしれないですね。 より多くのデータを扱うのはPostgreSQLのほうが向いているというのは聴いたことがあります。
kyoya0819

2020/02/18 14:16

なるほど、そういうことですか、ありがとうございます。
faaa

2020/02/19 00:52

横から。 OracleかSQLServerかは、Windowsか否かと趣味・経験の問題、 商用かオープンソースかは趣味・経験・予算の問題 MySQLかPostgreSQLかは、趣味・経験の問題。 適切な設計であれば、一般的なWEBシステムの範囲で機能差や速度差は無いに等しいと思います(数年ほど前から)。 何か譲れない機能があるなら、それで選ぶのでしょう。 ストアドプロシージャを使いたいならMySQLはイケてない。 ただ、Webベンチャーは予算の都合もあり、オープンソースが基本でしょうね。 データ量で言えば追記型か更新型かというアーキテクチャーの話もあるけど、そこまで気にする人も少ないかな。 MySQLばっかり使ってて久々にOracleな環境に戻りましたが、世界観が違いすぎて、死ぬほどイライラします。 開発者が一番ノウハウを持っているDBMSを使うのが一番いいと思います。
m.ts10806

2020/02/19 02:26

そうですね。 自身が選定に参加するならPostgreSQL選ぶかな…。くらいの感じではあります。規模にもよりますね。
kyoya0819

2020/02/19 02:29

全てMySQL(予算等の理由)で作ってきて、PostgreSQLやOracleなどは全く触れてこなかったので、学習することにします。
m.ts10806

2020/02/19 02:34 編集

PostgreSQLは使用感あまり変わりませんが、Oracleはかなり違ってくる印象はあります。 資格もありますしね。個人学習では無償なので自宅PCにスペック的な余裕があれば試してみてもいいかもしれません(私の自宅PCは全く余裕なくて買い換え時期過ぎてるくらいなので入れてませんけど…)
guest

0

もし、$_POST['memo']POYOという内容が含まれて送信したとされます。

もし、ダブルクォーテーションがない場合以下のような流れになります。
'INSERT INTO memos SET memo='.$_POST['memo'].',created_at=now()'
'INSERT INTO memos SET memo='.'POYO'.',created_at=now()'
'INSERT INTO memos SET memo=POYO,created_at=now()'
しかし、これは文法的に正しくありません。

ダブルクォーテーションで文字列は括らなければいけません。

このような回答でよろしいでしょうか?

投稿2020/02/15 12:40

編集2020/02/15 13:00
kyoya0819

総合スコア10429

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

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

退会済みユーザー

退会済みユーザー

2020/02/15 12:43

ご回答ありがとうございます。 疑問に思ったのですが、ダブルクオーテーションで括らなければいけないのなら$_POSTの周りをダブルクオーテーションで括るというのはNGなのでしょうか? なぜ一度シングルクオテーションで括っているのでしょうか?
kyoya0819

2020/02/15 12:46

??? もう少し別の例です。 例えば <div class="hoge">あいうえお</div> をPHPでechoしたいとします。 このときに、 echo '<div class="'.'hoge'.'">あいうえお</div>'; とかきますよね? それと同じ理由です。 あくまで、シングルクォーテーションが囲っているのはPOSTではなく、その前後にあるその他のINSERT文です。
退会済みユーザー

退会済みユーザー

2020/02/15 12:59 編集

PHPを始めたばかりなのですみません… シングルクオートで囲まれたコード $_POST シングルクオートで囲まれたコード のようになっているということであってますか? またダブルクオーテーションの位置を変えて 'INSERT INTO memos SET memo="'.$_POST['memo'].'",created_at=now()' のように記述するのはダメなのでしょうか? 重ね重ねの質問申し訳ございません。
kyoya0819

2020/02/15 13:00

何か質問文のコードと変わっているでしょうか?
退会済みユーザー

退会済みユーザー

2020/02/15 13:02

すみません 'INSERT INTO memos SET memo='".$_POST['memo']."',created_at=now()' でした。 シングルクオーテーションとダブルクオーテーションの位置を逆にしました。
kyoya0819

2020/02/15 13:04

逆にはなってないのでは? 'INSERT INTO memos SET memo='".$_POST['memo']."',created_at=now()' ではなく、以下の書き方なら良いはずです。 "INSERT INTO memos SET memo='".$_POST['memo']."',created_at=now()"
退会済みユーザー

退会済みユーザー

2020/02/15 13:07

$_POST周辺のクオーテーションを逆にするだけではNGなのでしょうか?
kyoya0819

2020/02/15 14:44

うーん。 私が上に書いたようなコードでご理解いただけないとなると、SQL文云々以前の問題です。 文字列結合について再度学習されることをお勧めします。
kyoya0819

2020/02/16 07:08 編集

特段の解説がない限り、この本は買うべきではないですね。 いろいろ足りてない、、
guest

0

実際に何をやっているか動かしてみると良いです。

php

1<?php 2$_POST['memo'] = 'hogehoge'; 3$str = 'INSERT INTO memos SET memo="'.$_POST['memo'].'",created_at=now()'; 4echo $str;

解説はマニュアルに任せますw
文字列 - php.net

まぁ、すでに別の回答にあるように、DB 利用時の文字連結は、基本的に NG なので、根本から見直す必要があります。

余談
DB の接続に関しては、テンプレートを作成しているので参照してみてください。
PHP で MySQL 接続時に必要な知識(最小限版)

投稿2020/02/16 07:08

退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

ベストアンサー

なぜダブルクオーテーションで囲まれているところにシングルクオーテーションがさらにあるのかということがわかりません。
ダブルクオーテーションはなぜ必要なのでしょうか?

以下の例でダブルクオーテーションはSQL文における文字列を表現したもので、シングルクオーテーションはPHPにおける文字列を表現しています。2重になっているということです。

PHP

1$db->exec('INSERT INTO memos SET memo="'.$_POST['memo'].'",created_at=now()');

ですが、ちょっと変なところがあって、
一般に、SQLでは文字列をシングルクォーテーションで括ります。
例のようにダブルクォーテーションで括るのは標準的ではありません。
memoの値が「XXX」だとすると、SQLは以下になります。

SQL

1INSERT INTO memos SET memo = 'XXX', created_at = now()

ちなみにSQLには多くの方言やバリエーションがあり、以下が標準的です。

SQL

1INSERT INTO memos (memo, created_at) VALUES('XXX', now())

※この後の例ではSQLのシングルクォーテーションとダブルクォーテーションを正さずに書いています。

また「$memo=$_POST["memo"];」で「$memo」に値を移しているのであれば、

PHP

1$db->exec('INSERT INTO memos SET memo="'.$_POST['memo'].'",created_at=now()');

でなく、以下になるはずです。

PHP

1$db->exec('INSERT INTO memos SET memo="'.$memo.'",created_at=now()');

PHPも文字列をクォーテーションで括ります。
ただ、シングルクォーテーションとダブルクォーテーションで効果が違います。
また、シングルクォーテーションの中にダブルクォーテーションがある場合や、その逆などの状況では、どちらを使うか工夫する必要があります。

※参考
https://www.php.net/manual/ja/language.types.string.php#language.types.string.syntax.double

これらを踏まえると、以下のようになります。
※この後の例ではSQLのシングルクォーテーションとダブルクォーテーションを正して書いています。

PHP

1$db->exec("INSERT INTO memos SET memo='" . $_POST['memo'] . "',created_at=now()");

「$_POST['memo']」のままだとできないのですが、
「$memo」に移したのであれば、「.」で文字列を結合せずに、以下のようにも書けます({}は、この場合は無くても良いです)。

PHP

1$db->exec("INSERT INTO memos SET memo='{$memo}',created_at=now()");

こんな風にするともっと分かりやすいかも。

PHP

1$sql = "INSERT INTO memos SET memo='%s',created_at=%s"; 2$db->exec(sprintf($sql, $memo, 'now()')); 3 4sprintf()の書き漏れを訂正[2/16 14:405前:$db->exec($sql, $memo, 'now()'); 6後:$db->exec(sprintf($sql, $memo, 'now()'));

※参考
https://www.php.net/manual/ja/function.sprintf.php

また他の方も指摘するように、プリペアドステートメントという方法でSQLの変数以外を作っておいて変数を設定してSQLを完成させる方法がセキュリティ的に望ましいので、最終的にはそういう方法でSQLを実行するのが良いですが、まぁ、後でやればいいことです(今はもっと基本的なことを学ぶべきです)。

※参考
https://www.php.net/manual/ja/pdo.prepared-statements.php
https://www.php.net/manual/ja/pdo.prepare.php

投稿2020/02/16 04:02

編集2020/02/17 14:27
faaa

総合スコア31

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

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

kyoya0819

2020/02/16 05:23

リンクはすべてMarkDown文法に則てください。
kyoya0819

2020/02/16 07:06

他人の回答にはコメントして、自身の回答のコメントに関しては無視ですか
faaa

2020/02/17 13:21

失礼いたしました。どうしてですか?
kyoya0819

2020/02/17 13:28

「どうして」というのは私のコメントのどれに対してですか?
faaa

2020/02/17 13:31

なぜリンクをMarkDownで書けと言うのか。
kyoya0819

2020/02/17 13:35

現状のままではページ移管が非常に手間がかかる。 加えてこのサイトではMD文法に対応しているからそちらを使うべきである。
faaa

2020/02/17 13:48

確かに。いや、PCで書いてる時は何でもない手間と思いましたが、スマホだと手間ですね。。改めます。
faaa

2020/02/17 14:44

しかし、terateilもレベルが低い。 回答数が多い人は質問者が躓いていることや聞きたいことには答えず、ただ言いたいことを言っているだけ。 質問者のレベルを考えない理想的な正解を振りかざすのは、さぞ簡単で気持ちが良いことでしょう。 teratail運営側は、もう少しコミュニティの醸成に気を使ったらいいんじゃないかな。
kyoya0819

2020/02/17 14:48

ここで回答されている皆様は「正しいこと」を言ってるだけです。 今の財産となるのか、将来の財産となるのか、どちらが良いのかは自明でしょう。
kyoya0819

2020/02/17 14:49

コードだけ答えてなんになるのか、答えだけを教えてどうなるのか等を加味すると的確な回答だと私は思います。
faaa

2020/02/17 15:45

遠く離れた正解を言いっ放しなのは、質問者を混乱させるだけでなく、見ていて不快です。 ここで質問している人は、今、困っているのであって、遠く離れた道標でなく、今ここからの道標であるべきです。 でも私は貴方のことを言ったわけではありません。 失礼な言い方ですみませんが、あなたは説明が下手なだけで、ちゃんと回答しようとしていたと思います。 基本的には、teratail全般の話です。
maisumakun

2020/02/18 06:14

> 質問者のレベルを考えない理想的な正解を振りかざすのは、さぞ簡単で気持ちが良いことでしょう。 自分自身は、質問者のレベルを考えた上で、あえて回答しています。 変な知識が最初に身につくと、知識がない状態より厄介な事になりかねないので、入門書こそ安全なやり方を叩き込むべきと考えます。 > 今ここからの道標であるべきです。 自分としては「こんな危険地帯を立ち去る」のが最善の行程と考えたまでです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問