Help us understand the problem. What is going on with this article?

Yii 2: Html ヘルパーを使おう

More than 5 years have passed since last update.

はじめに

Html クラスは HTML タグを生成するためのクラスです。Yii 2 では \yii\helpers に属するので 「Html ヘルパー」という名前で呼ぶことにします。主にビューやウィジェットで使われるかと思います。さまざまなものがあり、いちいち覚えるのがめんどくさいですし、その都度覚えればいいとは思いますが、いくつかのパターンがあるので、まず最初にそれらを抑えておきましょう。

その前に

Yii の公式ガイドには Html ヘルパーについて 詳しく書かれているページがあるので先に読んでおきましょう。また、この記事はガイドのものと若干(かなり)内容がかぶりますが予めご了承ください。

パターン

  • Html ヘルパーは Html::methodName() で表現する
  • 引数の最後は属性 (id, classなど) を追加するものか、または微調整のためのもの
  • active からはじまるメソッドとそうでないものがある

では早速いろいろ使ってみましょう。

一般的な Html ヘルパー

(以降 Html ヘルパーを使う場合はすべて use yii\helpers\Html; と書かれていることを前提にします)

Html::a($text, $url = null, $options = [])

リンクを生成。

たとえば site/index ページから site/login ページへのリンクを貼りたい場合は、

こう書く
<?= Html::a('Login', ['login']) ?>
するとこうレンダリングされる
<a href="/site/login">Login</a>

post/index ページから site/login ページへのリンクを貼りたい場合は、

input
<?= Html::a('Login', ['site/login']) ?>
output
<a href="/site/login">Login</a>

現在いるコントローラの別のアクションにジャンプしたい場合は、アクション名のみを書くだけで良い感じにやってくれます。それ以外の場合は コントローラ名/アクション名 または モジュール名/コントローラ名/アクション名 という感じに書きましょう。 これに従うことによって urlManager を使って URL をカスタマイズした場合でもビュー側で何かを変更する必要がなくなります。直接 HTML タグを書く場合は変化のない静的なものだけにしましょう。

その他いろいろ。

class属性を追加したい場合
<?= Html::a('Login', ['site/login'], ['class' => 'btn btn-primary']) ?>
output
<a class="btn btn-primary" href="site/login">Login</a>
アイコンを含めたリンクとか
<?= Html::a(Html::tag('span', '', ['class' => 'glyphicon glyphicon-user']) . ' Login', ['site/login']) ?>
output
<a href="/site/login"><span class="glyphicon glyphicon-user"></span> Login</a>

ちなみに Html::a() の第一引数の $text ですが、自動的にエンコードされないので、直接文字列を書かない場合 (特にユーザからの入力値などを扱う場合) はすべて Html::a(Html::encode($string), [...]) と書きましょう。

Html::encode($content, $doubleEncode = true)

特殊文字を HTML エンティティに変換。

input
<?= Html::encode('<script>alert("Qiita");</script>') ?>
output
&lt;script&gt;alert(&quot;Qiita&quot;);&lt;/script&gt;

これは直接コードを見たほうがわかりやすいので説明は省略します。PHP から出力する文字列はほぼすべて Html::encode() を通してやるのが理想です。特にユーザからの入力値に対しては必ず使いましょう。

Html::img($src, $options = [])

画像タグを生成。

input
<?= Html::img('@web/images/qiita.png') ?>
output
<img src="/images/qiita.png" alt="">

@web は現在実行中の Web アプリケーションのベース URL を表します。

alt属性を追加
<?= Html::img('@web/images/qiita.png', ['alt' => 'qiita']) ?>
output
<img src="/images/qiita.png" alt="qiita">

Html::ul($items, $options = [])

順不同なリストを生成。

input
<?= Html::ul(['a1', 'a2', 'a3']) ?>
output
<ul>
<li>a1</li>
<li>a2</li>
<li>a3</li>
</ul>
ulにclass属性を追加
<?= Html::ul(['a1', 'a2', 'a3'], ['class' => 'list']) ?>
output
<ul class="list">
<li>a1</li>
<li>a2</li>
<li>a3</li>
</ul>
liにclass属性を追加
<?= Html::ul(['a1', 'a2', 'a3'], ['itemOptions' => ['class' => 'list']]) ?>
output
<ul>
<li class="list">a1</li>
<li class="list">a2</li>
<li class="list">a3</li>
</ul>
liタグ内にリンクを貼る
<?= Html::ul(['user', 'profile', 'post'], ['item' => function ($item) {
    return Html::tag('li', Html::a($item, ["$item/index"]));
}]) ?>
output
<ul>
<li><a href="/user/index">user</a></li>
<li><a href="/profile/index">profile</a></li>
<li><a href="/post/index">post</a></li>
</ul>

Html::ul() の第一引数の配列の各値は Html::a() などと違い自動的にエンコードされます。エンコードしたくない場合は

こう書く
<?= Html::ul(['a1', 'a2', 'a3'], ['encode' => false]) ?>

Html::cssFile($url, $options = [])

外部 CSS ファイルを参照するリンクタグを生成。

input
<?= Html::cssFile('@web/css/style.css') ?>
output
<link href="/css/style.css" rel="stylesheet">
IE9未満向け
<?= Html::cssFile('@web/css/ie.css', ['condition' => 'lt IE 9']) ?>
output
<!--[if lt IE 9]>
<link href="/css/ie.css" rel="stylesheet">
<![endif]-->

Html::jsFile() も同じような書き方になります。

フォーム関連の Html ヘルパー

Html::beginForm($action = '', $method = 'post', $options = [])

フォームの開始タグを生成。

hoge/createにいる場合
<?= Html::beginForm() ?>
output
<form action="/hoge/create" method="post">
<input type="hidden" name="_csrf" value="TndpdWd5dG8bQh0yFy8VAjwZDSckADANOjoNTRAKTVw7PF5ENDYnNg==">

yii\web\Request::enableCsrfValidation の値が true の場合 (デフォルトは true) CSRF対策用のトークンが自動で埋め込まれます。

enctype属性の追加(hoge/createにいる場合)
<?= Html::beginForm('', 'post', ['enctype' => 'multipart/form-data']); ?>
output
<form action="/hoge/create" method="post" enctype="multipart/form-data">
<input type="hidden" name="_csrf" value="cURhWXUyZlkVDlkLP0gJC0dpFzQBXggRKy80PD91Ej8mcSsxGmYnDw==">
method属性をgetで(hoge/indexにいる場合)
<?= Html::beginForm([''], 'get') ?>
output
<form action="/hoge/index" method="get">

Html::beginForm() は Html::endForm() とご一緒に。

Html:: textInput($name, $value = null, $options = [])

テキスト入力フィールドを生成。

input
<?= Html::textInput('search', $search, ['placeholder' => 'Search']) ?>
output
<input type="text" name="search" placeholder="Search">

Html::passwordInput(), Html::fileInput() なども同じような書き方になります。

Html::radio($name, $checked = false, $options = [])

ラジオボタンを生成。

ラベルに画像を使ったラジオボタン
<?= Html::radio('qiita', false, ['label' => Html::img('@web/images/qiita.png')]) ?>
output
<label><input type="radio" name="qiita" value="1"> <img src="/images/qiita.png" alt=""></label>

label オプションでは画像なども選択できますが、ユーザからの入力などをラベルに使用する場合は必ず Html::encode() を通したものを使いましょう。

ラジオボタンがチェックされていない場合は0を送るようにする
<?= Html::radio('hoge', true, ['uncheck' => 0, 'label' => 'ほげ']) ?>
output
<input type="hidden" name="hoge" value="0">
<label><input type="radio" name="hoge" value="1"> ほげ</label>

Html::checkbox() なども同じような書き方になります。

Html::checkboxList($name, $selection = null, $items = [], $options = [])

チェックボックスのリストを生成。

input
<?= Html::checkboxList('framework', null, ['Yii', 'CakePHP', 'Laravel']) ?>
output
<div>
<label><input type="checkbox" name="framework[]" value="0"> Yii</label>
<label><input type="checkbox" name="framework[]" value="1"> CakePHP</label>
<label><input type="checkbox" name="framework[]" value="2"> Laravel</label>
</div>

デフォルトでは div タグで囲まれます。変更したい場合は tag オプションを追加しましょう。

以下のような感じで第二引数の $selection を指定しておくと、予めチェックされた状態でチェックボックスを生成できます。

YiiとCakePHPをチェックされた形でチェックボックスのリストを生成
<?= Html::checkboxList('framework', [0, 1], ['Yii', 'CakePHP', 'Laravel']) ?>
output
<div>
<label><input type="checkbox" name="framework[]" value="0" checked> Yii</label>
<label><input type="checkbox" name="framework[]" value="1" checked> CakePHP</label>
<label><input type="checkbox" name="framework[]" value="2"> Laravel</label>
</div>

第三引数の $items の値は Html::ul() などと同様に自動的にエンコードされます。エンコードしたくない場合は encode オプションで false を指定します。

Html::dropDownList($name, $selection = null, $items = [], $options = [])

ドロップダウンリストを生成。

都道府県ドロップダウンリスト
<?php $items = [
    ['id' => 1, 'name' => '東京都', 'group' => '関東地方'],
    ['id' => 2, 'name' => '大阪府', 'group' => '近畿地方'],
    ['id' => 3, 'name' => '福岡県', 'group' => '九州地方'],
]; ?>

<?= Html::dropDownList('pref', null,
    ArrayHelper::map($items, 'id', 'name', 'group'), [
        'prompt' => '都道府県を選択してください。'
    ]
) ?>
output
<select name="pref">
<option value="">都道府県を選択してください。</option>
<optgroup label="関東地方">
<option value="1">東京都</option>
</optgroup>
<optgroup label="近畿地方">
<option value="2">大阪府</option>
</optgroup>
<optgroup label="九州地方">
<option value="3">福岡県</option>
</optgroup>
</select>

こちらも上記でいえば、値 (value="1"の部分) とラベル (東京都の部分) は自動でエンコードされます。encodeSpaces オプション (デフォルト false) に true を渡してあげるとラベル (東京都の部分) にスペースが含まれている場合 &nbsp; にエンコードされます。ArrayHelper::map() は Yii 1.x でいうところの CHtml::listData() みたいな役割でしょうか。

active からはじまるフォーム関連の Html ヘルパー

active からはじまるフォーム関連の Html ヘルパーは、指定されたモデル属性からデータを取ってきます。

Html::activeTextInput($model, $attribute, $options = [])

与えられたモデル属性のテキスト入力タグを生成。

input
<?= Html::activeTextInput($user, 'username', ['class' => 'form-control']) ?>
output
<input type="text" id="user-username" class="form-control" name="User[username]">

id, name, value 属性が関連するモデルに対応し、自動的にふられる形になります。そのほかの active から始まるものすべてがこういう感じになります。

ただ、バリデーションを実行したり、動的に css を変更したり、Javascript などを使って何か操作したい場合などを考えるとけっこうやることが多くて大変になってきます。そういうときのために Yii では ActiveForm というウィジェットが用意されています。ここでは詳細は省きますが、多機能でいろいろと楽ができるかもなので、是非こちらを使って開発していきましょう。

active 系は一個しか書いてないですが、そういう感じですw

まとめ

Html ヘルパーは単体で見ていくとけっこう退屈ですが、ウィジェットなどを自分で作るようになるとけっこう楽しくなってくるかと思います。

けっこう省いているメソッドがあるので、それらは関連リンクなどを参考にしてみてください。

関連リンク

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした