Skip to content

憂鬱なSQLのためのアレ

公開日:

東京都港区六本木株式会社メルカリ(六本木ヒルズ森タワー18F)で開催された『PHP BLT #4』でライトニングトーク(5分)として発表しました。

Download PDF

スライドテキスト

Page 1

憂鬱なSQLのためのアレ

PHP-BLT #4

Page 2

近況報告

  • PHPカンファレンス北海道で喋ってきました

「仕事で使えるComposer」http://niconare.nicovideo.jp/watch/kn1371

  • WEB+DB Press Vol. 92に

PHPからHTTPリクエストをする話を書きました

http://gihyo.jp/magazine/wdpress/archive/2016/vol92

Page 3

近況報告

  • AdventCalendarではPHPマニュアルの

バージョン番号をパースする話を書きました

http://qiita.com/tadsan/items/94e00f6fdf40d96c5072

  • スレッドフロート掲示板を作りたかった少年時

代の代償行為として、モダンPHP、ただしフレームワーク抜きで書き始めました

http://qiita.com/tadsan/items/cdbbb5b08591af2b110d

Page 4

みんな大好きPDO

  • PHP Data Objects
  • いろんなSQLを抽象化したオブジェクト
  • 学生がmysqli関数使ってたけどPDOでいい
  • あとなんか、Doctrineとか使った方がいいの?

Page 5

Real World PHP

  • 2015年にもなって徳丸先生がPHPカンファレン

スでSQLインジェクションの話をしてるリアル

  • O/Rマッパー使っとけwwwと煽ったところで、

世界にはまだ文字列結合SQLが眠ってる

Page 6

みんな事故る

  • 文字列結合の温床
  • 型を指定するのはめんどくさい
  • $stmt->bindValue(':id', $id, \PDO::PARAM_INT)
  • 可変個数のIN句が地雷

Page 7

Real World PHP

$names = ["taro","jiro","saburo"];$str = implode(",", array_map($name){return sprintf('"%s"', $name);});$sql = "SELECT * FROM users WHERE name IN ($str)";

// ↑典型的な漏れのあるロジックの例

Page 8

PDOのラッパー作った

  • 警告:ちゃんとしたO/Rマッパーの方がいい
  • (会社で同僚が作ったのを)コピペして再実装した
  • SQL内に型が書けるDSL
  • PDOに乗っかって、余計なことはしない
  • SQLインジェクションにある程度の耐性がある?

Page 9

composer require zonuexe/tetosql

https://github.com/BaguettePHP/TetoSQL

Page 10

<?php namespace InspireBBS\Model;use Teto\SQL;

/*** 板を表現するモデル* @copyright 2016 USAMI Kenta* @license WTFPL*/final class Board {/*** @return Board[]*/public static function findAll() {$data = SQL\Query::execute(db(), self::findAll_query, [])->fetchAll(\PDO::FETCH_ASSOC) ?: [];

$boards = [];foreach ($data as $b) {$boards[] = new Board($b);}

return $boards;}const findAll_query = 'SELECT `id`, `name`, `text` FROM `boards`';}

Page 11

use Teto\SQL;public static function find($id) {$data = SQL\Query::execute(db(), self::findAll_query, [':id' => $id,])->fetchAll(\PDO::FETCH_ASSOC) ?: [];

$boards = [];foreach ($data as $b) {$boards[] = new Board($b);}

return $boards;}const find_query = ‘SELECT `id`, `name`, `text` FROM `boards` WHERE `id` = $id@int';

Page 12

基本的なAPI

  • どうにかしてPDOのコネクションをとっておく
  • $stmt = SQL\Query::execute($con, self::find_query,

[':id' => $id, ':hoge' => $hoge] );

  • コネクション、SQL、アサインする値を渡す
  • 帰ってくる値はPDOStatementなので、

いつもの感覚でfetch/fetchAllするだけ!

Page 13

const

  • PHPのconstは(原則)実行時に変更されない
  • そこにパラメータを当て嵌めるだけ、なのは

なんとなく心理的な安心感がある (本当か?)

  • お気付きだろうか…
  • このコードがPSR-1違反であることに…