miércoles, 21 de enero de 2015

Comportamientos (Behaviors)

Los comportamientos son instancias de  yii\base\Behavior, o de una clase hija. Los comportamientos, también conocidos como mixins, permiten mejorar la funcionalidad de un componente existente sin necesidad de cambiar la herencia de la clase. Adjuntando un comportamiento a un componente se le "inyectan" los métodos y propiedades del comportamiento, se logra que esos métodos y propiedades accesibles como si estuvieran definidos en la propia clase componente. Por otra parte, un comportamiento puede responder a los acontecimientos desencadenados por el componente, que permite a los comportamientos para personalizar también la ejecución normal de código del componente.

Definiendo Comportamientos

Para definir un comportamiento, se debe crear una clase de yii\base\Behavior, o en su defecto, de una clase hija de la misma. Por ejemplo:

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()
    {
        // ...
    }
}

El código presentado define una clase Comportamiento app\components\MyBehavior con dos propiedades, con dos propiedades y un método (prop1, prop2, foo), Nótese que la propiedad prop2 se define a través del captador getProp2 y el definidor setProp2(). Esto se debe a que  yii\base\Behavior se extiende de yii\base\Object y por lo tanto soporta la definición de propiedades a través de captadores (getter) y definidores (setter).

Debido a que ésta clase es un comportamiento (behavior), cuando sea añadido a un componente, el componente también tendrá las propiedades prop1 y prop2 y el método foo().

Consejo: Dentro del comportamiento, se puede acceder al componente al cual está adjunto, a través de la propiedad yii\base\Behavior::$owner

Gestionando Eventos de Componentes

Si un comportamiento necesita responder a los eventos disparados por el componente al cual está unido, se debe sobrescribir el método yii\base\Behavior::events(). Por ejemplo:

namespace app\components;

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

class MyBehavior extends Behavior{
    // ...

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

    public function beforeValidate($event)
    {
        // ...
    }
}

El método events() debe retornar una lista de eventos y sus correspondientes controladores. El ejemplo anterior declara que el evento EVENT_BEFORE_VALIDATE existe y define su controlador  beforeValidate(). Al especificar un controlador de eventos, se puede utilizar uno de los siguientes formatos:

  • una cadena que se refiere al nombre de un método de la clase comportamiento, como en el ejemplo anterior
  • un arreglo de un objeto o nombre de clase, y un nombre de método como una cadena (sin paréntesis), por ejemplo, [$object, 'methodName'];
  • una función anónima

La firma de un controlador de eventos es la siguiente,

function ($event) {
}

donde $event se refiere al parámetro del evento.

Adjuntando Comportamientos

Se puede adjuntar un comportamiento de forma estática o dinámica. La primera opción es la más común.

Para adjuntar un comportamiento de manera estática, se debe sobrescribir el método behaviors() de la clase componente al que se adjunta el comportamiento. El método behaviors()debe devolver una lista de configuraciones del comportamiento. Cada configuración del comportamiento puede ser un nombre de clase comportamiento o un arreglo de configuración:

namespace app\models;

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

class User extends ActiveRecord{
    public function behaviors()
    {
        return [
            // comportamiento anónimo, sólo nombre de la clase
            MyBehavior::className(),

            // comportamiento con nombre, sólo nombre de la clase
            'myBehavior2' => MyBehavior::className(),

            // comportamiento anónimo, arreglo de configuración
            [
                'class' => MyBehavior::className(),
                'prop1' => 'value1',
                'prop2' => 'value2',
            ],

            // comportamiento con nombre, arreglo de configuración
            'myBehavior4' => [
                'class' => MyBehavior::className(),
                'prop1' => 'value1',
                'prop2' => 'value2',
            ]
        ];
    }
}

Se puede asociar un nombre con un comportamiento especificando la clave del arreglo correspondiente a la configuración del comportamiento. En este caso, el comportamiento se denomina un comportamiento con nombre. En el ejemplo anterior, hay dos comportamientos con nombre: myBehavior2 y myBehavior4 . Si un comportamiento no está asociado con un nombre, se llama un comportamiento anónimo.

Para adjuntar un comportamiento dinámicamente, hay que llamar al método yii\base\Component::attachBehavior() de el componente al que se adjunta el comportamiento:

use app\components\MyBehavior;
// adjunta un objeto comportamiento
$component->attachBehavior('myBehavior1', new MyBehavior);
// adjunta una clase comportamiento
$component->attachBehavior('myBehavior2'MyBehavior::className());
// adjunta una arreglo de configuración
$component->attachBehavior('myBehavior3', [
    'class' => MyBehavior::className(),
    'prop1' => 'value1',
    'prop2' => 'value2',
]);

Se puede adjuntar múltiples comportamientos de una sola vez usando el método yii\base\Component::attachBehaviors():

$component->attachBehaviors([
    'myBehavior1' => new MyBehavior,  // un comportamiento con nombre
    MyBehavior::className(),          // un comportamiento anónimo
]);

También se puede adjuntar comportamientos a través de configuración:

[
    'as myBehavior2' => MyBehavior::className(),

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

Utilizando Comportamientos

Para utilizar un comportamiento, primero hay que adjuntarlo a un componente de acuerdo a lo descrito anteriormente. Una vez que el comportamiento se ha adjuntado al componente, la utilización es simple.

Se puede acceder a una variable miembro pública o una propiedad definida por un captador (getter) y/o definidor (setter):

// "prop1" is una propiedad definida en la clase comportamiento
echo $component->prop1;$component->prop1 $value;

También se puede llamar a un método público de manera similar:

// foo() is a método público definido en la clase comportamiento
$component->foo();

Como se puede ver, a pesar que $component no define ni prop1 ni foo(), pueden ser usados como parte de la definición del componente debido al comportamiento (behavior) que se ha adjuntado.

Si dos comportamientos definen la misma propiedad o método y ambos están unidos a un mismo componente, el comportamiento que se une al componente primero tendrá prioridad cuando se accede a la propiedad o método.

Un comportamiento puede estar asociado con un nombre cuando está unido a un componente. Si este es el caso, se puede acceder al objeto comportamiento utilizando el nombre:

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

También se puede obtener todos los comportamientos adjunto a un componente:

$behaviors $component->getBehaviors();

Separando Comportamientos

Para separar un comportamiento, se debe llamar a yii\base\Component::detachBehavior() con el nombre asociado al comportamiento:

$component->detachBehavior('myBehavior1');

También se puede separar todos los comportamientos:

$component->detachBehaviors();



También te puede interesar:
Definición de un mixin
Configuraciones
Eventos
Propiedades
Componentes

No hay comentarios.:

Publicar un comentario

Nota: sólo los miembros de este blog pueden publicar comentarios.