행동 정의
동작을 정의하려면 yiibaseBehavior 또는 해당 하위 클래스를 상속하여 클래스를 만듭니다. 예:
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() { // ... } }
위 코드는 동작 클래스 appcomComponentsMyBehavior를 정의하고 동작이 연결될 구성 요소에 대해 두 가지 속성 prop1, prop2 및 foo() 메서드를 제공합니다. prop2 속성은 getter getProp2() 및 setter setProp2()를 통해 정의됩니다. yiibaseObject는 yiibaseBehavior의 조상 클래스이기 때문에 이런 방식으로 사용할 수 있습니다. 이 조상 클래스는 getter 및 setter 메서드를 사용하여 속성 정의를 지원합니다
팁: 동작 내에서 yiibaseBehavior::owner 속성을 통해 동작이 연결된 구성 요소에 액세스할 수 있습니다.
정적 메서드 바인딩 동작
동작을 정적으로 바인딩하려면 yiibaseComponent::behaviors()만 오버로드하면 됩니다. 이 메서드는 클래스의 동작을 설명하는 데 사용됩니다. 그것을 설명하는 방법? Behavior 클래스 이름 또는 Behavior 클래스의 구성 배열일 수 있는 구성을 사용하여 설명합니다.
namespace app\models; use yii\db\ActiveRecord; use app\Components\MyBehavior; class User extends ActiveRecord { public function behaviors() { return [ // 匿名的行为,仅直接给出行为的类名称 MyBehavior::className(), // 名为myBehavior2的行为,也是仅给出行为的类名称 'myBehavior2' => MyBehavior::className(), // 匿名行为,给出了MyBehavior类的配置数组 [ 'class' => MyBehavior::className(), 'prop1' => 'value1', 'prop3' => 'value3', ], // 名为myBehavior4的行为,也是给出了MyBehavior类的配置数组 'myBehavior4' => [ 'class' => MyBehavior::className(), 'prop1' => 'value1', 'prop3' => 'value3', ] ]; } }
구성 파일을 통해 바인딩하는 정적 바인딩 방법도 있습니다.
[ 'as myBehavior2' => MyBehavior::className(), 'as myBehavior3' => [ 'class' => MyBehavior::className(), 'prop1' => 'value1', 'prop3' => 'value3', ], ]
동적 메서드 바인딩 동작
동적 바인딩 동작은 yiibaseComponent::attachBehaviors():
를 호출해야 합니다.$Component->attachBehaviors([ 'myBehavior1' => new MyBehavior, // 这是一个命名行为 MyBehavior::className(), // 这是一个匿名行为 ]);
이 메소드는 배열 매개변수를 허용하며, 매개변수의 의미는 위의 정적 바인딩 동작과 동일합니다.
위의 예에서는 배열의 키가 동작의 이름으로 사용되며, 키 이름을 제공하지 않는 동작은 익명의 동작입니다.
이름이 지정된 동작의 경우 yiibaseComponent::getBehavior()를 호출하여 바인딩된 동작을 가져올 수 있습니다.
$behavior = $Component->getBehavior('myBehavior2');
익명 활동의 경우 직접 인용할 수 있는 방법이 없습니다. 그러나 모든 바인딩된 동작을 얻을 수 있습니다.
$behaviors = $Component->getBehaviors();
제본 내부 원칙
yiibaseComponent::behaviors()를 오버로드하기만 하면 동작을 마술처럼 사용할 수 있나요? 이는 빙산의 일각에 불과합니다. 실제로 관련 측면은 다음과 같습니다.
yii\base\Component::behaviors() yii\base\Component::ensureBehaviors() yii\base\Component::attachBehaviorInternal() yii\base\Behavior::attach()
동작은 네 가지 메소드 중 하나만 설명하며, 더 많은 코드가 컴포넌트에서 완성됩니다.
yiibaseComponent::behaviors() 정적 메서드 바인딩 동작에 관해 위에서 언급한 것처럼 동작을 설명하는 배열을 반환합니다. yiibaseComponent::ensuerBehaviors()는 어떻습니까?
이 메서드는 구성 요소의 여러 위치에서 사용될 때 __get() __set() __isset() __unset() __call() canGetProperty() hasMethod() hasEventHandlers() on() off() 등을 호출합니다. 두통인가요? 한마디로 이 함수는 클래스의 속성, 메소드 및 이벤트를 포함하는 한 호출됩니다.
그렇게 많은 사람들에게 필요한sureBehaviors()는 누구입니까? 이름에서 알 수 있듯이 그의 역할은 "보장"입니다. 실제로는 Behaviors()에 설명된 동작이 바인딩되었는지 확인하기 위한 것입니다.
public function ensureBehaviors() { // 为null表示尚未绑定 // 多说一句,为空数组表示没有绑定任何行为 if ($this->_behaviors === null) { $this->_behaviors = []; // 遍历 $this->behaviors() 返回的数组,并绑定 foreach ($this->behaviors() as $name => $behavior) { $this->attachBehaviorInternal($name, $behavior); } } }
이 메서드는 주로 하위 클래스에 사용됩니다. yiibaseComponent에는 사전 주입 동작이 없으므로 이 호출은 쓸모가 없습니다. 그러나 하위 클래스의 경우 일부 동작을 미리 주입하기 위해 yiibaseComponent::behaviros()를 오버로드할 수 있습니다. 그런 다음 이 함수는 이러한 동작을 먼저 주입합니다.
위 코드를 보면 다음으로 이야기할 세 번째 항목인 yiibaseComponentattachBehaviorInternal():
이 자연스럽게 보입니다.private function attachBehaviorInternal($name, $behavior) { // 不是 Behavior 实例,说是只是类名、配置数组,那么就创建出来吧 if (!($behavior instanceof Behavior)) { $behavior = Yii::createObject($behavior); } // 匿名行为 if (is_int($name)) { $behavior->attach($this); $this->_behaviors[] = $behavior; // 命名行为 } else { // 已经有一个同名的行为,要先解除,再将新的行为绑定上去。 if (isset($this->_behaviors[$name])) { $this->_behaviors[$name]->detach(); } $behavior->attach($this); $this->_behaviors[$name] = $behavior; } return $behavior; }
가장 먼저 주목해야 할 점은 비공개 회원이라는 점입니다. 실제로 Yii에서는 접미사 *Internal이 붙은 모든 메소드가 비공개입니다. 이 방법은 다음 작업을 수행합니다.
$behavior 매개변수가 Behavior 인스턴스가 아닌 경우 이를 매개변수로 사용하고 Yii::createObject()를 사용하여 생성하세요.
동작을 익명 동작으로 바인딩하는 경우 해당 동작을 이 클래스에 직접 연결하세요.
이름이 지정된 동작인 경우 먼저 이 클래스에 이미 바인딩된 동일한 이름의 동작이 있는지 확인하세요. 그렇다면 이전 동작을 이후 동작으로 바꾸세요.
yiibaseComponent::attachBehaviorInternal()에서 yiibaseBehavior::attach()는 $this를 매개변수로 사용하여 호출됩니다. 따라서 바인딩과 관련된 마지막 사항인 yiibaseBehavior::attach()가 소개되는데, 이는 앞서 동작의 요소에 대해 이야기할 때 이야기를 마치지 못한 것입니다. 먼저 코드를 살펴보겠습니다.
public function attach($owner) { $this->owner = $owner; foreach ($this->events() as $event => $handler) { $owner->on($event, is_string($handler) ? [$this, $handler] : $handler); } }
위 코드는 두 가지 작업을 수행합니다.
요약
이제 바인딩에 대해 요약해 보겠습니다.