よく使うクラスをサクッと作成、"Maker Bundle"

[Symfony Component Advent Calendar 2022](https://qiita.com/advent-calendar/2022/symfony-component)の10日目の記事です。

## 最初に
[Symfony](https://symfony.com)はPHPのフレームワークのひとつです。しかし、公式サイトの説明文には

> Symfony is a set of PHP Components, a Web Application framework, a Philosophy, and a Community — all working together in harmony.
  （SymfonyはPHPコンポーネントのセットで、Webアプリケーションフレームワークで、哲学、そしてコミュニティです。それらがハーモニーを奏でながら動作しています。）

と書かれている通り、PHPコンポーネントのセットで、たくさんのコンポーネントを提供しており、それらを組み合わせてひとつのフレームワークとして動作しています。Symfonyのコンポーネントは、Symfony上だけで動作するのではなく、他のPHPフレームワークやアプリケーションでも動作している強力なものが揃っています。

今回はそれらの中から、役立ちそうなもの・お薦めしたいものを紹介していきたいと思います。

※記事内ではautoloadのインポートは省略します。


## よく使うクラスをサクッと作成、"Maker Bundle"

[Maker Bundle](https://symfony.com/bundles/SymfonyMakerBundle/current/index.html)は、Symfonyでよく使うクラスの作成をサポートするコンポーネントです。ほぼSymfony専用です。
いままで紹介してきたものとはちょっと変わって、開発のサポートをするコンポーネントです。

### インストール

```shell
composer require symfony/maker-bundle --dev
```

#### クラスの作成

Maker Bundleは、`bin/console` コマンドを介して実行します。例えばControllerを作成する必要がある場合、

```shell
bin/console make:controller
```

と実行するとウィザード形式で、作成するControllerの情報を設定します。Controllerの場合はクラス名のみ設定すると、

```shell
 Choose a name for your controller class (e.g. GentleKangarooController):
 > ItemController

 created: src/Controller/ItemController.php

           
  Success! 
           

 Next: Open your new controller class and add some pages!
```

このように指定したクラス名のControllerを以下のように作ってくれます。


```php
<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Annotation\Route;

class ItemController extends AbstractController
{
    #[Route('/item', name: 'app_item')]
    public function index(): JsonResponse
    {
        return $this->json([
            'message' => 'Welcome to your new controller!',
            'path' => 'src/Controller/ItemController.php',
        ]);
    }
}
```

なお、Twigが入っている場合は、Twigファイルも作成してくれます。

### 独自作成コマンドを作成する

Maker Bundleにはいくつかの作成コマンドが用意されており、おおよその開発はこれだけで賄えますが、独自の作成コマンドを作ることもできます。
`AbstractMaker` クラスの子クラスを作り、必要なメソッドをオーバーライドします。


```php:Maker/MakeDto.php

<?php

namespace App\Maker;

use Symfony\Bundle\MakerBundle\ConsoleStyle;
use Symfony\Bundle\MakerBundle\DependencyBuilder;
use Symfony\Bundle\MakerBundle\Generator;
use Symfony\Bundle\MakerBundle\InputConfiguration;
use Symfony\Bundle\MakerBundle\Maker\AbstractMaker;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;

class MakeDto extends AbstractMaker
{
    /** コマンド名を指定するメソッド **/
    public static function getCommandName(): string
    {
        return 'make:dto';
    }

    /** コマンド概要を設定するメソッド **/
    public static function getCommandDescription(): string
    {
        return 'DTOを作ります';
    }

    /** 必要な引数を指定するコマンド **/
    public function configureCommand(Command $command, InputConfiguration $inputConfig)
    {
        $command
            ->addArgument('name', InputArgument::OPTIONAL, 'DTOの名前')
        ;
    }

    /** 作成処理を記述するメソッド **/
    public function generate(InputInterface $input, ConsoleStyle $io, Generator $generator)
    {
        // 作成するクラス名を決定
        $dtoClass = $generator
            ->createClassNameDetails(
                $input->getArgument('name'),
                'Dto\\',
                'Dto'
            );

        // テンプレートファイルからクラスを生成
        $generator->generateClass(
            $dtoClass->getFullName(),
            __DIR__ . '/../Resources/skeleton/dto/Dto.tpl.php'
        );

        // ファイルに書き込み
        $generator->writeChanges();

        $this->writeSuccessMessage($io);
        $io->text('作成完了');
    }

    /** 依存関係を設定するメソッド
    public function configureDependencies(DependencyBuilder $dependencies)
    {
        // TODO: Implement configureDependencies() method.
    }
}
```

大元は`Command`なので、前回紹介した[Console](https://qiita.com/ippey_s/private/6ef5d22e455bf8e78c17)コンポーネントのコマンド作成と似ています。実行メソッドが`generate()`に変わっているので、そこだけ注意が必要です。また、作成するクラスが何かしら依存する場合は`congigureDependencies()`で設定する必要があります。

## まとめ

今回は、Maker Bundleを紹介しました。クラスを作成するためのコマンドが追加されるだけですが、雛形を使ったクラスを作成することで、コードの書き方やクラス名の付け方にある程度秩序が生まれるので、そのあたりもおすすめなコンポーネントです。