structure-widgets.md 8.9 KB
Newer Older
1 2
ウィジェット
============
3

4
ウィジェットは、[ビュー](structure-views.md) で使用される再利用可能な構成ブロックで、
5
複雑かつ構成可能なユーザインタフェイス要素をオブジェクト指向のやり方で作成するためのものです。
6 7
例えば、日付選択ウィジェットを使うと、入力として日付を選択することを可能にする素敵なデイトピッカーを生成することが出来ます。
このとき、あなたがしなければならないことは、次のようなコードをビューに挿入することだけです:
8 9 10 11 12 13 14 15

```php
<?php
use yii\jui\DatePicker;
?>
<?= DatePicker::widget(['name' => 'date']) ?>
```

16 17
数多くのウィジェットが Yii にバンドルされています。
例えば、[[yii\widgets\ActiveForm|アクティブフォーム]] や、[[yii\widgets\Menu|メニュー]]、[jQuery UI ウィジェット](widget-jui.md)[Twitter Bootstrap ウィジェット](widget-bootstrap.md) などです。
18 19
下記では、ウィジェットに関する基本的な知識の手引きをします。
特定のウィジェットの使い方について学ぶ必要がある場合は、クラス API ドキュメントを参照してください。
20 21


22
## ウィジェットを使う <a name="using-widgets"></a>
23

24 25
ウィジェットは主として [ビュー](structure-views.md) で使われます。
ビューでウィジェットを使うためには、[[yii\base\Widget::widget()]] メソッドを使うことが出来ます。
26 27
このメソッドは、ウィジェットを初期化するための [構成情報](concept-configurations.md) 配列を受け取り、ウィジェットのレンダリング結果を返します。
例えば、下記のコードは、日本語を使い、入力を `$model``from_date` 属性に保存するように構成された日付選択ウィジェットを挿入するものです。
28 29 30 31 32 33 34 35

```php
<?php
use yii\jui\DatePicker;
?>
<?= DatePicker::widget([
    'model' => $model,
    'attribute' => 'from_date',
36
    'language' => 'ja',
37 38 39 40 41 42
    'clientOptions' => [
        'dateFormat' => 'yy-mm-dd',
    ],
]) ?>
```

43 44
ウィジェットの中には、コンテンツのブロックを受け取ることが出来るものもあります。
その場合、コンテンツのブロックは [[yii\base\Widget::begin()]] と [[yii\base\Widget::end()]] の呼び出しの間に包むようにしなければなりません。
45 46 47
例えば、次のコードは [[yii\widgets\ActiveForm]] ウィジェットを使ってログインフォームを生成するものです。
このウィジェットは、`begin()``end()` が呼ばれる場所で、それぞれ、開始と終了の `<form>` タグを生成します。
その間に置かれたものは全てそのままレンダリングされます。
48 49 50 51 52 53 54 55 56 57 58 59 60 61

```php
<?php
use yii\widgets\ActiveForm;
use yii\helpers\Html;
?>

<?php $form = ActiveForm::begin(['id' => 'login-form']); ?>

    <?= $form->field($model, 'username') ?>

    <?= $form->field($model, 'password')->passwordInput() ?>

    <div class="form-group">
62
        <?= Html::submitButton('ログイン') ?>
63 64 65 66 67
    </div>

<?php ActiveForm::end(); ?>
```

68 69
[[yii\base\Widget::widget()]] がウィジェットのレンダリング結果を返すのとは違って、[[yii\base\Widget::begin()]] メソッドがウィジェットのインスタンスを返すことに注意してください。
返されたウィジェットのインスタンスを使って、ウィジェットのコンテンツを構築することが出来ます。
70 71


72
## ウィジェットを作成する <a name="creating-widgets"></a>
73

74 75 76
ウィジェットを作成するためには、[[yii\base\Widget]] を拡張して、[[yii\base\Widget::init()]] および/または [[yii\base\Widget::run()]] メソッドをオーバーライドします。
通常、`init()` メソッドはウィジェットのプロパティを正規化するコードを含むべきものであり、`run()` メソッドはウィジェットのレンダリング結果を生成するコードを含むべきものです。
レンダリング結果は、直接に "echo" しても、`run()` の返り値として文字列として返しても構いません。
77

78
次の例では、`HelloWidget``message` プロパティとして割り当てられたコンテンツを HTML エンコードして表示します。
79
プロパティがセットされていない場合は、デフォルトとして "Hello World" を表示します。
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

```php
namespace app\components;

use yii\base\Widget;
use yii\helpers\Html;

class HelloWidget extends Widget
{
    public $message;

    public function init()
    {
        parent::init();
        if ($this->message === null) {
            $this->message = 'Hello World';
        }
    }

    public function run()
    {
        return Html::encode($this->message);
    }
}
```

106
このウィジェットを使うために必要なことは、次のコードをビューに挿入するだけのことです。
107 108 109 110 111

```php
<?php
use app\components\HelloWidget;
?>
112
<?= HelloWidget::widget(['message' => 'おはよう']) ?>
113 114
```

115
下記は `HelloWidget` の変種で、`begin()``end()` の間に包まれたコンテンツを受け取り、それを HTML エンコードして表示するものです。
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138

```php
namespace app\components;

use yii\base\Widget;
use yii\helpers\Html;

class HelloWidget extends Widget
{
    public function init()
    {
        parent::init();
        ob_start();
    }

    public function run()
    {
        $content = ob_get_clean();
        return Html::encode($content);
    }
}
```

139
ご覧のように、`init()` の中で PHP の出力バッファが開始され、`init()``run()` の呼び出しの間の全ての出力がキャプチャされ、`run()` の中で処理されて返されます。
140

141 142
> Info|情報: [[yii\base\Widget::begin()]] を呼ぶと、ウィジェットの新しいインスタンスが作成され、ウィジェットのコンストラクタの最後で `init()` メソッドが呼ばれます。
[[yii\base\Widget::end()]] を呼ぶと、`run()` メソッドが呼ばれて、その返り値が `end()` によって echo されます。
143

144
次のコードは、この `HelloWidget` の新しい変種をどのように使うかを示すものです:
145 146 147 148 149 150 151

```php
<?php
use app\components\HelloWidget;
?>
<?php HelloWidget::begin(); ?>

152
    ... タグを含みうるコンテンツ ...
153 154 155 156

<?php HelloWidget::end(); ?>
```

157 158 159 160
場合によっては、ウィジェットが大きな固まりのコンテンツを表示する必要があるかもしれません。
コンテンツを `run()` メソッドの中に埋め込むことも出来ますが、より良い方法は、コンテンツを [ビュー](structure-views.md)
の中に置いて、[[yii\base\Widget::render()]] を呼んでレンダリングすることです。
例えば、
161 162 163 164 165 166 167 168

```php
public function run()
{
    return $this->render('hello');
}
```

169 170 171 172
既定では、ウィジェット用のビューは `WidgetPath/views` ディレクトリの中のファイルに保存すべきものです。
ここで `WidgetPath` はウィジェットのクラスファイルを含むディレクトリを指します。
したがって、上記の例では、ウィジェットクラスが `@app/components` に配置されていると仮定すると、`@app/components/views/hello.php` というビューファイルがレンダリングされることになります。
[[yii\base\Widget::getViewPath()]] メソッドをオーバーライドして、ウィジェットのビューファイルを含むディレクトリをカスタマイズすることが出来ます。
173 174


175
## 最善の慣行 <a name="best-practices"></a>
176

177
ウィジェットはビューのコードを再利用するためのオブジェクト指向の方法です。
178

179 180
ウィジェットを作成するときでも、MVC パターンに従うべきです。
一般的に言うと、ロジックはウィジェットクラスに保持し、表現は [ビュー](structure-views.md) に保持すべきです。
181

182 183 184 185
ウィジェットは自己完結的に設計されるべきです。
言い換えると、ウィジェットを使うときに、他に何もしないでもビューに挿入することが出来るようにすべきです。
この要求は、ウィジェットが CSS、JavaScript、画像などの外部リソースを必要とする場合は、扱いにくい問題になり得ます。
幸いなことに、Yii はこの問題を解決するのに利用することが出来る [アセットバンドル](structure-assets.md) のサポートを提供しています。
186

187 188 189
ウィジェットがビューコードだけを含む場合は、[ビュー](structure-views.md) と非常に似たものになります。
実際のところ、この場合、両者の唯一の違いは、ウィジェットが再配布可能なクラスである一方で、
ビューはアプリケーション内に保持することが望ましい素の PHP スクリプトである、というぐらいの事です。