Behavior | core architecture | Yii Chinese document 2.0.x

Posted by chmpdog on Fri, 04 Feb 2022 04:34:01 +0100

behavior

Behavior is an instance of yii\base\Behavior or its subclass. Behavior, also known as mixins , you can enhance the function of an existing yii\base\Component component class without changing the class inheritance relationship. When a behavior is attached to a component, it "injects" its methods and properties into the component, and then accesses them as if they were defined within the component. In addition, the behavior can respond to triggered events through components event To customize or adjust the code normally executed by the component.

Define behavior

To define behavior, create a class by inheriting yii\base\Behavior or its subclasses. For example:

namespace app\components;

use yii\base\Behavior;

class MyBehavior extends Behavior
{
    public $prop1;

    private $_prop2;

    public function getProp2()
    {
        return $this->_prop2;
    }

    public function setProp2($value)
    {
        $this->_prop2 = $value;
    }

    public function foo()
    {
        // ...
    }
}

The above code defines the behavior class app\components\MyBehavior and provides two properties prop1, prop2 and a method foo() for the component to which the behavior is to be attached. Note that the property prop2 is defined through getter getProp2() and setter setProp2(). This is because yii\base\Object is the ancestor class of yii\base\Behavior. This ancestor class supports the definition of getter and setter methods attribute

Because this is a behavior class, when it is attached to a component, the component will also have prop1 and prop2 properties and foo() methods.

Tip: inside the behavior, you can access the attached components of the behavior through the [[yii\base\Behavior::owner]] attribute.

Note: if [[yii\base\Behavior::get()]] and or [[yii\base\Behavior::set()]] behavior methods are overwritten, you need to override [[yii\base\Behavior::canGetProperty()]] and or [[yii\base\Behavior::canSetProperty()]].

Handling events

If you want the behavior to respond to the event trigger of the corresponding component, you should override the [[yii\base\Behavior::events()]] method, such as:

namespace app\components;

use yii\db\ActiveRecord;
use yii\base\Behavior;

class MyBehavior extends Behavior
{
    // Other codes

    public function events()
    {
        return [
            ActiveRecord::EVENT_BEFORE_VALIDATE => 'beforeValidate',
        ];
    }

    public function beforeValidate($event)
    {
        // Processor method logic
    }
}

The [[yii\base\Behavior::events()]] method returns the event list and the corresponding processor. The above example declares the [[yii\db\ActiveRecord::EVENT_BEFORE_VALIDATE]] event and its processor beforeValidate(). When specifying an event handler, use one of the following formats:

  • A string pointing to the method name of the behavior class, as shown in the above example;
  • An array of object or class names and method names, such as [$object, 'methodName'];
  • Anonymous method.

The format of the processor is as follows, where $event points to the event parameter. For more details about the event, please refer to event:

function ($event) {
}

Additional behavior

You can attach behaviors to yii\base\Component components statically or dynamically. The former is more common in practice.

To attach the behavior statically, override the [[yii\base\Component::behaviors()]] method of the component class to be attached. The [[yii\base\Component::behaviors()]] method should return behavior to configure List. Each behavior configuration can be a behavior class name or a configuration array. For example:

namespace app\models;

use yii\db\ActiveRecord;
use app\components\MyBehavior;

class User extends ActiveRecord
{
    public function behaviors()
    {
        return [
            // Anonymous behavior, only behavior class name
            MyBehavior::class,

            // Named behavior, only behavior class name
            'myBehavior2' => MyBehavior::class,

            // Anonymous behavior, configuring arrays
            [
                'class' => MyBehavior::class,
                'prop1' => 'value1',
                'prop2' => 'value2',
            ],

            // Naming behavior, configuring arrays
            'myBehavior4' => [
                'class' => MyBehavior::class,
                'prop1' => 'value1',
                'prop2' => 'value2',
            ]
        ];
    }
}

You can associate a name with a behavior by specifying the corresponding key of the behavior configuration array. This behavior is called naming behavior. In the above example, there are two naming behaviors: myBehavior2 and myBehavior4. If the behavior does not specify a name, it is anonymous.

To dynamically attach behavior, call the [[yii\base\Component::attachBehavior()]] method in the corresponding component, such as:

use app\components\MyBehavior;

// Attach behavior object
$component->attachBehavior('myBehavior1', new MyBehavior);

// Additional behavior class
$component->attachBehavior('myBehavior2', MyBehavior::class);

// Additional configuration array
$component->attachBehavior('myBehavior3', [
    'class' => MyBehavior::class,
    'prop1' => 'value1',
    'prop2' => 'value2',
]);

You can attach multiple behaviors at one time through the [[yii\base\Component::attachBehaviors()]] method:

$component->attachBehaviors([
    'myBehavior1' => new MyBehavior,  // Naming behavior
    MyBehavior::class,          // Anonymous behavior
]);

You can also pass to configure De attach behavior:

[
    'as myBehavior2' => MyBehavior::class,

    'as myBehavior3' => [
        'class' => MyBehavior::class,
        'prop1' => 'value1',
        'prop2' => 'value2',
    ],
]

For details, please refer to to configure Chapter.

Usage behavior

To use behavior, you must first attach it to the yii\base\Component class or its subclasses as described above. Once a behavior is attached to a component, it can be used directly.

After the behavior is attached to the component, the public member variable of a behavior or the defined by getter and setter methods can be accessed through the component attribute:

// "prop1" is an attribute defined in the behavior class
echo $component->prop1;
$component->prop1 = $value;

Similarly, you can call public methods of behavior:

// foo() is a public method defined in the behavior class
$component->foo();

As you can see, although $component does not define prop1 and foo(), they are used as defined by the component itself.

If both behaviors define the same property or method and they are attached to the same component, the behavior attached first has priority when the property or method is accessed.

The named behavior when attaching a behavior to a component. You can use this name to access the behavior object, as shown below:

$behavior = $component->getBehavior('myBehavior');

You can also get all the behaviors attached to this component:

$behaviors = $component->getBehaviors();

Remove behavior

To remove the behavior, you can call the [[yii\base\Component::detachBehavior()]] method and implement it with the name associated with the behavior:

$component->detachBehavior('myBehavior1');

You can also remove all behaviors:

$component->detachBehaviors();

Using TimestampBehavior

Finally, it ends with the explanation of yii\behaviors\TimestampBehavior. This behavior supports the automatic update of yii\db\ActiveRecord's timestamp attribute when it is stored.

First, attach this behavior to the yii\db\ActiveRecord activity record class that plans to use it:

namespace app\models\User;

use yii\db\ActiveRecord;
use yii\behaviors\TimestampBehavior;

class User extends ActiveRecord
{
    // ...

    public function behaviors()
    {
        return [
            [
                'class' => TimestampBehavior::class,
                'attributes' => [
                    ActiveRecord::EVENT_BEFORE_INSERT => ['created_at', 'updated_at'],
                    ActiveRecord::EVENT_BEFORE_UPDATE => ['updated_at'],
                ],
                // if you're using datetime instead of UNIX timestamp:
                // 'value' => new Expression('NOW()'),
            ],
        ];
    }
}

The behavior array specified above:

  • When a record is inserted, the behavior assigns the current timestamp to created_at and updated_at attribute;
  • When the record is updated, the behavior assigns the current timestamp to updated_at attribute.

Note: for the above implementation using MySQL database, please define the column (created_at, updated_at) as int(11) as UNIX timestamp.

If you try to save more than one piece of User created code, you will find it_ At and updated_at is automatically populated by the current UNIX timestamp:

$user = new User;
$user->email = 'test@example.com';
$user->save();
echo $user->created_at;  // Displays the current timestamp

The [[yii\behaviors\TimestampBehavior]] behavior also provides a useful method [[yii\behaviors\TimestampBehavior::touch()]], which can assign the current timestamp to the specified attribute and save it to the database:

$user->touch('login_time');

Other behavior

Several built-in and external behaviors are available:

  • [[yii\behaviors\BlameableBehavior]] - automatically populate the specified attributes with the current user ID.
  • [[yii\behaviors\SluggableBehavior]] - automatically populates the specified attribute whose value can be used as a slug in the URL.
  • [[Yii \ behaviors \ attributevideo] - automatically specify a specified value for one or more attributes of the ActiveRecord object when a specific event occurs.
  • yii2tech\ar\softdelete\SoftDeleteBehavior -Provides methods for soft deletion and soft recovery of ActiveRecord. The setting or status that marks the record as deleted.
  • yii2tech\ar\position\PositionBehavior -Allows you to manage the order of records in integer fields by providing a reordering method.

Compare behavior with Traits

Although the behavior is similar to traits , they all "inject" their own properties and methods into the main class, but they are different in many ways. As described below, they all have advantages and disadvantages. They are more like complementary classes than alternative classes.

Reasons for using behavior

Behavior classes support inheritance like normal classes. On the other hand, traits can be regarded as a copy and paste function supported by PHP language, which does not support inheritance.

Behaviors can be dynamically attached to or removed from components without modifying component classes. To use traits, you must modify the class that uses it.

Behavior is configurable, while traits is not feasible.

Behavior can customize the code execution of components by responding to events.

When there may be name conflicts between different behaviors attached to the same component, the conflicts are automatically resolved by giving priority to the behaviors attached to the component. Name conflicts caused by different traits need to be resolved manually by renaming the affected attributes or methods.

Reasons for using Traits

Traits are more effective than behavior, because behavior is an object that requires both time and memory.

Because ides are a native language structure, they are more friendly to Traits.

💖 Those who like this document are welcome to like, collect, leave a message or forward it. Thank you for your support! Author email: zhuzixian520@126.com

This article was first published in LearnKu.com On the website.