Виджеты

Виджеты - это многократно используемые строительные блоки, используемые в представлениях для создания сложных и настраиваемых элементов пользовательского интерфейса в объектно-ориентированном стиле. Например, виджет выбора даты может генерировать фантастический выбор даты, который позволяет пользователям выбирать дату в качестве своего входа. Все, что вам нужно сделать, это просто вставить код в такое представление, как следующее:

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

В Yii имеется большое количество виджетов, например активная форма, меню, виджеты jQuery UI, виджеты Twitter Bootstrap.

Использование виджетов

Виджеты в основном используются в представлениях. Вы можете вызвать метод yii\base\Widget::widget(), чтобы использовать виджет в представлении. Этот метод принимает массив конфигурации для инициализации виджета и возвращает результат визуализации виджета. Например, следующий код вставляет виджет выбора даты, который настроен на использование русского языка и сохраняет входные данные в атрибуте from_date в $model.

<?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 для создания формы входа. Виджет будет создавать открывающий и закрывающий теги <form> в месте, где вызываются функции begin() и end() соответственно. Все, что находится между ними, будет отображаться как есть.

<?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() возвращает экземпляр виджета, который вы можете использовать для создания содержимого виджета.

Настройка глобальных значений по умолчанию

Глобальные значения по умолчанию для типа виджета можно настроить через контейнер DI:

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

Создание виджетов

Чтобы создать виджет, нужно перейти от yii\base\Widget и переопределить методы yii\base\Widget::init() или yii\base\Widget::run(). Обычно метод init() должен содержать код, который нормализует свойства виджета, тогда как метод run() должен содержать код, который генерирует результат визуализации виджета. Результат визуализации может быть непосредственно «отражен» или возвращен в виде строки функцией run().

В следующем примере HelloWidget 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']) ?>

Ниже представлен вариант HelloWidget, который принимает содержимое, заключенное в вызовы begin() и end(), HTML-кодирует его, а затем отображает.

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().

Следующий код показывает, как использовать этот новый вариант HelloWidget:

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

    content that may contain <tag>'s

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

Иногда виджету может понадобиться отображать большой кусок контента. Хотя вы можете вставлять контент в метод run(), лучше поместить его в представление и вызвать yii\base\Widget::render() для его рендеринга. Например:

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

По умолчанию представления для виджета должны храниться в файлах в каталоге WidgetPath/views, где WidgetPath обозначает каталог, содержащий файл класса виджета. Поэтому в приведенном выше примере будет отображаться файл вида @app/components/views/hello.php, при условии, что класс виджетов находится в @app/components. Вы можете переопределить метод yii\base\Widget::getViewPath() для настройки каталога, содержащего файлы представлений виджетов.