热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Yii分析1:web程序入口(3)

//第二个参数标识如果是空则创建之,默认为truepublicfunctiongetComponent($id,$createIfNull=true){if(isset($this->_components[$id]))return

接上篇:Yii分析1:web程序入口(2)

本文分析前两篇文章用到的一些函数。

 

上一篇提到在preloadComponents的时候会调用getComponent,我们来看一下getComponent的细节:

 

Yii_PATH/base/CModule.php

PHP
//第二个参数标识如果是空则创建之,默认为true public function getComponent($id,$createIfNull=true) { if(isset($this->_components[$id])) return $this->_components[$id]; //_componentConfig是在configure方法中由setComponents中已经保存的变量 else if(isset($this->_componentConfig[$id]) && $createIfNull) { $cOnfig=$this->_componentConfig[$id]; unset($this->_componentConfig[$id]); //如果没有设置enable参数或者enable参数为true 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; } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
        //第二个参数标识如果是空则创建之,默认为true  
        public function getComponent($id,$createIfNull=true)  
        {  
            if(isset($this->_components[$id]))  
                return $this->_components[$id];          
            //_componentConfig是在configure方法中由setComponents中已经保存的变量  
            else if(isset($this->_componentConfig[$id]) && $createIfNull)  
            {  
                $cOnfig=$this->_componentConfig[$id];  
                unset($this->_componentConfig[$id]);  
                //如果没有设置enable参数或者enable参数为true  
                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的实现:

PHP
public static function createComponent($config) { //如果配置项内容是一个字符串,则它是类名,如果是数组,那么数组的class成员是类名 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.')); //如果类不存在,则使用import来引入,而不是用autoload 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); //如果参数大于4个,那么调用newInstance方法来进行初始化 $object=call_user_func_array(array($class,'newInstance'),$args); } } else $object=new $type; //将配置中的配置项赋值给组件的成员 foreach($config as $key=>$value) $object->$key=$value; return $object;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
        public static function createComponent($config)  
        {  
 
            //如果配置项内容是一个字符串,则它是类名,如果是数组,那么数组的class成员是类名  
            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.'));    
            //如果类不存在,则使用import来引入,而不是用autoload  
            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);  
                    //如果参数大于4个,那么调用newInstance方法来进行初始化  
                    $object=call_user_func_array(array($class,'newInstance'),$args);  
                }  
            }  
            else  
                $object=new $type;    
 
            //将配置中的配置项赋值给组件的成员  
            foreach($config as $key=>$value)  
                $object->$key=$value;  
 
            return $object;

 

=========================================================================

 

我们再来看看errorhandler和exceptionhandler:

 

Yii_PATH/base/CApplication.php

PHP
public function handleError($code,$message,$file,$line) { if($code & error_reporting()) { // disable error capturing to avoid recursive errors //恢复原错误handler(内建的错误handler),避免本函数触发错误handler,从而递归调用 restore_error_handler(); restore_exception_handler(); $log="$message ($file:$line)"; if(isset($_SERVER['REQUEST_URI'])) $log.=' REQUEST_URI='.$_SERVER['REQUEST_URI']; Yii::log($log,CLogger::LEVEL_ERROR,'php'); try { //使用一个error事件类来触发error事件,然后显示log信息,这里暂不分析 $event=new CErrorEvent($this,$code,$message,$file,$line); $this->onError($event); if(!$event->handled) { // try an error handler if(($handler=$this->getErrorHandler())!==null) $handler->handle($event); else $this->displayError($code,$message,$file,$line); } } catch(Exception $e) { $this->displayException($e); } $this->end(1); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
        public function handleError($code,$message,$file,$line)  
        {  
            if($code & error_reporting())  
            {  
                // disable error capturing to avoid recursive errors  
                //恢复原错误handler(内建的错误handler),避免本函数触发错误handler,从而递归调用  
                restore_error_handler();  
                restore_exception_handler();  
 
                $log="$message ($file:$line)";  
                if(isset($_SERVER['REQUEST_URI']))  
                    $log.=' REQUEST_URI='.$_SERVER['REQUEST_URI'];  
                Yii::log($log,CLogger::LEVEL_ERROR,'php');  
 
                try  
                {    
 
                    //使用一个error事件类来触发error事件,然后显示log信息,这里暂不分析  
                    $event=new CErrorEvent($this,$code,$message,$file,$line);  
                    $this->onError($event);  
                    if(!$event->handled)  
                    {  
                        // try an error handler  
                        if(($handler=$this->getErrorHandler())!==null)  
                            $handler->handle($event);  
                        else  
                            $this->displayError($code,$message,$file,$line);  
                    }  
                }  
                catch(Exception $e)  
                {  
                    $this->displayException($e);  
                }  
                $this->end(1);  
            }  
        }

dispalyError代码如下:

PHP
public function displayError($code,$message,$file,$line) { //如果是调试,打印调用栈,否则不打印 if(YII_DEBUG) { echo "PHP Error [$code]\n"; echo "

$message ($file:$line)

\n"; echo '
'; debug_print_backtrace(); echo '
'; } else { echo "PHP Error [$code]\n"; echo "

$message

\n"; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    public function displayError($code,$message,$file,$line)                        
    {            
        //如果是调试,打印调用栈,否则不打印  
        if(YII_DEBUG)  
        {            
            echo "PHP Error [$code]\n";  
            echo "

$message ($file:$line)

\n";  
            echo '
';  
							
            debug_print_backtrace();  
            echo '';                                                          
        }                
        else  
        {                    
            echo "PHP Error [$code]\n";                                    
            echo "

$message

\n";                                              
        }        
    }

参考:

PHP
设定了error hanlder之后,某些级别的错误是不会触发设置的函数的,例如:E_ERROR(运行期错误,如内存分配错误),E_PARSE(解释错误,即语法),E_CORE_ERROR(在PHP内核startup阶段发生的错误),E_CORE_WARNING(在PHP内核startup阶段发生的warning),E_COMPILE_ERROR(编译错误,zend引擎生成),E_COMPILE_WARNING(编译warning,zend引擎生成) 关于startup和zend引擎请参考php内核方面的资料
1
2
3
设定了error hanlder之后,某些级别的错误是不会触发设置的函数的,例如:E_ERROR(运行期错误,如内存分配错误),E_PARSE(解释错误,即语法),E_CORE_ERROR(在PHP内核startup阶段发生的错误),E_CORE_WARNING(在PHP内核startup阶段发生的warning),E_COMPILE_ERROR(编译错误,zend引擎生成),E_COMPILE_WARNING(编译warning,zend引擎生成)  
 
关于startup和zend引擎请参考php内核方面的资料

handleException与Error相似:

PHP
public function handleException($exception) { // disable error capturing to avoid recursive errors restore_error_handler(); restore_exception_handler(); $category='exception.'.get_class($exception); //如果是Http异常,获取状态码 if($exception instanceof CHttpException) $category.='.'.$exception->statusCode; $message=(string)$exception; if(isset($_SERVER['REQUEST_URI'])) $message.=' REQUEST_URI='.$_SERVER['REQUEST_URI']; Yii::log($message,CLogger::LEVEL_ERROR,$category); //接下来同handleError try { $event=new CExceptionEvent($this,$exception); $this->onException($event); if(!$event->handled) { // try an error handler if(($handler=$this->getErrorHandler())!==null) $handler->handle($event); else $this->displayException($exception); } } catch(Exception $e) { $this->displayException($e); } $this->end(1); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
        public function handleException($exception)  
        {  
            // disable error capturing to avoid recursive errors  
            restore_error_handler();  
            restore_exception_handler();  
 
            $category='exception.'.get_class($exception);  
            //如果是Http异常,获取状态码  
            if($exception instanceof CHttpException)  
                $category.='.'.$exception->statusCode;  
            $message=(string)$exception;  
            if(isset($_SERVER['REQUEST_URI']))  
                $message.=' REQUEST_URI='.$_SERVER['REQUEST_URI'];  
            Yii::log($message,CLogger::LEVEL_ERROR,$category);  
 
            //接下来同handleError  
            try  
            {  
                $event=new CExceptionEvent($this,$exception);  
                $this->onException($event);  
                if(!$event->handled)  
                {  
                    // try an error handler  
                    if(($handler=$this->getErrorHandler())!==null)  
                        $handler->handle($event);  
                    else  
                        $this->displayException($exception);  
                }  
            }  
            catch(Exception $e)  
            {  
                $this->displayException($e);  
            }  
            $this->end(1);  
        }

参考:

PHP
call_user_function可以传递儿女和内置的或者用户自定义的函数,除了语言结构如array(), echo(), empty(), eval(), exit(), isset(), list(), print(), unset()
1
call_user_function可以传递儿女和内置的或者用户自定义的函数,除了语言结构如array(), echo(), empty(), eval(), exit(), isset(), list(), print(), unset()

推荐阅读
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 2018年人工智能大数据的爆发,学Java还是Python?
    本文介绍了2018年人工智能大数据的爆发以及学习Java和Python的相关知识。在人工智能和大数据时代,Java和Python这两门编程语言都很优秀且火爆。选择学习哪门语言要根据个人兴趣爱好来决定。Python是一门拥有简洁语法的高级编程语言,容易上手。其特色之一是强制使用空白符作为语句缩进,使得新手可以快速上手。目前,Python在人工智能领域有着广泛的应用。如果对Java、Python或大数据感兴趣,欢迎加入qq群458345782。 ... [详细]
  • 本文内容为asp.net微信公众平台开发的目录汇总,包括数据库设计、多层架构框架搭建和入口实现、微信消息封装及反射赋值、关注事件、用户记录、回复文本消息、图文消息、服务搭建(接入)、自定义菜单等。同时提供了示例代码和相关的后台管理功能。内容涵盖了多个方面,适合综合运用。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了brain的意思、读音、翻译、用法、发音、词组、同反义词等内容,以及脑新东方在线英语词典的相关信息。还包括了brain的词汇搭配、形容词和名词的用法,以及与brain相关的短语和词组。此外,还介绍了与brain相关的医学术语和智囊团等相关内容。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • Echarts图表重复加载、axis重复多次请求问题解决记录
    文章目录1.需求描述2.问题描述正常状态:问题状态:3.解决方法1.需求描述使用Echats实现了一个中国地图:通过选择查询周期&#x ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • Python字典推导式及循环列表生成字典方法
    本文介绍了Python中使用字典推导式和循环列表生成字典的方法,包括通过循环列表生成相应的字典,并给出了执行结果。详细讲解了代码实现过程。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • “你永远都不知道明天和‘公司的意外’哪个先来。”疫情期间,这是我们最战战兢兢的心情。但是显然,有些人体会不了。这份行业数据,让笔者“柠檬” ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
author-avatar
melodyhaoduo
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有