[PHP] 7.3~でヒアドキュメントのインデントルールが大幅に改善された

2020/03/15

author

masyus

Webプログラミングフレームワークを使った実装では、ORマッパーでSQLを組み立てることがよくあります。ですが複雑なSQLを組み立てたい場合はORMではなく、ベタのSQLを書きたいこともあります。

ヒアドキュメントを使って書くことが多いかと思われますが、PHP7.2以前までのヒアドキュメント(&ナウドキュメント)はインデントの扱いが結構曲者でした。それがPHP7.3以降では劇的に改善されましたので、今回紹介していきます。

PHP7.2までのヒアドキュメント内のインデントの扱い

全て反映されてしまっていました。下記のようになります:

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; // ←終端ID(=ヒアドキュメントの終わりを宣言する)と呼びます

        return $sql;
    }
}

...

$hoge = new Hoge();
$sql = $hoge->getExistingAuthorArticlesSQL();
print_r($sql);

実行結果:

            SELECT
                Article.*
                ,Author.*
            FROM
                articles Article
            INNER JOIN authors Author
                ON Article.author_id = Author.id
            WHERE
                Author.deleted = 0
            ;

残念なことに、

プログラミング上良かれと思ってヒアドキュメント内に入れたインデントが反映されてしまう

という事態になっておりました。さらには終端IDもインデントせずに記述する必要がある等、散々な状態です。

そのため、ヒアドキュメントでこの状況を回避するためにはインデントを使わずに書く必要がありました。

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);

実行結果:

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がインデントできるようになった

これにより、PHP7.2で悩まされたヒアドキュメントの記述が綺麗に書けるようになっています。

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);

実行結果:

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以降で試していただければと。

参考