Представь, что ты строишь дом. У тебя есть стандартные кирпичи, но тебе нужны необычные окна. В Yii2 виджеты — это такие же кирпичи. Стандартные есть, но иногда хочется своего. В этой статье я расскажу, как создать свой виджет с нуля. Без лишних заморочек, но с душой.

Что такое виджет и зачем он нужен

Виджет в Yii2 — это небольшой кусочек кода, который выводит что-то на страницу. Например, кнопку, форму или список новостей. Он удобен тем, что его можно переиспользовать в разных местах. Не нужно копировать один и тот же код сто раз. Просто вызвал виджет — и всё готово.

Кастомные виджеты нужны, когда стандартные не подходят. Например, тебе нужно вывести сложную таблицу с данными из базы, но с особым оформлением. Или сделать слайдер, которого нет в коробке. Тут и приходят на помощь свои виджеты.

Структура виджета: с чего начать

В Yii2 виджет — это класс, который наследуется от yii\base\Widget. В нём есть два главных метода: init() и run(). Первый — для подготовки данных, второй — для вывода результата. Всё просто.

Давай создадим простой виджет, который показывает приветствие. Создай файл HelloWidget.php в папке components (или в своей папке виджетов).

namespace app\components;

use yii\base\Widget;

class HelloWidget extends Widget
{
    public $name = 'гость';

    public function init()
    {
        parent::init();
        // Тут можно проверить данные
    }

    public function run()
    {
        return "<h2>Привет, {$this->name}!</h2>";
    }
}

Теперь в любом представлении (view) можно вызвать этот виджет:

<?= \app\components\HelloWidget::widget(['name' => 'Алексей']) ?>

На экране появится заголовок "Привет, Алексей!". Магия, да? Но это только начало.

Правило: Всегда вызывай parent::init() в методе init(). Иначе виджет может работать непредсказуемо. Это как застегнуть молнию перед выходом — мелочь, а важно.

Добавляем настройки: свойства и параметры

Виджет становится гибким, когда у него есть настройки. Свойства класса — это те самые параметры, которые можно передать при вызове. Например, цвет кнопки или текст сообщения.

Создадим виджет для вывода сообщения с настройками стиля.

namespace app\components;

use yii\base\Widget;

class MessageWidget extends Widget
{
    public $text = 'По умолчанию';
    public $type = 'info'; // info, success, warning, error

    public function init()
    {
        parent::init();
        if (!in_array($this->type, ['info', 'success', 'warning', 'error'])) {
            $this->type = 'info';
        }
    }

    public function run()
    {
        $class = 'alert alert-' . $this->type;
        return "<div class='{$class}'>{$this->text}</div>";
    }
}

Используем так:

<?= \app\components\MessageWidget::widget([
    'text' => 'Всё работает!',
    'type' => 'success'
]) ?>

Теперь у нас есть универсальное сообщение. Можно передать любой текст и тип. Удобно, правда?

СвойствоОписаниеПример
textТекст сообщения'Привет'
typeТип сообщения (info, success, warning, error)'success'

Работа с представлениями: виджеты с views

Иногда проще вынести HTML в отдельный файл. Это удобно, когда вёрстка сложная. Yii2 позволяет использовать представления внутри виджета.

Создадим папку views внутри папки виджета. Например, components/views. И файл card.php для карточки товара.

// components/CardWidget.php
namespace app\components;

use yii\base\Widget;

class CardWidget extends Widget
{
    public $title;
    public $description;
    public $image;

    public function run()
    {
        return $this->render('card', [
            'title' => $this->title,
            'description' => $this->description,
            'image' => $this->image,
        ]);
    }
}

А в представлении components/views/card.php:

<div class="card">
    <img src="<?= $image ?>" alt="<?= $title ?>">
    <h3><?= $title ?></h3>
    <p><?= $description ?></p>
</div>

Вызов:

<?= \app\components\CardWidget::widget([
    'title' => 'Крутой товар',
    'description' => 'Описание товара',
    'image' => '/images/product.jpg'
]) ?>

Так код остаётся чистым, а вёрстка — отдельно. Удобно для больших проектов.

Лайфхак: Если виджет сложный, разбивай его на подвиджеты. Например, виджет "Корзина" может состоять из виджета "Строка товара" и виджета "Итоговая сумма". Это упрощает поддержку.

Продвинутые возможности: события и JavaScript

Виджеты могут не только выводить HTML, но и подключать JavaScript. Например, для анимации или AJAX-запросов. Yii2 предоставляет удобные методы для регистрации скриптов.

Создадим виджет, который показывает модальное окно при клике.

namespace app\components;

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

class ModalWidget extends Widget
{
    public $buttonText = 'Нажми меня';
    public $modalContent = 'Содержимое окна';

    public function run()
    {
        $id = 'modal-' . $this->getId();
        $js = "
            $('#{$id}-btn').on('click', function() {
                $('#{$id}').show();
            });
            $('#{$id}-close').on('click', function() {
                $('#{$id}').hide();
            });
        ";
        $this->view->registerJs($js);

        $html = Html::button($this->buttonText, ['id' => $id . '-btn']);
        $html .= "<div id='{$id}' style='display:none;'>
                    <div>{$this->modalContent}</div>
                    <button id='{$id}-close'>Закрыть</button>
                 </div>";
        return $html;
    }
}

Подключаем на страницу:

<?= \app\components\ModalWidget::widget([
    'buttonText' => 'Открыть окно',
    'modalContent' => 'Привет, это модальное окно!'
]) ?>

JavaScript регистрируется автоматически. Не нужно вручную добавлять скрипты в layout. Удобно, когда виджетов много.

Что в итоге

Кастомные виджеты в Yii2 — это мощный инструмент. Они помогают не дублировать код, делают проект чище и гибче. Ты можешь создавать виджеты любой сложности: от простых кнопок до целых форм с AJAX. Главное — не бойся экспериментировать.

Начни с малого: сделай виджет для вывода даты или приветствия. Потом усложняй. Со временем ты соберёшь свою библиотеку виджетов, которые ускорят разработку.

Студия WNDER