Вы когда-нибудь задумывались, как сделать свой код на Yii2 переиспользуемым? Чтобы не копировать один и тот же функционал из проекта в проект, а просто подключить готовый модуль или компонент. В этой статье я расскажу, как создавать собственные расширения и компоненты для Yii2, какие подводные камни вас ждут и как их обойти. Будет много кода, примеров и практических советов.
Что такое компонент и расширение в Yii2
Для начала давайте разберемся с терминами. В Yii2 есть два близких понятия: компонент и расширение.
Компонент — это класс, который можно подключить к приложению через конфигурацию. Он может быть как простым (например, работа с почтой), так и сложным (например, полноценный модуль). Компоненты обычно регистрируются в секции components конфигурационного файла.
Расширение — это пакет, который распространяется через Composer. Он может содержать компоненты, модули, виджеты, поведения, консольные команды и даже целые приложения. Расширение — это способ упаковать ваш код для многократного использования, как в своих проектах, так и для сообщества.
Проще говоря, компонент — это кирпичик, а расширение — это коробка с кирпичиками и инструкцией по сборке.
Первый шаг: создаем компонент
Начнем с простого — создадим компонент для работы с API какого-нибудь сервиса. Пусть это будет сервис отправки SMS. Наш компонент будет иметь метод send($phone, $message).
Создаем файл components/SmsSender.php:
namespace app\components;
use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
class SmsSender extends Component
{
public $apiKey;
public $apiUrl = 'https://sms.ru/api';
public function init()
{
parent::init();
if (empty($this->apiKey)) {
throw new InvalidConfigException('Необходимо указать apiKey');
}
}
public function send($phone, $message)
{
// Здесь логика отправки SMS через HTTP-запрос
$response = file_get_contents($this->apiUrl . '?key=' . $this->apiKey . '&phone=' . $phone . '&text=' . urlencode($message));
return strpos($response, '100') !== false;
}
}
Теперь подключаем его в конфигурации приложения (config/web.php):
'components' => [
'sms' => [
'class' => 'app\components\SmsSender',
'apiKey' => 'ваш_ключ',
],
],
Готово! Теперь в любом месте приложения можно вызвать:
Yii::$app->sms->send('+79991234567', 'Привет!');
Обратите внимание: мы наследуемся от yii\base\Component, чтобы получить такие бонусы, как события и поведения. Если они не нужны, можно наследоваться от yii\base\BaseObject — это немного легче.
Превращаем компонент в расширение
Теперь, когда компонент работает, захотелось использовать его в другом проекте. Самое время упаковать его в расширение. Для этого создаем отдельную директорию, например, sms-sender, и внутри — composer.json.
Минимальный composer.json:
{
"name": "myname/sms-sender",
"description": "Компонент для отправки SMS",
"type": "yii2-extension",
"require": {
"yiisoft/yii2": "*"
},
"autoload": {
"psr-4": {
"myname\\smssender\\": "src/"
}
}
}
Переносим наш класс в src/SmsSender.php, меняем неймспейс на myname\smssender.
Теперь публикуем пакет на GitHub, добавляем тег версии (например, v1.0.0), затем регистрируем его на Packagist. После этого любой разработчик может установить его через Composer:
composer require myname/sms-sender
Но чтобы другим было удобно, нужно добавить документацию и примеры использования. Иначе никто не поймет, как настроить ваш компонент.
Модуль как расширение: когда компонента мало
Иногда функционал настолько объемный, что нужен модуль. Например, модуль для комментариев или блога. Модуль — это тоже класс, но он содержит контроллеры, представления, модели, миграции и прочее.
Создадим модуль blog. Структура:
blog/
src/
BlogModule.php
controllers/
PostController.php
models/
Post.php
views/
post/
index.php
view.php
migrations/
m240101_000000_create_post.php
composer.json
В BlogModule.php:
namespace myname\blog;
use yii\base\Module;
class BlogModule extends Module
{
public $controllerNamespace = 'myname\blog\controllers';
public function init()
{
parent::init();
// Пользовательская инициализация
}
}
Подключение в приложении:
'modules' => [
'blog' => [
'class' => 'myname\blog\BlogModule',
],
],
Теперь по адресу /?r=blog/post/index будет доступен список постов.
В модуле можно использовать миграции. Для этого нужно настроить путь к миграциям в composer.json:
"extra": {
"yii2": {
"migrations": [
"myname\blog\migrations"
]
}
}
После установки расширения миграции будут автоматически подхватываться командой yii migrate.
Виджеты и поведения: добавляем «фишек»
Расширение может содержать не только компоненты и модули, но и виджеты. Виджет — это класс, который выводит HTML-код. Например, виджет облака тегов.
namespace myname\blog\widgets;
use yii\base\Widget;
use myname\blog\models\Tag;
class TagCloud extends Widget
{
public $limit = 10;
public function run()
{
$tags = Tag::find()->orderBy(['frequency' => SORT_DESC])->limit($this->limit)->all();
return $this->render('tag-cloud', ['tags' => $tags]);
}
}
А поведения — это способ переиспользовать функциональность между моделями. Например, поведение для автоматической генерации slug (ЧПУ) из названия.
namespace myname\blog\behaviors;
use yii\base\Behavior;
use yii\db\ActiveRecord;
use yii\helpers\Inflector;
class SluggableBehavior extends Behavior
{
public $sourceAttribute = 'title';
public $slugAttribute = 'slug';
public function events()
{
return [
ActiveRecord::EVENT_BEFORE_INSERT => 'makeSlug',
ActiveRecord::EVENT_BEFORE_UPDATE => 'makeSlug',
];
}
public function makeSlug($event)
{
$model = $this->owner;
if (empty($model->{$this->slugAttribute})) {
$model->{$this->slugAttribute} = Inflector::slug($model->{$this->sourceAttribute});
}
}
}
Теперь в любой модели можно просто прикрепить это поведение:
public function behaviors()
{
return [
[
'class' => SluggableBehavior::class,
'sourceAttribute' => 'title',
'slugAttribute' => 'slug',
],
];
}
Правила и лайфхаки при создании расширений
Создание расширений — это не только код, но и забота о пользователях. Вот несколько правил, которые я выработал за годы работы.
- Документируйте все публичные свойства и методы — люди не любят читать чужой код, чтобы понять, как работать с вашим расширением.
- Следуйте стандартам PSR — это обеспечит совместимость с другими библиотеками и инструментами.
- Используйте семантическое версионирование (SemVer) — это поможет пользователям понять, насколько безопасно обновляться.
- Пишите тесты — даже простые тесты значительно повышают доверие к вашему коду.
- Публикуйте исходники на GitHub — это бесплатно и позволяет другим вносить вклад.
Также полезно добавить в расширение консольные команды. Например, для очистки кэша или генерации отчета. Для этого создайте класс, унаследованный от yii\console\Controller, и укажите его в composer.json:
"extra": {
"yii2": {
"commands": [
"myname\blog\commands\PostController"
]
}
}
Что в итоге
Создание расширений и компонентов для Yii2 — это отличный способ структурировать код и делиться им с другими. Начните с малого: превратите часто используемый компонент в расширение, затем добавите модуль, виджеты и поведения. Главное — не забывайте про документацию и тесты. Тогда ваше расширение будет полезным и востребованным.
Если вы хотите, чтобы ваш код стал популярным, опубликуйте его на Packagist и расскажите о нем в сообществе Yii. Удачи в разработке!

