1.11. 静的解析

Qiqテンプレートファイルは、PHPStanなどの静的解析ツールで簡単に分析できます。分析を有効にするにはdocblockのみが必要です。このdocblockは、Template メソッド、ヘルパー、および変数を分析ツールが認識できるようにするものです。

1.11.1. 分析の有効化

分析対象の各テンプレートファイルに、Qiq\EngineHelpers オブジェクトの交差型を使用して $this の型を指定するdocblockを追加します。

また、テンプレートファイルで使用される各変数を必ずドキュメント化してください。

PHPコードでは、docblockは以下のようになるかもしれません...

<?php
/**
 * @var \Qiq\Engine&\Qiq\Helper\Html\HtmlHelpers $this
 * @var string $name
 */
?>
Hello <?= $this->h($name) ?>!

...一方、Qiq構文では以下のようになるかもしれません:

{{ /** @var \Qiq\Engine&\Qiq\Helper\Html\HtmlHelpers $this */ }}
{{ /** @var string $name */ }}

Hello {{h $name }}!

1.11.1.1. カスタム型付け

この型ヒントが冗長だと感じる場合、静的解析ツールでカスタム疑似型を定義できる場合があります。例えば、PHPStanの設定エントリで以下の型エイリアスを定義できます:

parameters:
    typeAliases:
        HtmlTemplate: \Qiq\Engine&\Qiq\Helper\Html\HtmlHelpers

そして、テンプレートファイルのdocblockで、$this をカスタム型として指定できます:

{{ /** @var HtmlTemplate $this */ }}

1.11.1.2. ミックスイン

あるいは、Template クラス自体を拡張し、適切な Helpers クラスの @mixin を指定することもできます。例えば:

namespace Project;

use Qiq\Catalog;
use Qiq\Helper\Html\HtmlHelpers;
use Qiq\Template;

/**
 * @mixin HtmlHelpers
 */
class HtmlTemplate extends Template
{
    public function __construct(
        Catalog $catalog,
        HtmlHelpers $helpers
    ) {
        parent::__construct($catalog, $helpers)
    }
}

そして、テンプレートファイルのdocblockで、拡張クラス名を使用できます:

{{ /** @var Project\HtmlTemplate $this */ }}

1.11.2. 分析の実行

テンプレートファイルがPHPのみの場合、これで十分です:ソースの場所にあるままで静的解析を実行できます。

ただし、Qiq構文を含むテンプレートファイルの場合、静的解析の前にテンプレートファイルをPHPにコンパイルする必要があります。そのために、テンプレートファイルをレンダリングする Template クラスをインスタンス化し、Catalog 内のすべてのテンプレートファイルを compileAll() します:

$cachePath = '/path/to/compiled';

$template = Template::new(
    paths: ...,
    cachePath: $cachePath,
);

$template->getCatalog()->compileAll();

その後、コンパイルされたテンプレートファイルの $cachePath ディレクトリに対して静的解析を実行できます(分析不可能なQiqコードを含むソーステンプレートファイルに対してではありません)。

上記の $cachePath 例を考えると、コンパイルされたテンプレートファイルの静的解析のためのPHPStan設定エントリには、以下のようなエントリが含まれるかもしれません:

parameters:
    paths:
        - /path/to/compiled/

1.11.3. 分析の問題の解決

静的解析によって明らかになった問題のデバッグと解決は簡単です。

コンパイルされたテンプレートファイルはソーステンプレートファイルのパスを使用して $cachePath に保存されるため、どのソーステンプレートファイルに問題があるかを簡単に確認できます。

さらに、コンパイルされたテンプレートコードの行がソーステンプレートコードの行と一致するため、報告される行番号も一致します。

そこから、他のPHPコードと同様にソーステンプレートファイルの問題を解決し、再コンパイルして再分析します。