PHP 7.0.0α2 の例外の例外の継承関係を可視化してみた

[PHP7.0.0α2で例外の扱いが変わった](http://qiita.com/rana_kualu/items/68886ba86ee4e75c4122) らしいので継承関係を可視化してみた。

なお、php-build の 7.0.0alpha2 でやってます。

```php:exception.php
<?php
$classes = array();

foreach (get_declared_classes() as $class) {
    if (is_a($class, 'Throwable', true)) {
        if (get_parent_class($class) !== false) {
            $classes[$class] = get_parent_class($class);
        }
    }
}

?>
digraph Exception {
    node [shape="box", fontname="sazanami gothic" fontsize="9"];
    graph [rankdir = RL, fontpath="/usr/share/fonts/japanese/TrueType/"];

    <?php foreach ($classes as $class => $parent): ?>

        <?= $class ?> -> <?= $parent ?>

    <?php endforeach; ?>

}
```

```sh
php exception.php | dot -Tpng > exception.png 
```

![classes.png](https://qiita-image-store.s3.amazonaws.com/0/8734/72e41c76-0a80-cbc4-cb42-421ede62862d.png)

インタフェースが書かれていないので Exception と Error が繋がっていません。

----

インタフェースも書いてみました。

```php:exception.php
<?php
$classes = array();
$interfaces =  array();

function func(ReflectionClass $class)
{
    global $interfaces;
    $name = $class->getName();
    if (isset($interfaces[$name]) === false) {
        $interfaces[$name] = [];
        foreach ($class->getInterfaces() as $iface) {
            $interfaces[$name][] = $iface->getName();
            func($iface);
        }
    }
}

foreach (get_declared_classes() as $class) {
    if (is_a($class, 'Throwable', true)) {
        if (get_parent_class($class) !== false) {
            $classes[$class] = get_parent_class($class);
        }
        func(new ReflectionClass($class));
    }
}

?>
digraph Exception {
    node [shape="box", fontname="sazanami gothic" fontsize="9"];
    graph [rankdir = RL, fontpath="/usr/share/fonts/japanese/TrueType/"];

    <?php foreach ($classes as $class => $parent): ?>

        <?= $class ?> -> <?= $parent ?>

    <?php endforeach; ?>

    <?php foreach ($interfaces as $class => $arr): ?>
        <?php foreach ($arr as $iface): ?>

        <?= $class ?> -> <?= $iface ?> [style = dashed];

        <?php endforeach; ?>
    <?php endforeach; ?>

}
```

```sh
php exception.php | dot -Tpng > exception.png 
```

![exception.png](https://qiita-image-store.s3.amazonaws.com/0/8734/3b2a4e1d-fed6-dbfe-3345-a0646b6f8fad.png)

間接的に実装しているインタフェースも `ReflectionClass::getInterfaces()` に出てくるのでめちゃくちゃわかりにくい図になってしまいました。。。

----

親が実装しているインタフェースは書かないようにした。

```php:exception.php
<?php
$classes = array();
$interfaces =  array();

function func(ReflectionClass $class)
{
    global $interfaces;
    $name = $class->getName();
    if (isset($interfaces[$name]) === false) {
        $interfaces[$name] = [];
        foreach ($class->getInterfaces() as $iface) {
            if ($class->getParentClass()) {
                if ($class->getParentClass()->implementsInterface($iface)) {
                    continue;
                }
            }
            $interfaces[$name][] = $iface->getName();
            func($iface);
        }
    }
}

foreach (get_declared_classes() as $class) {
    if (is_a($class, 'Throwable', true)) {
        if (get_parent_class($class) !== false) {
            $classes[$class] = get_parent_class($class);
        }
        func(new ReflectionClass($class));
    }
}

?>
digraph Exception {
    node [shape="box", fontname="sazanami gothic" fontsize="9"];
    graph [rankdir = RL, fontpath="/usr/share/fonts/japanese/TrueType/"];

    <?php foreach ($classes as $class => $parent): ?>

        <?= $class ?> -> <?= $parent ?>

    <?php endforeach; ?>

    <?php foreach ($interfaces as $class => $arr): ?>
        <?php foreach ($arr as $iface): ?>

        <?= $class ?> -> <?= $iface ?> [style = dashed];

        <?php endforeach; ?>
    <?php endforeach; ?>

}
```

```sh
php exception.php | dot -Tpng > exception.png 
```

![exception.png](https://qiita-image-store.s3.amazonaws.com/0/8734/7e7426e0-d147-1443-980b-3a9e5ae1e68f.png)