Heim  >  Artikel  >  php教程  >  Yii-Framework-Analyse (2) – CComponent-Klassenanalyse

Yii-Framework-Analyse (2) – CComponent-Klassenanalyse

黄舟
黄舟Original
2016-12-27 11:04:051214Durchsuche

Yii ist ein komponentenbasiertes Webframework und die CComponent-Klasse ist die Basisklasse für alle Komponenten.

Die CComponent-Klasse stellt Unterklassen Programmierschnittstellen bereit, die auf Eigenschaften, Ereignissen und Verhaltensweisen basieren.

1. Komponenteneigenschaften (Eigenschaft)

Die Ccomponent-Klasse bietet keine variable Speicherung von Attributen und eine Unterklasse muss zwei Methoden bereitstellen, um sie zu implementieren. Die Methode getPropertyName() der Unterklasse stellt die Wertoperationsdaten von $component->PropertyName bereit, und die Methode setPropertyName($val) der Unterklasse stellt die Wertzuweisungsoperation von $component->PropertyName bereit.

$width=$component->textWidth;???? // Holen Sie sich das textWidth-Attribut

Die Implementierungsmethode besteht darin, die von der Unterklasse $width=$component- bereitgestellte Methode aufzurufen >getTextWidth( )

$component->textWidth=$width;???? // Setze das textWidth-Attribut

Die Implementierung besteht darin, die von der Unterklasse $component bereitgestellte Methode aufzurufen ->setTextWidth($width)

public function getTextWidth()
{
    return $this->_textWidth;
}
 
public function setTextWidth($value)
{
    $this->_textWidth=$value;
}

Bei den Attributwerten der Komponente wird die Groß-/Kleinschreibung nicht beachtet (bei Mitgliedern der Klasse wird die Groß-/Kleinschreibung beachtet)

2 Komponentenereignisse ( Ereignisse)

Ein Komponentenereignis ist ein spezielles Attribut, das einen Ereignishandler (der ein Funktionsname, eine Klassenmethode oder eine Objektmethode sein kann) an einen Ereignisnamen registriert (bindet), und der Handler wird automatisch aufgerufen, wenn das Ereignis wird hervorgerufen.
Komponentenereignisse werden im Array $_e[] von CComponent gespeichert. Der Wert des Schlüsselwerts ist ein von Yii bereitgestellter Warteschlangencontainer. Die Methode add() von Clist fügt das Callback-Handle des Ereignisses hinzu.

//Eine globale Funktion zur Ereignisverarbeitung hinzufügen
$component-> onBeginRequest="logRequest";
//Eine statische Klassenmethode zur Ereignisverarbeitung hinzufügen
$component-> onBeginRequest=array("CLog"," logRequest");
//Eine Objektmethode zur Ereignisverarbeitung hinzufügen
$component-> onBeginRequest=array($mylog," logRequest");

Ereignis auslösen:
$component ->raiseEvent('onBeginRequest ', $event);
ruft automatisch auf:
logRequest($event), Clog::logRequest($event) und $mylog. logRequest($event)

Der Event-Handler muss wie folgt definiert werden:

function methodName($event)
{
……
}
$event Parameter Es handelt sich um eine Instanz von CEvent oder seiner Unterklasse, die mindestens die Information enthält, „wer dieses Ereignis aufgehängt hat“.

Der Name des Ereignisses beginnt mit „on“, was zur Unterscheidung von Attributen und Ereignissen in __get() und __set() verwendet werden kann.

3. Komponentenverhalten (Verhalten)

Das Verhalten einer Komponente ist eine Methode zur Erweiterung der Komponentenfunktionalität ohne Vererbung (siehe das Strategiemuster in Entwurfsmustern).

Verhaltensklassen müssen die IBehavior-Schnittstelle implementieren und die meisten Verhaltensweisen können von der CBehavior-Basisklasse aus erweitert werden.

Die IBehavior-Schnittstelle bietet 4 Methoden.
attach($component) verbindet sich mit der Komponente, detach($component) entfernt die $component-Zuordnung, getEnabled() und setEnabled() legen die Gültigkeit des Verhaltensobjekts fest.

Das Verhaltensobjekt wird im Array $_m[] der Komponente gespeichert. Der Array-Schlüsselwert ist die Verhaltensnamenzeichenfolge und der Array-Wert ist das Verhaltensklassenobjekt.

Die Komponente erweitert ein Verhalten durch attachmentBehavior ($name,$behavior):
$component-> attachmentBehavior ('render',$htmlRender)
Fügt einen Namen für render zu $component hinzu Verhalten muss $htmlRender ein Objekt sein, das die IBehavior-Schnittstelle implementiert, oder ein Array:

array( ‘class’=>’path.to.BehaviorClass’,
    ‘property1′=>’value1′,
    ‘property2′=>’value2′,
* )

erstellt ein Verhaltensobjekt und legt Attributwerte basierend auf der Klasse des Arrays fest.

$htmlRender wird in $_m[‘render’] gespeichert.

Wenn eine undefinierte Methode einer Komponente extern aufgerufen wird, durchläuft die magische Methode __call()? alle Verhaltensobjekte und ruft sie auf, wenn eine Methode mit demselben Namen gefunden wird.

$htmlRender verfügt beispielsweise über eine Methode renderFromFile(), auf die direkt als Komponentenmethode zugegriffen werden kann:

$component-> renderFromFile()

4.CKomponenten-Quellcode-Analyse

//所有部件的基类
class CComponent
{
    private $_e;
    private $_m;
 
    //获取部件属性、事件和行为的magic method
    public function __get($name)
    {
        $getter=’get’.$name;
        //是否存在属性的get方法
        if(method_exists($this,$getter))
            return $this->$getter();
        //以on开头,获取事件处理句柄
        else if(strncasecmp($name,’on’,2)===0 && method_exists($this,$name))
        {
            // 事件名小写
            $name=strtolower($name);
            // 如果_e[$name] 不存在,返回一个空的CList事件句柄队列对象
            if(!isset($this->_e[$name]))
                $this->_e[$name]=new CList;
            // 返回_e[$name]里存放的句柄队列对象
            return $this->_e[$name];
        }
        // _m[$name] 里存放着行为对象则返回
        else if(isset($this->_m[$name]))
            return $this->_m[$name];
        else
            throw new CException(Yii::t(‘yii’,'Property “{class}.{property}” is not defined.’,
                array(‘{class}’=>get_class($this), ‘{property}’=>$name)));
    }
 
    /**
    * PHP magic method
    * 设置组件的属性和事件
    */
     public function __set($name,$value)
    {
        $setter=’set’.$name;
        //是否存在属性的set方法
        if(method_exists($this,$setter))
            $this->$setter($value);
        //name以on开头,这是事件处理句柄
        else if(strncasecmp($name,’on’,2)===0 && method_exists($this,$name))
        {
            // 事件名小写
            $name=strtolower($name);
            // _e[$name] 不存在则创建一个CList对象
            if(!isset($this->_e[$name]))
                $this->_e[$name]=new CList;
            // 添加事件处理句柄
            $this->_e[$name]->add($value);
        }
        // 属性没有set方法,只有get方法,为只读属性,抛出异常
        else if(method_exists($this,’get’.$name))
            throw new CException(Yii::t(‘yii’,'Property “{class}.{property}” is read only.’,
                array(‘{class}’=>get_class($this), ‘{property}’=>$name)));
        else
            throw new CException(Yii::t(‘yii’,'Property “{class}.{property}” is not defined.’,
                array(‘{class}’=>get_class($this), ‘{property}’=>$name)));
    }
 
    /**
    * PHP magic method
    * 为isset()函数提供是否存在属性和事件处理句柄的判断
    */
    public function __isset($name)
    {
        $getter=’get’.$name;
        if(method_exists($this,$getter))
            return $this->$getter()!==null;
        else if(strncasecmp($name,’on’,2)===0 && method_exists($this,$name))
        {
            $name=strtolower($name);
            return isset($this->_e[$name]) && $this->_e[$name]->getCount();
        }
        else
            return false;
    }
 
    /**
    * PHP magic method
    * 设置属性值为空或删除事件名字对应的处理句柄
    */
    public function __unset($name)
    {
        $setter=’set’.$name;
        if(method_exists($this,$setter))
            $this->$setter(null);
        else if(strncasecmp($name,’on’,2)===0 && method_exists($this,$name))
            unset($this->_e[strtolower($name)]);
        else if(method_exists($this,’get’.$name))
            throw new CException(Yii::t(‘yii’,'Property “{class}.{property}” is read only.’,
        array(‘{class}’=>get_class($this), ‘{property}’=>$name)));
    }
 
    /**
    * PHP magic method
    *?CComponent未定义的类方法,寻找行为类里的同名方法,实现行为方法的调用
    */
    public function __call($name,$parameters)
    {
        // 行为类存放的$_m数组不空
        if($this->_m!==null)
        {
            // 循环取出$_m数组里存放的行为类
            foreach($this->_m as $object)
            {
                // 行为类对象有效,并且方法存在,调用之
                if($object->enabled && method_exists($object,$name))
                    return call_user_func_array(array($object,$name),$parameters);
            }
        }
        throw new CException(Yii::t(‘yii’,'{class} does not have a method named “{name}”.’,
            array(‘{class}’=>get_class($this), ‘{name}’=>$name)));
    }
 
    /**
    * 根据行为名返回行为类对象
    */
    public function asa($behavior)
    {
        return isset($this->_m[$behavior]) ? $this->_m[$behavior] : null;
    }
 
    /**
    * Attaches a list of behaviors to the component.
    * Each behavior is indexed by its name and should be an instance of
    *?{@link?IBehavior}, a string specifying the behavior class, or an
    * array of the following structure:
    *
* array( *???? ‘class’=>’path.to.BehaviorClass’, *???? ‘property1′=>’value1′, *???? ‘property2′=>’value2′, * ) *

* @param array list of behaviors to be attached to the component * @since 1.0.2 */ public function attachBehaviors($behaviors) { // $behaviors为数组 $name=>$behavior foreach($behaviors as $name=>$behavior) $this->attachBehavior($name,$behavior); } /** * 添加一个行为到组件 */ public function attachBehavior($name,$behavior) { /* $behavior不是IBehavior接口的实例,则为 * array( *???? ‘class’=>’path.to.BehaviorClass’, *???? ‘property1′=>’value1′, *???? ‘property2′=>’value2′, * ) * 传递给Yii::createComponent创建行为了并初始化对象属性 */ if(!($behavior instanceof IBehavior)) $behavior=Yii::createComponent($behavior); $behavior->setEnabled(true); $behavior->attach($this); return $this->_m[$name]=$behavior; } /** * Raises an event. * This method represents the happening of an event. It invokes * all attached handlers for the event. * @param string the event name * @param CEvent the event parameter * @throws CException if the event is undefined or an event handler is invalid. */ public function raiseEvent($name,$event) { $name=strtolower($name); // _e[$name] 事件处理句柄队列存在 if(isset($this->_e[$name])) { // 循环取出事件处理句柄 foreach($this->_e[$name] as $handler) { // 事件处理句柄为全局函数 if(is_string($handler)) call_user_func($handler,$event); else if(is_callable($handler,true)) { // an array: 0 – object, 1 – method name list($object,$method)=$handler; if(is_string($object))?// 静态类方法 call_user_func($handler,$event); else if(method_exists($object,$method)) $object->$method($event); else throw new CException(Yii::t(‘yii’,'Event “{class}.{event}” is attached with an invalid handler “{handler}”.’,array(‘{class}’=>get_class($this), ‘{event}’=>$name, ‘{handler}’=>$handler[1]))); } else throw new CException(Yii::t(‘yii’,'Event “{class}.{event}” is attached with an invalid handler “{handler}”.’,array(‘{class}’=>get_class($this), ‘{event}’=>$name, ‘{handler}’=>gettype($handler)))); // $event 的handled 设置为true后停止队列里剩余句柄的调用 if(($event instanceof CEvent) && $event->handled) return; } } else if(YII_DEBUG && !$this->hasEvent($name)) throw new CException(Yii::t(‘yii’,'Event “{class}.{event}” is not defined.’, array(‘{class}’=>get_class($this), ‘{event}’=>$name))); } }

 以上就是Yii框架分析(二)——CComponent类剖析的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn