5 フォロワー

ウィジェット

ウィジェットは、ビュー で、複雑で構成可能なユーザーインターフェース要素をオブジェクト指向方式で作成するために使用される再利用可能なビルディングブロックです。例えば、日付ピッカーウィジェットは、ユーザーが入力として日付を選択できるような、おしゃれな日付ピッカーを生成できます。ビューに次のコードを挿入するだけで済みます。

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

Yiiには、アクティブフォームメニューjQuery UIウィジェットTwitter Bootstrapウィジェットなど、多くのウィジェットがバンドルされています。以下では、ウィジェットに関する基本的な知識を紹介します。特定のウィジェットの使用方法については、クラスAPIドキュメントを参照してください。

ウィジェットの使用

ウィジェットは、主にビューで使用されます。ビューでウィジェットを使用するには、yii\base\Widget::widget() メソッドを呼び出すことができます。このメソッドは、ウィジェットを初期化するための構成配列を取り、ウィジェットのレンダリング結果を返します。例えば、次のコードは、ロシア語を使用するように構成され、$modelfrom_date属性に入力を保持するように構成された日付ピッカーウィジェットを挿入します。

<?php
use yii\jui\DatePicker;
?>
<?= DatePicker::widget([
    'model' => $model,
    'attribute' => 'from_date',
    'language' => 'ru',
    'dateFormat' => 'php:Y-m-d',
]) ?>

一部のウィジェットは、yii\base\Widget::begin()yii\base\Widget::end() の呼び出しの間で囲む必要のあるコンテンツのブロックを受け取ることができます。例えば、次のコードでは、yii\widgets\ActiveFormウィジェットを使用してログインフォームを生成します。ウィジェットは、begin()end()がそれぞれ呼び出された場所に、開始と終了の<form>タグを生成します。その間のものはすべてそのままレンダリングされます。

<?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">
        <?= Html::submitButton('Login') ?>
    </div>

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

ウィジェットのレンダリング結果を返す yii\base\Widget::widget() とは異なり、yii\base\Widget::begin() メソッドはウィジェットのインスタンスを返し、これを使ってウィジェットのコンテンツを構築できます。

注意: 一部のウィジェットは、yii\base\Widget::end() が呼び出されたときに、囲まれたコンテンツを調整するために 出力バッファリング を使用します。このため、yii\base\Widget::begin()yii\base\Widget::end() の呼び出しは、同じビューファイル内で行われることが期待されます。このルールに従わないと、予期しない出力が発生する可能性があります。

グローバルデフォルトの設定

ウィジェットタイプのグローバルデフォルトは、DIコンテナを介して構成できます。

\Yii::$container->set('yii\widgets\LinkPager', ['maxButtonCount' => 5]);

詳細は、依存性注入コンテナガイドの「実践的な使い方」セクションを参照してください。

ウィジェットの作成

ウィジェットは、要件に応じて2つの異なる方法のいずれかで作成できます。

1: widget() メソッドの利用

ウィジェットを作成するには、yii\base\Widget を拡張し、yii\base\Widget::init() メソッドおよび/または yii\base\Widget::run() メソッドをオーバーライドします。通常、init() メソッドにはウィジェットのプロパティを初期化するコードを含める必要があり、run() メソッドにはウィジェットのレンダリング結果を生成するコードを含める必要があります。レンダリング結果は、run() で直接「エコー」出力するか、文字列として返すことができます。

次の例では、HelloWidgetmessage プロパティに割り当てられたコンテンツを HTML エンコードして表示します。プロパティが設定されていない場合は、デフォルトで「Hello World」が表示されます。

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);
    }
}

このウィジェットを使用するには、次のコードをビューに挿入するだけです。

<?php
use app\components\HelloWidget;
?>
<?= HelloWidget::widget(['message' => 'Good morning']) ?>

場合によっては、ウィジェットが大きなコンテンツの塊をレンダリングする必要がある場合があります。コンテンツを run() メソッド内に埋め込むこともできますが、より良い方法は、ビュー に配置し、yii\base\Widget::render() を呼び出してレンダリングすることです。たとえば、

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

2: begin() および end() メソッドの利用

これは上記のものとわずかな違いがあります。以下は、begin() および end() の呼び出しで囲まれたコンテンツを取得し、HTML エンコードして表示する HelloWidget のバリアントです。

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);
    }
}

ご覧のとおり、PHP の出力バッファは init() で開始されるため、init()run() の呼び出しの間に出力された内容はキャプチャされ、処理され、run() で返されます。

情報: yii\base\Widget::begin() を呼び出すと、ウィジェットの新しいインスタンスが作成され、ウィジェットのコンストラクターの最後に init() メソッドが呼び出されます。 yii\base\Widget::end() を呼び出すと、run() メソッドが呼び出され、その戻り値が end() によってエコーされます。

次のコードは、この新しい HelloWidget のバリアントの使用方法を示しています。

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

    sample content that may contain one or more <strong>HTML</strong> <pre>tags</pre>

    If this content grows too big, use sub views

    For e.g.

    <?php echo $this->render('viewfile'); // Note: here render() method is of class \yii\base\View as this part of code is within view file and not in Widget class file ?>

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

デフォルトでは、ウィジェットのビューは WidgetPath/views ディレクトリ内のファイルに保存する必要があります。ここで、WidgetPath はウィジェットのクラスファイルを含むディレクトリを表します。したがって、上記の例では、ウィジェットクラスが @app/components に配置されていると仮定すると、ビューファイル @app/components/views/hello.php がレンダリングされます。 yii\base\Widget::getViewPath() メソッドをオーバーライドして、ウィジェットのビューファイルを含むディレクトリをカスタマイズできます。

ベストプラクティス

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

ウィジェットを作成する場合は、MVCパターンに従う必要があります。一般的に、ロジックはウィジェットクラスに保持し、プレゼンテーションは ビュー に保持する必要があります。

ウィジェットは自己完結型になるように設計する必要があります。つまり、ウィジェットを使用するときは、他の何もせずにビューにドロップできる必要があります。ウィジェットに CSS、JavaScript、画像などの外部リソースが必要な場合は、これは難しい場合があります。幸い、Yii は アセットバンドル のサポートを提供しており、これを利用して問題を解決できます。

ウィジェットにビューコードのみが含まれている場合、ビュー と非常に似ています。実際、この場合、それらの唯一の違いは、ウィジェットが再配布可能なクラスであるのに対し、ビューはアプリケーション内に保持したいだけのプレーンな PHP スクリプトであるということです。

タイプミスを見つけたり、このページを改善する必要があると思われる場合は?
githubで編集する !