Yii2 Events & Behaviors

  Add to Bookmark

Yii2 provides a powerful event-driven programming model and behavior system, allowing developers to extend functionality without modifying core code. Events enable objects to communicate in a loosely coupled manner, while behaviors allow attaching reusable functionality to components dynamically.


1. Yii2 Events

Yii2’s event system allows objects to trigger and respond to specific actions.

1.1 Registering and Triggering Events

Yii2 uses on() to attach event handlers and trigger() to fire events.

Example: Defining a Custom Event

class User extends \yii\base\Component
{
    const EVENT_NEW_USER_REGISTERED = 'newUserRegistered';

    public function register()
    {
        // Simulate user registration process
        echo "User registered successfully.\n";

        // Trigger the event
        $this->trigger(self::EVENT_NEW_USER_REGISTERED);
    }
}

// Create an instance
$user = new User();

// Attach an event handler
$user->on(User::EVENT_NEW_USER_REGISTERED, function () {
    echo "Sending welcome email...\n";
});

// Register user (this will trigger the event)
$user->register();

1.2 Passing Event Data

Sometimes, you may need to pass additional data when triggering an event.

class Order extends \yii\base\Component
{
    const EVENT_ORDER_PLACED = 'orderPlaced';

    public function placeOrder($orderId)
    {
        echo "Order #{$orderId} placed successfully.\n";

        // Trigger event with event data
        $this->trigger(self::EVENT_ORDER_PLACED, new \yii\base\Event(['data' => ['orderId' => $orderId]]));
    }
}

// Attach an event handler
$order = new Order();
$order->on(Order::EVENT_ORDER_PLACED, function ($event) {
    echo "Generating invoice for Order ID: " . $event->data['orderId'] . "\n";
});

// Place order
$order->placeOrder(101);

1.3 Detaching and Checking Events

You can remove event handlers using off() and check if an event is attached with hasEventHandlers().

$order->off(Order::EVENT_ORDER_PLACED);
if (!$order->hasEventHandlers(Order::EVENT_ORDER_PLACED)) {
    echo "No event handlers attached to ORDER_PLACED.\n";
}

2. Yii2 Behaviors

Behaviors allow you to extend the functionality of Yii components dynamically.

2.1 Creating and Attaching Behaviors

Behaviors can be attached at runtime or declared within a model.

Example: Timestamp Behavior

class TimestampBehavior extends \yii\base\Behavior
{
    public function events()
    {
        return [
            ActiveRecord::EVENT_BEFORE_INSERT => 'beforeInsert',
        ];
    }

    public function beforeInsert($event)
    {
        $this->owner->created_at = time();
    }
}

// Apply behavior to a model
class Post extends \yii\db\ActiveRecord
{
    public function behaviors()
    {
        return [
            TimestampBehavior::class,
        ];
    }
}

2.2 Dynamic Behavior Attachment

You can attach behaviors at runtime.

$post = new Post();
$post->attachBehavior('timestamp', new TimestampBehavior());

2.3 Using Built-in Yii2 Behaviors

Yii2 provides built-in behaviors such as:

TimestampBehavior

Automatically sets created and updated timestamps.

use yii\behaviors\TimestampBehavior;

class User extends \yii\db\ActiveRecord
{
    public function behaviors()
    {
        return [
            [
                'class' => TimestampBehavior::class,
                'attributes' => [
                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
                    ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
                ],
            ],
        ];
    }
}

BlameableBehavior

Tracks which user created or updated a record.

use yii\behaviors\BlameableBehavior;

class Post extends \yii\db\ActiveRecord
{
    public function behaviors()
    {
        return [
            BlameableBehavior::class,
        ];
    }
}

SluggableBehavior

Automatically generates URL-friendly slugs.

use yii\behaviors\SluggableBehavior;

class Article extends \yii\db\ActiveRecord
{
    public function behaviors()
    {
        return [
            [
                'class' => SluggableBehavior::class,
                'attribute' => 'title',
                'slugAttribute' => 'slug',
            ],
        ];
    }
}

3. Real-World Example: Events & Behaviors in a User Registration System

Imagine a system where:

  • When a user registers, an event is triggered.
  • A behavior automatically sets created_at and updated_at.

User Model with Events and Behaviors

class User extends \yii\db\ActiveRecord
{
    const EVENT_USER_REGISTERED = 'userRegistered';

    public function behaviors()
    {
        return [
            TimestampBehavior::class,
        ];
    }

    public function register()
    {
        if ($this->save()) {
            $this->trigger(self::EVENT_USER_REGISTERED);
        }
    }
}

Attaching Event Listeners in a Component

Yii::$app->on(User::EVENT_USER_REGISTERED, function ($event) {
    echo "Sending welcome email to User ID: " . $event->sender->id;
});

4. Yii2 Console Commands with Events

You can integrate events in Yii2 console commands.

namespace app\commands;

use yii\console\Controller;
use app\models\User;

class UserController extends Controller
{
    public function actionRegister($email)
    {
        $user = new User(['email' => $email]);
        $user->on(User::EVENT_USER_REGISTERED, function () use ($user) {
            echo "Console: Sending welcome email to {$user->email}\n";
        });

        if ($user->register()) {
            echo "User Registered Successfully.\n";
        }
    }
}

Run in terminal:

php yii user/register example@mail.com

5. Using Events & Behaviors in Modules

5.1 Registering Events in Module

Inside Module.php:

namespace app\modules\dashboard;

use Yii;
use yii\base\BootstrapInterface;
use app\models\User;

class Module extends \yii\base\Module implements BootstrapInterface
{
    public function bootstrap($app)
    {
        User::on(User::EVENT_USER_REGISTERED, function ($event) {
            echo "Module: User Registered Event Triggered.";
        });
    }
}

5.2 Registering Console Commands for a Module

Modify config/console.php:

return [
    'bootstrap' => ['dashboard'],
    'modules' => [
        'dashboard' => [
            'class' => 'app\modules\dashboard\Module',
        ],
    ],
];

Modify Module.php:

if (Yii::$app->request->isConsoleRequest) {
    \Yii::configure($this, ['controllerNamespace' => 'app\modules\dashboard\commands']);
}

Conclusion

Yii2’s Events & Behaviors provide a powerful way to extend application functionality without modifying core logic. By leveraging events, you can create loosely coupled systems, and with behaviors, you can dynamically add reusable features to components.