3行目は静的プレースホルダというものにするという指令です。MySQLの場合、プレースホルダの実装に静的プレースホルダ(Prepared Statement)と動的プレースホルダ(Prepared Statementのエミュレーション)を選択できます。PDO::ATTR_EMULATE_PREPARES を false にするというのは、エミュレーションを無効化するということで、つまるところ静的プレースホルダの指定になります。結論だけ言えば静的プレースホルダの方が安全ですが、詳細はIPAの安全なSQLの呼び出し方を参照くださいい。
安全なSQLの呼び出し方
重要な箇所を引用します。
引用テキストこのうち、静的プレースホルダは、SQL を準備する段階で SQL 文の構文が確定し、あとから SQL 構文が変化することがないため、SQL インジェクションの脆弱性が生じません。
それに対して、動的プレースホルダは、バインド処理を実現するライブラリの実装に問題があると、SQL 構文が変化する可能性があり、SQL インジェクションの脆弱性が生じる可能性を否定できません。
6行目のPDO::PARAM_STRは、プレースホルダの型を文字列型として指定するものです。列idが文字列型(VARCHARなど)であればこのままでいいですが、列が整数型の場合はPARAM_INTを指定します。テーブルの定義は示されていませんが、$id = 1 という代入からは整数型のようにも見えまして、もし整数型ならPDO::PARAM_INT が正しい指定ということになります。
setAttributeとPDO::PARAM_STRはなくてもセキュリティ上は問題ないのでしょうか?
setAttributeについてはIPAの安全なSQLの呼び出し方の引用部分に答えが書いてありますが、違いは微妙であり、「問題ありとは言えない」というくらいです。せっかく書いてあるので消す必要はありません。
PDO::PARAM_STRが問題になるケースはありますが、こちらはさらに難しい話になります。参考文献としては下記があります。
SQLの暗黙の型変換はワナがいっぱい
これが問題になるのは、下記の条件が揃っている場合です
- 桁数の大きな数値を扱っている
- 値を文字列型で指定している(例: $id = '12345678901234567890')
- PDO::PARAM_STR を指定している
現在のスクリプトは上の2つが該当しないので実害はないと思います。