polidog lab

Top About Rss
2021年12月14日

Symfonyで開発時に使いたいコードを分離する

Symfony Advent Calendar 2021 の14日目の記事です。

昨日は @ttskch さんの [Symfony][Doctrine] エンティティを自前でJsonSerializableにするときはプロパティの循環参照に要注意 でした🌈

今日は自分が開発時にか使わないコードをどう分離するかという話をしたいと思います。

開発時にしか使わないコードをどうするか?

開発を進めていくとどのプロジェクトでも絶対発生する、開発(dev)環境でしか使わないコード。 みなさんのプロジェクトにもありますよね?

この開発時にしか使わないコードって、本番環境(prod)で実行されるとかなりヤバいってことがたまによくありますよね? ただ、開発時には必要。

安全のためにも本番環境では実行されないようにしたい。 そういった問題を解決するために本番環境では分離するように最近はしています。

どのように実現するのか?

compsoerのautoload-dev をうまく活用して実現することができます。

大体symfonyでプロジェクトを作ると composer.jsonのautoload-dev の部分が以下のように書かれています。

    "autoload-dev": {
        "psr-4": {
            "App\\Tests\\": "tests/"
        }
    },

ここに以下のように変更します。

    "autoload-dev": {
        "psr-4": {
            "App\\Tests\\": "tests/",
            "App\\Dev\\": "src-dev/"
        }
    },

そして src とか tests のあるディレクトリで src-dev を追加します。

開発時に必要なコードはsrc-dev に追加していきます。

services_dev.yamlを用意する

services.yamlをみてみると App なnamespaceに対してのDIの設定が記述されています。 src-dev のNamespaceはApp\Dev になっているのでDIのオートワイヤリングとかこのままではうまくいきません。 ということで config/services_dev.yamlを用意しましょう。

parameters:

services:
  _defaults:
    autowire: true
    autoconfigure: true

  App\Dev\:
    resource: '../src-dev/'

こんな感じに書いておけばsrc-devに入っているコードもsrc ディレクトリ同様にオートワイヤリングされます。 必要に応じてここにDIの設定も書いていけばいいかと思います。

テスト時にsrc-devにあるクラスをself::getContainer()->get()したい場合

services_dev.yamlは通常だとenvironmentがdevの場合にしかロードされません。 テスト時に利用したい場合は src/Kernel.php を変更する必要があります。

configureContainer メソッドにenvironmentがtestのときはservices_dev.yamlも読むように修正します。

    protected function configureContainer(ContainerConfigurator $container): void
    {
        $container->import('../config/{packages}/*.yaml');
        $container->import('../config/{packages}/' . $this->environment . '/*.yaml');

        if (is_file(\dirname(__DIR__) . '/config/services.yaml')) {
            $container->import('../config/services.yaml');
            $container->import('../config/{services}_' . $this->environment . '.yaml');
            if ($this->environment ===  'test') {
                $container->import('../config/{services}_dev.yaml');
            }
        } else {
            $container->import('../config/{services}.php');
        }
    }

開発用のコマンドを作りたいんだけど

安心してください。src-dev/Command というディレクトリを追加するだけでコマンドとして認識されます。 細かく調査はできてないんですが、調べた時の流れを簡単にツイートしてます。

最後に

開発用のコードを分離することで本番環境での事故を防ぎやすくなるし、どのコードが開発のときだけ使うかをわかりやすくなるのでぜひ試してみてください。

あすは @77web さんの記事ですー!Symfony UXなにもわからないのですごく楽しみです!!!

comments powered by Disqus