Custom widgets in Yii2 allow developers to create reusable UI components, improving code modularity and maintainability. Yii2 provides a powerful Widget class that makes it easy to build custom widgets with configurable properties and dynamic rendering capabilities.
In widgets/GreetingWidget.php, create a simple widget that displays a greeting message:
namespace app\widgets;
use yii\base\Widget;
use yii\helpers\Html;
class GreetingWidget extends Widget
{
public $message;
public function init()
{
parent::init();
if ($this->message === null) {
$this->message = 'Hello, Guest!';
}
}
public function run()
{
return Html::tag('h3', Html::encode($this->message), ['class' => 'greeting-message']);
}
}use app\widgets\GreetingWidget;
// Basic usage
echo GreetingWidget::widget();
// With a custom message
echo GreetingWidget::widget(['message' => 'Welcome to Yii2!']);To create a more advanced widget, let's build an Alert Widget that displays flash messages from the session.
In widgets/Alert.php, define the widget:
namespace app\widgets;
use Yii;
use yii\base\Widget;
class Alert extends Widget
{
public $alertTypes = [
'error' => 'error',
'danger' => 'error',
'success' => 'success',
'info' => 'info',
'warning' => 'warning'
];
public function run()
{
$session = Yii::$app->session;
$flashes = $session->getAllFlashes();
foreach ($flashes as $type => $flash) {
if (!isset($this->alertTypes[$type])) {
continue;
}
foreach ((array) $flash as $message) {
return "<script>notif({ type: '{$this->alertTypes[$type]}', msg: '{$message}', position: 'right' });</script>";
}
$session->removeFlash($type);
}
}
}To use the notif() function, include the CDN in your layout file (layouts/main.php):
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/notifit/1.0.0/notifit.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/notifit/1.0.0/notifit.min.css">
</head>In layouts/main.php, include the widget:
use app\widgets\Alert;
<?= Alert::widget(); ?>Now, whenever you set a flash message in the controller:
Yii::$app->session->setFlash('success', 'Your action was successful!');The widget will automatically display the message in the view using modern alert popups.
Components in Yii2 extend core functionalities by providing reusable logic that can be used across the application. Here, we will build a custom log target and a WhatsApp notification system.
This log target will send log messages to WhatsApp.
WhatsappLogTarget.phpnamespace app\packages\components;
use Yii;
use yii\log\Target;
use yii\log\LogRuntimeException;
class WhatsappLogTarget extends Target
{
public $except = [
'yii\web\HttpException:404',
'yii\web\HttpException:400',
];
public function export()
{
$text = implode("\n", array_map([$this, 'formatMessage'], $this->messages)) . "\n";
$message_text = '';
if (isset($_SERVER['SERVER_NAME'])) {
$message_text .= 'SERVER_NAME : ' . $_SERVER['SERVER_NAME'] . PHP_EOL;
} else {
if (isset(Yii::$app->params['baseurl'])) {
$message_text .= 'Project Name : ' . Yii::$app->params['baseurl'] . PHP_EOL;
} else {
$message_text .= 'PWD : ' . $_SERVER['PWD'] . PHP_EOL;
}
}
$message_text .= PHP_EOL . 'Error Summary: ' . PHP_EOL;
$message_text .= $text;
\Yii::$app->WhatsappNotification
->setMessageBody($message_text)
->setNoticeModule('weblogtarget')
->setActionRoute('systemlog')
->sendMessage();
}
}config/web.php'components' => [
'log' => [
'targets' => [
[
'class' => 'app\packages\components\WhatsappLogTarget',
'levels' => ['error', 'warning'],
],
],
],
],Now, all errors and warnings will be sent to WhatsApp.
This component sends notifications to WhatsApp via an API.
WhatsappNotification.phpnamespace app\packages\components;
use Yii;
use app\models\WhatsappNotificationLog;
class WhatsappNotification extends \yii\base\Component
{
private $_ENABLE_NOTIFICATION = false;
private $_API_URL;
private $_API_BEARER_TOKEN;
private $_DEFAULT_MOBILE_NUMBER;
private $_RECIPIENT_MOBILE_NUMBER;
private $_messageBody;
private $_actionRoute;
private $_module = 'core';
public function init()
{
$this->_ENABLE_NOTIFICATION = Yii::$app->params['whatsapp_notification_enable'];
$this->_API_URL = Yii::$app->params['whatsapp_api_url'];
$this->_API_BEARER_TOKEN = Yii::$app->params['whatsapp_api_bearer_token'];
$this->_DEFAULT_MOBILE_NUMBER = Yii::$app->params['whatsapp_api_mobile_number'];
}
public function sendMessage()
{
if (!$this->_ENABLE_NOTIFICATION) return;
$data = $this->prepareMessageData();
$api_response = '';
if (!empty($this->_API_BEARER_TOKEN) && !empty($this->_API_URL)) {
$data_string = json_encode($data);
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $this->_API_URL,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => $data_string,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $this->_API_BEARER_TOKEN,
],
]);
$api_response = curl_exec($curl);
curl_close($curl);
}
return $this->saveMessageLog($data, $api_response);
}
public function setRecipientMobileNumber($value)
{
$this->_RECIPIENT_MOBILE_NUMBER = $value;
return $this;
}
public function setMessageBody($body)
{
$this->_messageBody = $body;
return $this;
}
public function setActionRoute($value)
{
$this->_actionRoute = $value;
return $this;
}
public function setNoticeModule($module)
{
$this->_module = $module;
return $this;
}
private function prepareMessageData()
{
return [
"messaging_product" => 'whatsapp',
'recipient_type' => 'individual',
'to' => $this->_RECIPIENT_MOBILE_NUMBER ?? $this->_DEFAULT_MOBILE_NUMBER,
"type" => 'text',
'text' => ['preview_url' => false, 'body' => $this->_messageBody],
];
}
private function saveMessageLog($sent_data, $result)
{
$log = new WhatsappNotificationLog();
$log->module = $this->_module;
$log->action = $this->_actionRoute;
$log->recipient_mobile_number = $this->_RECIPIENT_MOBILE_NUMBER ?? $this->_DEFAULT_MOBILE_NUMBER;
$log->message_body = json_encode($sent_data);
$log->response = $result;
$log->created_at = time();
$log->save();
return $log;
}
}\Yii::$app->WhatsappNotification
->setMessageBody('Your order has been shipped!')
->setNoticeModule('order')
->setActionRoute('shipping')
->sendMessage();
Sign in to join the discussion and post comments.
Sign in