サーバーサイドでフレームワークを使っている場合、ORマッパーでSQLを組み立てることがよくあると思う。が、時として
「ORマッパーで書くのは困難だが、ベタのSQLなら書きやすい」
ようなクエリを書きたいシーンにどうしても直面する。
僕はそういう時にヒアドキュメントを使ってSQLを書くことがあるのだが、PHP7.2以前までのヒアドキュメント(&ナウドキュメント)はインデントの扱いが結構曲者だった。それが、PHP7.3以降では劇的に改善されていて感動したので、今回紹介しようと思う。
PHP7.2までのヒアドキュメント内のインデントは全て反映されてしまっていた
たとえばこんな感じ:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
class Hoge extends Fuga { public function getExistingAuthorArticlesSQL() { $sql = <<<SQL SELECT Article.* ,Author.* FROM articles Article INNER JOIN authors Author ON Article.author_id = Author.id WHERE Author.deleted = 0 ; SQL; return $sql; } } ... $hoge = new Hoge(); $sql = $hoge->getExistingAuthorArticlesSQL(); print_r($sql); // result: SELECT Article.* ,Author.* FROM articles Article INNER JOIN authors Author ON Article.author_id = Author.id WHERE Author.deleted = 0 ; |
このように、
プログラミング上良かれと思ってヒアドキュメント内に入れたインデントが変数内にもしっかり反映されてしまう
という状況が起こっていた。おまけに、ヒアドキュメントの終わりを宣言する意味を持つ終端IDはインデントせずに書く必要があるという始末。
そのため、ヒアドキュメントでこの状況を回避するためにはインデントを使わずに書かなければならなかったのが今までの状況だった:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
class Hoge extends Fuga { public function getExistingAuthorArticlesSQL() { $sql = <<<SQL SELECT Article.* ,Author.* FROM articles Article INNER JOIN authors Author ON Article.author_id = Author.id WHERE Author.deleted = 0 ; SQL; return $sql; } } ... $hoge = new Hoge(); $sql = $hoge->getExistingAuthorArticlesSQL(); print_r($sql); // result: SELECT Article.* ,Author.* FROM articles Article INNER JOIN authors Author ON Article.author_id = Author.id WHERE Author.deleted = 0 ; |
ううむ、、コードから滲み出るツラミ。
PHP7.3以降のヒアドキュメントでは、終端IDのインデント位置に合わせてドキュメント内のインデントを計算してくれるようになった
ところが、PHP7.3から状況が好転し始める。
- 終端IDがインデントできるようになった
- 終端IDのインデント量に合わせて、ヒアドキュメント内のインデントの開始位置が計算されるようになった
の2点だ。具体例を挙げていく:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
class Hoge extends Fuga { public function getExistingAuthorArticlesSQL() { $sql = <<<SQL SELECT Article.* ,Author.* FROM articles Article INNER JOIN authors Author ON Article.author_id = Author.id WHERE Author.deleted = 0 ; SQL; return $sql; } } ... $hoge = new Hoge(); $sql = $hoge->getExistingAuthorArticlesSQL(); print_r($sql); // result: SELECT Article.* ,Author.* FROM articles Article INNER JOIN authors Article ON Article_author_id = Author.id WHERE Author.deleted = 0 ; |
解説すると、終端ID(SQL)のインデントが半角スペース12個の時、ヒアドキュメント内でも12個分の半角スペースを取り除いた上で、そこからさらにインデントされている分からインデントを計算し始めるようになったのだ。これかなりステキング。皆さんもぜひPHP7.3以降で試してみてほしい。
参考)https://wiki.php.net/rfc/flexible_heredoc_nowdoc_syntaxes