백엔드 개발 PHP 튜토리얼 Yii2--yiibaseEvent 클래스 심층 학습

Yii2--yiibaseEvent 클래스 심층 학습

Jul 29, 2016 am 09:08 AM
class event handler name the

根据之前一篇文章,我们知道 Yii2 的事件分两类,一是类级别的事件,二是实例级别的事件。类级别的事件是基于 yii\base\Event 实现,实例级别的事件是基于 yii\base\Component 实现。

今天先来看下类级别事件的实现,代码是 yii\base\Event 类。

<?<span>php
namespace yii\base;

</span><span>/*</span><span>*
 * Event is the base class for all event classes.
 </span><span>*/</span><span>class</span> Event <span>extends</span><span>Object</span><span>{
    </span><span>/*</span><span>*
     * @var string the event name. This property is set by [[Component::trigger()]] and [[trigger()]].
     * Event handlers may use this property to check what event it is handling.
     * 事件的名字
     </span><span>*/</span><span>public</span><span>$name</span><span>;
    </span><span>/*</span><span>*
     * @var object the sender of this event. If not set, this property will be
     * set as the object whose "trigger()" method is called.
     * This property may also be a `null` when this event is a
     * class-level event which is triggered in a static context.
     * 触发事件的对象
     </span><span>*/</span><span>public</span><span>$sender</span><span>;
    </span><span>/*</span><span>*
     * @var boolean whether the event is handled. Defaults to false.
     * When a handler sets this to be true, the event processing will stop and
     * ignore the rest of the uninvoked event handlers.
     * 记录事件是否已被处理,当 handled 被设置为 true 时,执行到这个 event 的时候,会停止,并忽略剩下的 event
     </span><span>*/</span><span>public</span><span>$handled</span> = <span>false</span><span>;
    </span><span>/*</span><span>*
     * @var mixed the data that is passed to [[Component::on()]] when attaching an event handler.
     * Note that this varies according to which event handler is currently executing.
     </span><span>*/</span><span>public</span><span>$data</span><span>;

    </span><span>/*</span><span>*
     * 存储所有的 event,因为是 static 的属性,所有的 event 对象/类都共享这一份数据
     </span><span>*/</span><span>private</span><span>static</span><span>$_events</span> =<span> [];


    </span><span>/*</span><span>*
     * Attaches an event handler to a class-level event.
     *
     * When a class-level event is triggered, event handlers attached
     * to that class and all parent classes will be invoked.
     *
     * For example, the following code attaches an event handler to `ActiveRecord`'s
     * `afterInsert` event:
     *
     * ~~~
     * Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
     *     Yii::trace(get_class($event->sender) . ' is inserted.');
     * });
     * ~~~
     *
     * The handler will be invoked for EVERY successful ActiveRecord insertion.
     *
     * For more details about how to declare an event handler, please refer to [[Component::on()]].
     *
     * 为一个类添加事件
     *
     * @param string $class the fully qualified class name to which the event handler needs to attach.
     * @param string $name the event name.
     * @param callable $handler the event handler.
     * @param mixed $data the data to be passed to the event handler when the event is triggered.
     * When the event handler is invoked, this data can be accessed via [[Event::data]].
     * @param boolean $append whether to append new event handler to the end of the existing
     * handler list. If false, the new handler will be inserted at the beginning of the existing
     * handler list.
     * @see off()
     <span>*/</span><span>public</span><span>static</span><span>function</span> on(<span>$class</span>, <span>$name</span>, <span>$handler</span>, <span>$data</span> = <span>null</span>, <span>$append</span> = <span>true</span><span>)
    {
        </span><span>//</span><span> 去掉 class 最左边的斜杠</span><span>$class</span> = <span>ltrim</span>(<span>$class</span>, '\\'<span>);
        </span><span>//</span><span> 如果 append 为true,就放到 $_events 中名字为 $name 的数组的最后,否则放到最前面</span><span>if</span> (<span>$append</span> || <span>empty</span>(self::<span>$_events</span>[<span>$name</span>][<span>$class</span><span>])) {
            self</span>::<span>$_events</span>[<span>$name</span>][<span>$class</span>][] = [<span>$handler</span>, <span>$data</span><span>];
        } </span><span>else</span><span> {
            </span><span>array_unshift</span>(self::<span>$_events</span>[<span>$name</span>][<span>$class</span>], [<span>$handler</span>, <span>$data</span><span>]);
        }
    }

    </span><span>/*</span><span>*
     * Detaches an event handler from a class-level event.
     *
     * This method is the opposite of [[on()]].
     *
     * 移除一个类的事件
     *
     * @param string $class the fully qualified class name from which the event handler needs to be detached.
     * @param string $name the event name.
     * @param callable $handler the event handler to be removed.
     * If it is null, all handlers attached to the named event will be removed.
     * @return boolean whether a handler is found and detached.
     * @see on()
     </span><span>*/</span><span>public</span><span>static</span><span>function</span> off(<span>$class</span>, <span>$name</span>, <span>$handler</span> = <span>null</span><span>)
    {
        </span><span>$class</span> = <span>ltrim</span>(<span>$class</span>, '\\'<span>);
        </span><span>if</span> (<span>empty</span>(self::<span>$_events</span>[<span>$name</span>][<span>$class</span><span>])) {
            </span><span>//</span><span> 不存在该事件</span><span>return</span><span>false</span><span>;
        }
        </span><span>if</span> (<span>$handler</span> === <span>null</span><span>) {
            </span><span>//</span><span> 如果 handler 为空,直接将在该类下该事件移除,即移出所有的是这个名字的事件</span><span>unset</span>(self::<span>$_events</span>[<span>$name</span>][<span>$class</span><span>]);
            </span><span>return</span><span>true</span><span>;
        } </span><span>else</span><span> {
            </span><span>$removed</span> = <span>false</span><span>;
            </span><span>//</span><span> 如果 $handler 不为空,循环 $_events 找到相应的 handler,只移除这个 handler 和 data 组成的数组</span><span>foreach</span> (self::<span>$_events</span>[<span>$name</span>][<span>$class</span>] <span>as</span><span>$i</span> => <span>$event</span><span>) {
                </span><span>if</span> (<span>$event</span>[0] === <span>$handler</span><span>) {
                    </span><span>unset</span>(self::<span>$_events</span>[<span>$name</span>][<span>$class</span>][<span>$i</span><span>]);
                    </span><span>$removed</span> = <span>true</span><span>;
                }
            }
            </span><span>if</span> (<span>$removed</span><span>) {
                </span><span>//</span><span> 移除之后,使数组重新变成一个自然数组</span>                self::<span>$_events</span>[<span>$name</span>][<span>$class</span>] = <span>array_values</span>(self::<span>$_events</span>[<span>$name</span>][<span>$class</span><span>]);
            }

            </span><span>return</span><span>$removed</span><span>;
        }
    }

    </span><span>/*</span><span>*
     * Returns a value indicating whether there is any handler attached to the specified class-level event.
     * Note that this method will also check all parent classes to see if there is any handler attached
     * to the named event.
     * 检测在某个类或者对象是否具有某个事件
     * @param string|object $class the object or the fully qualified class name specifying the class-level event.
     * @param string $name the event name.
     * @return boolean whether there is any handler attached to the event.
     </span><span>*/</span><span>public</span><span>static</span><span>function</span> hasHandlers(<span>$class</span>, <span>$name</span><span>)
    {
        </span><span>if</span> (<span>empty</span>(self::<span>$_events</span>[<span>$name</span><span>])) {
            </span><span>//</span><span> 不存在,直接返回</span><span>return</span><span>false</span><span>;
        }
        </span><span>if</span> (<span>is_object</span>(<span>$class</span><span>)) {
            </span><span>//</span><span> 如果是一个 object,就获取其类名</span><span>$class</span> = <span>get_class</span>(<span>$class</span><span>);
        } </span><span>else</span><span> {
            </span><span>//</span><span> 如果是一个类名,就去掉 class 最左边的斜杠</span><span>$class</span> = <span>ltrim</span>(<span>$class</span>, '\\'<span>);
        }
        </span><span>//</span><span> 如果该类中找不到,就去父类中找,直到找到或者没有父类了为止</span><span>do</span><span> {
            </span><span>if</span> (!<span>empty</span>(self::<span>$_events</span>[<span>$name</span>][<span>$class</span><span>])) {
                </span><span>return</span><span>true</span><span>;
            }
        } </span><span>while</span> ((<span>$class</span> = <span>get_parent_class</span>(<span>$class</span>)) !== <span>false</span><span>);

        </span><span>return</span><span>false</span><span>;
    }

    </span><span>/*</span><span>*
     * Triggers a class-level event.
     * This method will cause invocation of event handlers that are attached to the named event
     * for the specified class and all its parent classes.
     * 触发某个类或者对象的某个事件
     * @param string|object $class the object or the fully qualified class name specifying the class-level event.
     * @param string $name the event name.
     * @param Event $event the event parameter. If not set, a default [[Event]] object will be created.
     </span><span>*/</span><span>public</span><span>static</span><span>function</span> trigger(<span>$class</span>, <span>$name</span>, <span>$event</span> = <span>null</span><span>)
    {
        </span><span>if</span> (<span>empty</span>(self::<span>$_events</span>[<span>$name</span><span>])) {
            </span><span>return</span><span>;
        }
        </span><span>if</span> (<span>$event</span> === <span>null</span><span>) {
            </span><span>//</span><span> 事件不存在,就创建一个 Event 对象</span><span>$event</span> = <span>new</span><span>static</span><span>;
        }
        </span><span>//</span><span> 设置event对象的属性,默认是未被处理的</span><span>$event</span>->handled = <span>false</span><span>;
        </span><span>$event</span>->name = <span>$name</span><span>;

        </span><span>if</span> (<span>is_object</span>(<span>$class</span><span>)) {
            </span><span>if</span> (<span>$event</span>->sender === <span>null</span><span>) {
                </span><span>//</span><span> 如果 $class 是个对象,并且是 sender 为空,就将 $class 赋给 sender,即 $class 就是触发事件的对象</span><span>$event</span>->sender = <span>$class</span><span>;
            }
            </span><span>$class</span> = <span>get_class</span>(<span>$class</span><span>);
        } </span><span>else</span><span> {
            </span><span>$class</span> = <span>ltrim</span>(<span>$class</span>, '\\'<span>);
        }
        </span><span>//</span><span> 循环类的 $_event,直到遇到 $event->handled 为真或者没有父类了为止</span><span>do</span><span> {
            </span><span>if</span> (!<span>empty</span>(self::<span>$_events</span>[<span>$name</span>][<span>$class</span><span>])) {
                </span><span>foreach</span> (self::<span>$_events</span>[<span>$name</span>][<span>$class</span>] <span>as</span><span>$handler</span><span>) {
                    </span><span>//</span><span> 将参数赋到 event 对象的 data 属性上</span><span>$event</span>->data = <span>$handler</span>[1<span>];
                    </span><span>//</span><span> 调用 $handler 方法
                    // 在方法中,可以用 $this->data 取到相应的参数
                    // 也可以在其中设置 $this->handled 的值,中断后续事件的触发</span><span>call_user_func</span>(<span>$handler</span>[0], <span>$event</span><span>);
                    </span><span>//</span><span> 当某个 handled 被设置为 true 时,执行到这个事件的时候,会停止,并忽略剩下的事件</span><span>if</span> (<span>$event</span>-><span>handled) {
                        </span><span>return</span><span>;
                    }
                }
            }
        } </span><span>while</span> ((<span>$class</span> = <span>get_parent_class</span>(<span>$class</span>)) !== <span>false</span><span>);
    }
}</span>
로그인 후 복사

通过上面代码可以看出,类级别的 Event,其本质就是在 Event 类中的 $_events 变量中存储事件,触发事件的时候,只需将其取出,执行即可。

$_events里面的数据结构大概如下:

<span>[
    </span>'add' =><span> [
        </span>'Child' =><span> [
            [</span><span>function</span> (<span>$event</span>) { ... }, <span>$data</span>],<span>            [[</span><span>$object</span>, 'handleAdd'], <span>null</span>],<span>            [[</span>'ChildClass', 'handleAdd'], <span>$data</span>],<span>            [</span>'handleAdd', <span>$data</span><span>]
        ]</span>,
        'ChildClass' =><span> [
            </span>...<span>        ]
    ]</span>,
    'delete' =><span> [
        </span>...<span>    ]
]</span>
로그인 후 복사

之后讲到yii\base\Component类时,我们会再来说一下实例级别的事件。

对 Yii2 源码有兴趣的同学可以关注项目 yii2-2.0.3-annotated,现在在上面已经添加了不少关于 Yii2 源码的注释,之后还会继续添加~

有兴趣的同学也可以参与进来,提交 Yii2 源码的注释。

 

以上就介绍了Yii2的深入学习--yii\base\Event 类,包括了方面的内容,希望对PHP教程有兴趣的朋友有所帮助。

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
4 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Python에서 클래스와 메서드를 사용하는 방법 Python에서 클래스와 메서드를 사용하는 방법 Apr 21, 2023 pm 02:28 PM

클래스와 메소드의 개념과 인스턴스 클래스(Class): 동일한 속성과 메소드를 가진 객체의 컬렉션을 설명하는 데 사용됩니다. 컬렉션의 모든 개체에 공통적인 속성과 메서드를 정의합니다. 객체는 클래스의 인스턴스입니다. 메소드: 클래스에 정의된 함수입니다. 클래스 구성 메서드 __init__(): 클래스에는 클래스가 인스턴스화될 때 자동으로 호출되는 init()라는 특수 메서드(구성 메서드)가 있습니다. 인스턴스 변수: 클래스 선언에서 속성은 변수로 표시됩니다. 이러한 변수를 인스턴스 변수라고 합니다. 인스턴스화: 클래스의 특정 개체인 클래스의 인스턴스를 만듭니다. 상속: 즉, 파생 클래스(derivedclass)가 기본 클래스(baseclass)를 상속합니다.

2개월 만에 휴머노이드 로봇 '워커S' 옷 개기 가능 2개월 만에 휴머노이드 로봇 '워커S' 옷 개기 가능 Apr 03, 2024 am 08:01 AM

기계력 보고서 편집자: 우신(Wu Xin) 국내판 휴머노이드 로봇+대형 모델팀이 옷 접기 등 복잡하고 유연한 재료의 작업 작업을 처음으로 완료했습니다. OpenAI 멀티모달 대형 모델을 접목한 Figure01이 공개되면서 국내 동종업체들의 관련 진전이 주목받고 있다. 바로 어제, 중국의 "1위 휴머노이드 로봇 주식"인 UBTECH는 Baidu Wenxin의 대형 모델과 긴밀하게 통합되어 몇 가지 흥미로운 새로운 기능을 보여주는 휴머노이드 로봇 WalkerS의 첫 번째 데모를 출시했습니다. 이제 Baidu Wenxin의 대형 모델 역량을 활용한 WalkerS의 모습은 이렇습니다. Figure01과 마찬가지로 WalkerS는 움직이지 않고 책상 뒤에 서서 일련의 작업을 완료합니다. 인간의 명령을 따르고 옷을 접을 수 있습니다.

파이썬에서 클래스는 무엇을 의미합니까? 파이썬에서 클래스는 무엇을 의미합니까? May 21, 2019 pm 05:10 PM

클래스는 클래스를 정의하는 데 사용되는 키워드입니다. 클래스 뒤에 공백을 추가하고 클래스 이름을 추가합니다. 규칙: 첫 글자가 여러 개인 경우 카멜 표기법을 사용합니다. [class Dog()]와 같은 이름 지정.

jQuery를 사용하여 요소의 클래스 이름 바꾸기 jQuery를 사용하여 요소의 클래스 이름 바꾸기 Feb 24, 2024 pm 11:03 PM

jQuery는 웹 개발에 널리 사용되는 클래식 JavaScript 라이브러리로, 이벤트 처리, DOM 요소 조작, 웹 페이지에서 애니메이션 수행과 같은 작업을 단순화합니다. jQuery를 사용할 때 요소의 클래스 이름을 바꿔야 하는 상황이 자주 발생합니다. 이 기사에서는 몇 가지 실용적인 방법과 구체적인 코드 예제를 소개합니다. 1. RemoveClass() 및 addClass() 메소드 사용 jQuery는 삭제를 위한 RemoveClass() 메소드를 제공합니다.

PHP8.0의 이벤트 처리 라이브러리: 이벤트 PHP8.0의 이벤트 처리 라이브러리: 이벤트 May 14, 2023 pm 05:40 PM

PHP8.0의 이벤트 처리 라이브러리: 이벤트 인터넷의 지속적인 발전과 함께 널리 사용되는 백엔드 프로그래밍 언어인 PHP는 다양한 웹 애플리케이션 개발에 널리 사용됩니다. 이 과정에서 이벤트 중심 메커니즘은 매우 중요한 부분이 되었습니다. PHP8.0의 이벤트 처리 라이브러리 Event는 보다 효율적이고 유연한 이벤트 처리 방법을 제공합니다. 이벤트 처리란 무엇입니까? 이벤트 처리는 웹 애플리케이션 개발에 있어 매우 중요한 개념입니다. 이벤트는 모든 종류의 사용자 행일 수 있습니다.

PHP 클래스 사용법에 대한 자세한 설명: 코드를 더 명확하고 읽기 쉽게 만듭니다. PHP 클래스 사용법에 대한 자세한 설명: 코드를 더 명확하고 읽기 쉽게 만듭니다. Mar 10, 2024 pm 12:03 PM

PHP 코드를 작성할 때 클래스를 사용하는 것은 매우 일반적인 관행입니다. 클래스를 사용하면 관련 함수와 데이터를 단일 단위로 캡슐화하여 코드를 더 명확하고, 읽기 쉽고, 유지 관리하기 쉽게 만들 수 있습니다. 이 기사에서는 PHPClass의 사용법을 자세히 소개하고 구체적인 코드 예제를 제공하여 독자가 실제 프로젝트에 클래스를 적용하여 코드를 최적화하는 방법을 더 잘 이해할 수 있도록 돕습니다. 1. 클래스 생성 및 사용 PHP에서는 클래스 키워드를 사용하여 클래스를 정의하고 클래스의 속성과 메서드를 정의할 수 있습니다.

Vue 오류: v-bind를 사용하여 클래스와 스타일을 올바르게 바인딩할 수 없습니다. 어떻게 해결합니까? Vue 오류: v-bind를 사용하여 클래스와 스타일을 올바르게 바인딩할 수 없습니다. 어떻게 해결합니까? Aug 26, 2023 pm 10:58 PM

Vue 오류: v-bind를 사용하여 클래스와 스타일을 올바르게 바인딩할 수 없습니다. 어떻게 해결합니까? Vue 개발에서는 클래스와 스타일을 동적으로 바인딩하기 위해 v-bind 지시문을 사용하는 경우가 많지만, 클래스와 스타일을 바인딩하기 위해 v-bind를 올바르게 사용하지 못하는 등의 문제가 발생할 수도 있습니다. 이번 글에서는 이 문제의 원인을 설명하고 해결 방법을 알려드리겠습니다. 먼저 v-bind 지시어를 이해해 봅시다. v-bind는 V를 바인딩하는 데 사용됩니다.

SpringBoot가 사용자 정의 클래스 로더를 통해 클래스 파일을 암호화하고 보호하는 방법 SpringBoot가 사용자 정의 클래스 로더를 통해 클래스 파일을 암호화하고 보호하는 방법 May 11, 2023 pm 09:07 PM

배경 최근에는 jd-gui 등의 디컴파일 도구를 통해 엔지니어링 코드를 쉽게 복원하는 것을 방지하기 위해 회사 프레임워크에 대해 주요 비즈니스 코드를 암호화하고 있습니다. 관련 난독화 기법의 구성 및 사용이 상대적으로 복잡하고, springboot 프로젝트이므로 클래스 파일이 암호화된 후 사용자 정의 클래스로더가 해독되고 로드됩니다. 이 솔루션은 디컴파일의 난이도만 증가시키지만 전반적인 암호화 보호 흐름도는 표시되지 않습니다. 아래 그림에서 Maven 플러그인은 사용자 정의 Maven 플러그인을 사용하여 컴파일을 암호화하며, 암호화된 클래스 파일은 지정된 경로에 복사됩니다.

See all articles