Yii 2 で Html ヘルパーを作ろう

Html ヘルパーをたくさん使っていると、そのうちに面倒な記述がでてきて自分で作りたくなるかと思います。ということで作ってみましょう！

## アイコンを表示させる Html::icon() を作る

Twitter Bootstrap の 3.x 系だとアイコンを表示させるためには以下のような書き方になります。

```html
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
```

それを `<?= Html::icon('search') ?>` で記述できるような形にしてみます。Twitter Bootstrap のアイコンだけじゃ面白くないので [Font Awesome](http://fortawesome.github.io/Font-Awesome/) にも対応させてみます。

## 記述方法を調べる

### Twitter Bootstrap

- span タグで glyphicon glyphicon-xxxxx な class 属性
- araia-hidden 属性が true
- その他の拡張はなし

### Font Awesome

- i タグで fa fa-xxxxx な class 属性
- 拡張としてアイコンの大きさを変えたり、位置を替えたり、いろいろできる (e.g. fa-lg, pull-left)

Font Awesome の i タグは正しくは span のほうがいいので span タグに統一。Yii 2 は Twitter Bootstrap がデフォルトなので引数もそれに合わせるような形を取る。そんな感じでいきましょう。

## Font Awesome をダウンロード

Composer でダウンロードします。ついでに Font Awesome 用のアセットも作ります。

```composer.json
{
    "require": {
        "bower-asset/components-font-awesome": "*"
    },
}
```

```
composer update
```

```php:FontAwesomeAsset.php
namespace app\assets;

use yii\web\AssetBundle;

class FontAwesomeAsset extends AssetBundle
{
    public $sourcePath = '@bower/components-font-awesome';

    public $css = [
        'css/font-awesome.min.css',
    ];
}
```

```php:AppAsset.php
use yii\web\AssetBundle;

class AppAsset extends AssetBundle
{

    public $depends = [
        'yii\web\YiiAsset',
        'yii\bootstrap\BootstrapAsset',
        'app\assets\FontAwesomeAsset', // 追加
    ];
}
```

## Html::icon() を作ろう

先にテストを書いておきます。assertSame() の左側の引数は期待している値。右側は実際の値。

```php:HtmlTest.php
namespace tests\codeception\unit\helpers;

use yii\codeception\TestCase;
use yii\helpers\Html;

class HtmlTest extends TestCase
{
    public function testIcon()
    {
        $this->assertSame('<span class="glyphicon glyphicon-search" aria-hidden="true"></span>', Html::icon('search'));
        $this->assertSame('<span class="fa fa-search" aria-hidden="true"></span>', Html::icon('search', 'fa'));
        $this->assertSame('<span class="fa fa-search fa-lg" aria-hidden="true"></span>', Html::icon('search', 'fa', 'fa-lg'));
    }
}
```

続いて \yii\helpers\BaseHtml を継承した Html クラスを作成して icon メソッドを追加していきます。作成場所はどこでもかまいませんが今回は app/helpers にします。それと名前空間ですが app\helpers ではなく yii\helpers にしてください。

```php:Html.php
namespace yii\helpers;

class Html extends \yii\helpers\BaseHtml
{
    /**
     * アイコンを生成
     * @param string $name アイコン名
     * @param string $type アイコンの種類 (e.g. twbs, fa)
     * @param string $append 追加したいもの (e.g. fa-lg, fa-fw)
     * @return string
     */
    public static function icon($name, $type = 'twbs', $append = '')
    {
        $options['class'] = 'glyphicon glyphicon-';

        if ($type === 'fa') {
            $options['class'] = 'fa fa-';
        }
        $options['class'] .= (string) $name;

        if ($append !== '') {
            static::addCssClass($options, (string) $append);
        }
        $options['aria-hidden'] = 'true';

        return static::tag('span', '', $options);
    }
}
```

メソッドの作り方は [\yii\helpers\BaseHtml](https://github.com/yiisoft/yii2/blob/master/framework/helpers/BaseHtml.php) のメソッドを眺めると多分わかるかと思います。

最後にエントリースクリプトに以下を追加します。

```php:index.php
// ...
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php'); // この行以降に追加する
Yii::$classMap['yii\helpers\Html'] = '@app/helpers/Html.php';
// ...
```

Yii 側でクラスマップがロードされたあとに独自のものと差し替える形です。ちなみにエントリースクリプトに書くと index-test.php にも追加しないといけないので自分は config/common.php (config/web.php と console.php の共通部分をまとめたファイル) を作成して、そこに書いてます。

これで準備完了です。

```php:こう書くと
<?= Html::icon('search') ?>
```

```html:こう生成される
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
```

```php:こう書くと
<?= Html::icon('search', 'fa', 'fa-lg') ?>
```

```html:こう生成される
<span class="fa fa-search fa-lg" aria-hidden="true"></span>
```

短く書けるだけでなく、CSS Framework のバージョンが上がったりで書き方が変わった場合でも、このメソッドの中身を修正するだけでいいので楽ちんです。どんどん独自のヘルパーを作っていきましょう！

## 関連リンク

[Yii Guide: Helpers > Overview](http://www.yiiframework.com/doc-2.0/guide-helper-overview.html)