💬

[PHP]PlantUMLで定義されたクラス図からコードを自動生成するツールを作成しました

2021/11/14に公開

概要

PlantUMLのクラス図定義から、phpコードを自動生成するツールを作ってみました。
せっかくなので使い方を紹介してみようと思います。
https://github.com/tasuku43/puml2php

できること

例えば以下のPlantUMLファイルから、composer.jsonに定義されるpackageの定義に基づきディレクトリを解決し、各クラスファイルを生成します。

@startuml
package Sample\Sample2 {
    interface SampleInterface
    abstract class SampleAbstractClass implements SampleInterface
    class SampleClass

    SampleAbstractClass <|-- SampleClass
}
@enduml

もし以下のような定義がなされているならば、src/Sample2配下に三つのファイルが生成される事になります。

"autoload": {
  "psr-4": {
    "Sample\\": "src/"
  }
}

インストール方法と使い方

packagistに公開しているので、以下のコマンドでinstallできます。

composer require --dev puml2php/puml2php

準備

新規ディレクトリを作成し、その中で実行してみようと思います。

$ mkdir puml2php-sample  // サンプルプロジェクト作成
$ cd puml2php-sample
$ mkdir src  // srcディレクトリを生成
$ composer require --dev puml2php/puml2php  // install

composer.jsonにnamespaceを定義します。今回は、srcディレクトリをトップレベルとして、以下のように定義してみます。

"autoload": {
  "psr-4": {
    "Sample\\": "src/"
  }
}

PlantUMLファイルは以下を使用します。

@startuml
package Sample\Sample2 {
    interface SampleInterface
    // SampleInterfaceを実装する抽象クラスを定義
    abstract class SampleAbstractClass implements SampleInterface
    class SampleClass

    // SampleClassはSampleAbstractClassを継承する
    SampleAbstractClass <|-- SampleClass
}
@enduml

puml2php-sampleの中身は現在このような形になっています。

$ tree
.
├── composer.json
├── composer.lock
├── sample.puml
├── src  // 中身は空
└── vendor

以上で準備が整いました。

実行

PlantUMLファイルを指定し、puml2phpを実行します。PlantUMLで定義されたパッケージを元にディレクトリを作成し、各クラスファイルを生成します。
composer.jsonから名前空間が特定できない場合は失敗します。また、生成するクラスファイルが既に存在する場合は、処理をスキップします。

$ php vendor/bin/puml2php /path/to/sample.puml
Generating code from 'sample.puml'.

 - Created: src/Sample2/SampleInterface.php
 - Created: src/Sample2/SampleAbstractClass.php
 - Created: src/Sample2/SampleClass.php

Operations: 3 created, 0 skiped, 0 failed

作成されたファイルを確認してみます。

<?php
declare(strict_types=1);

namespace Sample\Sample2;

/**
 * Class SampleAbstractClass
 * @package Sample\Sample2
 */
abstract class SampleAbstractClass implements SampleInterface
{
}
<?php
declare(strict_types=1);

namespace Sample\Sample2;

/**
 * Class SampleClass
 * @package Sample\Sample2
 */
class SampleClass extends SampleAbstractClass
{
}
<?php
declare(strict_types=1);

namespace Sample\Sample2;

/**
 * Class SampleInterface
 * @package Sample\Sample2
 */
interface SampleInterface
{
}

終わりに

クラス図を作っても実装に移る際に一つづつクラスを作っていくのがすごく面倒だから自動化したい!というモチベーションで作ってみました。構文解析器の実装などは初めてだったので楽しかったです。
試していただけると嬉しいです。

Discussion