読者です 読者をやめる 読者になる 読者になる

Symfony Best Practice 訳してみた - Chapter6 -

Symfony Best Practiceの翻訳をしてます。 六日目です。

前回の記事

hanahirodev.hatenablog.com

※多分に意訳が入っておりますので、誤訳がある場合はご指摘ください。

※読み進めていくSymfony Best Practiceは 2016/10/23時点の情報です。

※写経をする場合は、事前にPHPの実行ができる環境をご用意ください。

3行まとめ

  • Symfony3.0で唯一動作保障されているテンプレートエンジンTwigを使おう。

  • テンプレートはapp/Resources/views/に配置して幸せになろう。

  • Twig拡張を開発しよう。


第6章 Templates

PHPが20年前に誕生した当初は、その単純さ、HTMLとの親和性、動的なコードに開発者たちは熱狂しました。 しかし、時が経つにつれ、Twig*1のような、より良いテンプレートを作成できる言語が出てきました。

  • テンプレートにはTwigを使いましょう。

一般的に、PHPによるテンプレートは、テンプレートで要求される継承、自動エスケープ、フィルタや関数に対する名前付き引数といったモダンな機能を備えていないため、Twigに比べれば冗長になってしまいます。 TwigはSymfonyにおけるデフォルトのテンプレートフォーマットで、有名どころで言うとDrupal8で採用されるなど、PHP以外も含めたすべてのテンプレートエンジンの中で最大のコミュニティーのサポートがあります。 加えて、TwigはSymfony3.0が動作保障する唯一のテンプレートフォーマットです。実のところ、 PHPはテンプレートエンジンとしてはサポートされなくなるでしょう。

テンプレートの配置
  • app/Resources/view/ディレクトリ配下にテンプレートを格納しましょう。

かつて、Symfonyの開発者たちは、バンドルごとにResources/views/ディレクトリ配下にテンプレートを格納していました。そのため、参照するための論理名を使用していました。(AcmeDemoBundle:Default:index.html.twigのように) しかし、アプリ内でテンプレートを使うには、app/Resources/views/ディレクトリ配下に格納する方が、はるかに便利です。手始めに、単純化してみてみましょう。

バンドルに保存されたテンプレート app/に保存されたテンプレート
AcmeDemoBundle:Default:index.html.twig default/index.html.twig
::layout.html.twig layout.html.twig
AcmeDemoBundle::index.html.twig index.html.twig
AcmeDemoBundle:Default:subdir/index.html.twig default/subdir/index.html.twig
AcmeDemoBundle:Default/subdir:index.html.twig default/subdir/index.html.twig

ほかにも、テンプレートを1箇所に集めることでデザイナーの仕事が単純化されるという効果が有ります。散らばったバンドルの海の中からテンプレートを探し出す必要がなくなるのです。

Twigの拡張

Blogアプリには、マークダウンで書かれた記事をHTMLに変換して投稿するために、md2htmlというTwigのフィルターが必要です。 まずはじめに、Parsedown*2というマークダウンパーサーを依存ライブラリとしてインストールします。

$ composer require erusev/parsedown

次に、後ほどTwig拡張から利用するMarkdownサービスを作ります。クラスのパスを書くだけで定義は完了です。

# app/config/services.yml
services:
    # ...
    app.markdown:
        class: AppBundle\Utils\Markdown

さて、Markdownクラスにはマークダウン記法からHTMLに変換するメソッドを一つ定義します。

namespace AppBundle\Utils;

class Markdown
{
    private $parser;

    public function __construct()
    {
        $this->parser = new \Parsedown();
    }

    public function toHtml($text)
    {
        $html = $this->parser->text($text);

        return $html;
    }
}

次に、Twig拡張を作成して、Twig_SimpleFilterクラスを使って、md2htmlフィルタを定義します。新たに定義したmarkdownサービスをTwig拡張のコンストラクタに注入します。

namespace AppBundle\Twig;

use AppBundle\Utils\Markdown;

class AppExtension extends \Twig_Extension
{
    private $parser;

    public function __construct(Markdown $parser)
    {
        $this->parser = $parser;
    }

    public function getFilters()
    {
        return array(
            new \Twig_SimpleFilter(
                'md2html',
                array($this, 'markdownToHtml'),
                array('is_safe' => array('html'))
            ),
        );
    }

    public function markdownToHtml($content)
    {
        return $this->parser->toHtml($content);
    }

    public function getName()
    {
        return 'app_extension';
    }
}

最後に、新しくサービスを定義して、Twig拡張をアプリケーションから使えるように有効化します。(自前のコードから呼び出すことがないので、サービス名はなんでも良いです。)

# app/config/services.yml
services:
    app.twig.app_extension:
        class:     AppBundle\Twig\AppExtension
        arguments: ['@app.markdown']
        public:    false
        tags:
            - { name: twig.extension }

感想

前に作ったTwig拡張見直してみよう。

(2016/11/3 更新)

next

hanahirodev.hatenablog.com