Heim  >  Artikel  >  php教程  >  Yii Framework-Analyse (3) – Klassenlademechanismus und Verwaltung, Konfiguration, Zugriff und Erstellung von Anwendungskomponenten

Yii Framework-Analyse (3) – Klassenlademechanismus und Verwaltung, Konfiguration, Zugriff und Erstellung von Anwendungskomponenten

黄舟
黄舟Original
2016-12-27 11:11:261371Durchsuche

Das Eingabeskript der Yii-Anwendung verweist auf die Yii-Klasse. Die Definition der Yii-Klasse:

class Yii extends YiiBase
{
}

In der von yiic erstellten Anwendung ist die Yii-Klasse nur die „Weste“ der YiiBase Wir können es auch an die Bedürfnisse unserer eigenen Yii-Klasse anpassen.

Yii (d. h. YiiBase) ist eine „Hilfsklasse“, die statischen und globalen Zugriff auf die gesamte Anwendung bietet.

Mehrere statische Mitglieder der Yii-Klasse:
$_aliases: speichert die tatsächlichen Pfade, die Systemaliasen entsprechen
$_imports:
$_classes:
$_includePaths php include paths
$_app: CWebApplication-Objekt, Zugriff über Yii::app()
$_logger: Systemprotokollobjekt
$_app-Objekt wird von der Yii::createWebApplication()-Methode erstellt.

Automatisches Laden von Klassen

Yii basiert auf dem Autoload-Mechanismus von PHP5, um die automatische Ladefunktion von Klassen bereitzustellen. Der Autoloader ist die statische Methode autoload() der YiiBase-Klasse.

Wenn das Programm new verwendet, um ein Objekt zu erstellen oder auf ein statisches Mitglied einer Klasse zuzugreifen, übergibt PHP den Klassennamen an den Klassenlader und der Klassenlader vervollständigt das Einschließen der Klassendatei.

Der Autoload-Mechanismus implementiert den „On-Demand-Import“ von Klassen, was bedeutet, dass das System Dateien der Klasse nur einbezieht, wenn es auf die Klasse zugreift.

Das statische Mitglied $_coreClasses der YiiBase-Klasse speichert Yiis eigenen Kernklassennamen und den entsprechenden Klassendateipfad vor. In anderen Yii-Anwendungen verwendete Klassen können mit Yii::import() importiert werden. Yii::import() speichert die einzelne Klasse und die entsprechenden Klassendateien in $_classes und fügt den durch das Platzhalterzeichen * dargestellten Pfad zu php include_path hinzu. Von Yii::import() importierte Klassendateien oder Verzeichnisse werden in $_imports aufgezeichnet, um Mehrfachimporte zu vermeiden.

/* Yii::import()
* $alias: 要导入的类名或路径
* $forceInclude false:只导入不include类文件,true则导入并include类文件
*/
public static function import($alias,$forceInclude=false)
{
    // 先判断$alias是否存在于YiiBase::$_imports[] 中,已存在的直接return, 避免重复import。
    if(isset(self::$_imports[$alias])) // previously imported
        return self::$_imports[$alias];
    // $alias类已定义,记入$_imports[],直接返回
    if(class_exists($alias,false) || interface_exists($alias,false))
        return self::$_imports[$alias]=$alias;
    // 已定义于$_coreClasses[]的类,或名字中不含.的类,记入$_imports[],直接返回
    if(isset(self::$_coreClasses[$alias]) || ($pos=strrpos($alias,’.'))===false) // a simple class name
    {
        self::$_imports[$alias]=$alias;
        if($forceInclude)
        {
            if(isset(self::$_coreClasses[$alias])) // a core class
                require(YII_PATH.self::$_coreClasses[$alias]);
            else
                require($alias.’.php’);
        }
        return $alias;
    }
    // 产生一个变量 $className,为$alias最后一个.后面的部分
    // 这样的:’x.y.ClassNamer’
    // $className不等于 ‘*’, 并且ClassNamer类已定义的,????? ClassNamer’ 记入 $_imports[],直接返回
    if(($className=(string)substr($alias,$pos+1))!==’*’ 
            && (class_exists($className,false) || interface_exists($className,false)))
        return self::$_imports[$alias]=$className;
    // $alias里含有别名,并转换真实路径成功
    if(($path=self::getPathOfAlias($alias))!==false)
    {
        // 不是以*结尾的路径(单类)
        if($className!==’*')
        {
            self::$_imports[$alias]=$className;
            if($forceInclude)
                require($path.’.php’);
            else
                // 类名与真实路径记入$_classes数组
                self::$_classes[$className]=$path.’.php’;
            return $className;
        }
        // $alias是’system.web.*’这样的已*结尾的路径,将路径加到include_path中
        else // a directory
        {
            if(self::$_includePaths===null)
            {
                self::$_includePaths=array_unique(explode(PATH_SEPARATOR,get_include_path()));
                if(($pos=array_search(‘.’,self::$_includePaths,true))!==false)
                    unset(self::$_includePaths[$pos]);
             }
            array_unshift(self::$_includePaths,$path);
            set_include_path(‘.’.PATH_SEPARATOR.implode(PATH_SEPARATOR,self::$_includePaths));
            return self::$_imports[$alias]=$path;
         }
    }
    else
        throw new CException(Yii::t(‘yii’,'Alias “{alias}” is invalid. Make sure it points to an existing directory or file.’,array(‘{alias}’=>$alias)));
}

Dann werfen Sie einen Blick auf die Verarbeitung der Funktion YiiBase::autoload():

public static function autoload($className)
{
    // $_coreClasses中配置好的类直接引入
    if(isset(self::$_coreClasses[$className]))
        include(YII_PATH.self::$_coreClasses[$className]);
    // $_classes 中登记的单类直接引入
    else if(isset(self::$_classes[$className]))
        include(self::$_classes[$className]);
    else
    {
        // 其他的认为文件路径以记入 include_path 里,以$className.’.php’直接引入
        include($className.’.php’);
        return class_exists($className,false) || interface_exists($className,false);
    }
    return true;
}

Die Klassen oder Pfade im Importelement in der Systemkonfigurationsdatei werden angezeigt Wird beim Skriptstart automatisch geladen. Importieren. Für Klassen, die in einzelne Klassen in Benutzeranwendungen importiert werden müssen, kann die Anweisung Yii::import() vor der Klassendefinition hinzugefügt werden.

Anwendungskomponentenverwaltung

Wie bereits erwähnt, stellt die CComponent-Klasse von Yii Zugriffsschnittstellen auf Komponenteneigenschaften, Ereignisse und Verhaltensweisen bereit, und die Unterklasse CModule von CComponent stellt auch Anwendungskomponentenverwaltung bereit.

Die Anwendungskomponente muss eine Instanz der IApplicationComponent-Schnittstelle sein und die Methoden init() und getIsInitialized() der Schnittstelle implementieren. init() wird automatisch aufgerufen, nachdem Komponenteninitialisierungsparameter angewendet wurden.

Yiis eigene Funktionsmodule werden über Anwendungskomponenten bereitgestellt, wie etwa den gemeinsamen Yii::app()->user, Yii::app()->request usw. Benutzer können auch Anwendungskomponenten definieren.

Als übergeordnete Klasse des Yii::app()-Objekts (CWebApplication) bietet CModule eine vollständige Verwaltung des Komponentenlebenszyklus, einschließlich Komponentenerstellung, Initialisierung, Objektspeicherung usw.

Jede Anwendungskomponente wird durch einen Zeichenfolgennamen identifiziert und über die __get()-Methode der CModule-Klasse aufgerufen.

Das $_components[]-Mitglied der CModule-Klasse speichert die Objektinstanz der Anwendungskomponente ($name => $object) und $_componentConfig[] speichert den Klassennamen und die Initialisierungsparameter der Anwendungskomponente.

Wenn Sie eine Anwendungskomponente verwenden, legen Sie zunächst den Klassennamen und die Initialisierungsparameter der Komponente in $_componentConfig fest. Wenn Sie zum ersten Mal auf die Komponente zugreifen, erstellt CModule automatisch eine Anwendungskomponentenobjektinstanz und initialisiert die angegebenen Parameter Anschließend wird die init()-Methode der Anwendungskomponente aufgerufen.

Die Klasse CWebApplication des Yii::app()-Objekts und seine übergeordnete Klasse CApplication sind mit den vom System selbst verwendeten Anwendungskomponenten vorkonfiguriert: urlManager, request, session, assetManager, user, themeManager, authManager , clientScript, coreMessages, db, messages, errorHandler, securityManager, statePersister.

Wir können die Parameter der Systemanwendungskomponenten ändern oder neue Anwendungskomponenten im Komponentenprojekt der Systemkonfigurationsdatei konfigurieren.

CModule ist nicht für die Erstellung von Anwendungskomponenteninstanzen verantwortlich, sondern erfolgt durch die statische Methode Yii::createComponent().

Der Parameter $config von createComponent() kann eine Zeichenfolge mit Klassennamen oder ein Array sein, in dem Klassennamen und Initialisierungsparameter gespeichert sind.

Konfiguration der Anwendungskomponenten

Die Konfiguration der Anwendungskomponenten wird im Komponentenelement in der Systemvariablen $config (config/main.php) gespeichert:

// application components
‘components’=>array(
    ‘log’=>array(
        ‘class’=>’CLogRouter’,
        ‘routes’=>array(
            array(
                ‘class’=>’CFileLogRoute’,
                ‘levels’=>’error, warning’,
            ),
         ),
    ),
    ‘user’=>array(
    // enable cookie-based authentication
        ‘allowAutoLogin’=>true,
    ),
),

$ Die Komponentenelemente in config werden im Konstruktor von CApplication verarbeitet:

$this->configure($config);

Die Verarbeitung der Funktion configure() ist sehr einfach:

public function configure($config)
{
    if(is_array($config))
    {
        foreach($config as $key=>$value)
            $this->$key=$value;
    }
}

Jedes Element in $config wird als Attribut an die Attributeinstellungsmethode setXXX() des $_app-Objekts übergeben, wo das Element „components“ von setComponents(), der übergeordneten Klasse von CModule, verarbeitet wird in CWebApplication.

setComponents() speichert den Klassennamen und die Initialisierungsparameter im Element „components“ in $_componentConfig[]:

public function setComponents($components)
{
    // $config 里的’components’每一项
    foreach($components as $id=>$component)
    {
        if($component instanceof IApplicationComponent)
            $this->setComponent($id,$component);
        // $_componentConfig里已经存在配置,合并$component
        else if(isset($this->_componentConfig[$id]))
            $this->_componentConfig[$id]=CMap::mergeArray($this->_componentConfig[$id],$component);
        // 在$_componentConfig里新建项目
        else
            $this->_componentConfig[$id]=$component;
    }
}

Zugriff auf Anwendungskomponenten

CModule类重载了CComponent的__get()方法,优先访问应用组件对象。

public function __get($name)
{
    if($this->hasComponent($name))
        return $this->getComponent($name);
    else
        return parent::__get($name);
}

hasComponent() 判断$_components[]中是否已存在组件实例,或$_componentConfig[]中存在组件配置信息。

public function hasComponent($id)
{
    return isset($this->_components[$id]) || isset($this->_componentConfig[$id]);
}

getComponent() 判断组件实例已经存在于$_components[]中,则直接返回对象。
否则根据$_componentConfig[]里的组件配置数据调用 Yii::createComponent() 来创建组件,并将对象存入$_components[]中然后返回。

public function getComponent($id,$createIfNull=true)
{
    if(isset($this->_components[$id]))
        return $this->_components[$id];
    else if(isset($this->_componentConfig[$id]) && $createIfNull)
    {
        $config=$this->_componentConfig[$id];
        unset($this->_componentConfig[$id]);
        if(!isset($config['enabled']) || $config['enabled'])
        {
            Yii::trace(“Loading \”$id\” application component”,’system.web.CModule’);
            unset($config['enabled']);
            $component=Yii::createComponent($config);
            $component->init();
            return $this->_components[$id]=$component;
        }
    }
}

应用组件的创建

Yii::createComponent() 来完成应用组件的创建

public static function createComponent($config)
{
    if(is_string($config))
    {
        $type=$config;
        $config=array();
    }
    else if(isset($config['class']))
    {
        $type=$config['class'];
        unset($config['class']);
    }
    else
        throw new CException(Yii::t(‘yii’,'Object configuration must be an array containing a “class” element.’));
 
    if(!class_exists($type,false))
        $type=Yii::import($type,true);
 
    if(($n=func_num_args())>1)
    {
        $args=func_get_args();
        if($n===2)
            $object=new $type($args[1]);
        else if($n===3)
            $object=new $type($args[1],$args[2]);
        else if($n===4)
            $object=new $type($args[1],$args[2],$args[3]);
        else
        {
            unset($args[0]);
            $class=new ReflectionClass($type);
            // Note: ReflectionClass::newInstanceArgs() is available for PHP 5.1.3+
            // $object=$class->newInstanceArgs($args);
            $object=call_user_func_array(array($class,’newInstance’),$args);
        }
    }
    else
        $object=new $type;
 
    foreach($config as $key=>$value)
    $object->$key=$value;
 
    return $object;
}

 以上就是Yii框架分析(三)——类加载机制及应用组件的管理、配置、访问、创建的内容,更多相关内容请关注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