php yii1.1框架组件用法分析代码

First.注册核心组件流程

1. require_once(SITEPARH . ‘/apple/yii/framework/yii.php’);

入口文件代码 Yii::createWebApplication($config)->run();

# yii.php继承于同级下YiiBase.php
public static function createWebApplication($config=null)
{
	return self::createApplication('CWebApplication',$config);
}
	
public static function createApplication($class,$config=null)
{
	return new $class($config); # new CWebApplication($config)
}
2. yii/web下CWebApplication.php继承于 yii/base下CApplication
# 调用 CApplication 的 __construct方法
class CWebApplication extends CApplication # CApplication 在yii/base下
# registerCoreComponents注册核心组件
abstract class CApplication extends CModule
{
	public function __construct($config=null)
	{
		Yii::setApplication($this); # self::$_app 赋值

		// set basePath at early as possible to avoid trouble
		if(is_string($config))
			$config=require($config);
		if(isset($config['basePath']))
		{
			$this->setBasePath($config['basePath']);
			unset($config['basePath']);
		}
		else
			$this->setBasePath('protected');
		Yii::setPathOfAlias('application',$this->getBasePath());
		Yii::setPathOfAlias('webroot',dirname($_SERVER['SCRIPT_FILENAME']));
		Yii::setPathOfAlias('ext',$this->getBasePath().DIRECTORY_SEPARATOR.'extensions');

		$this->preinit();

		$this->initSystemHandlers();
		$this->registerCoreComponents();

		$this->configure($config);
		$this->attachBehaviors($this->behaviors);
		$this->preloadComponents();

		$this->init();
	}
	
	protected function registerCoreComponents()
	{
		$components=array(
			'coreMessages'=>array(
				'class'=>'CPhpMessageSource',
				'language'=>'en_us',
				'basePath'=>YII_PATH.DIRECTORY_SEPARATOR.'messages',
			),
			'db'=>array(
				'class'=>'CDbConnection',
			),
			'messages'=>array(
				'class'=>'CPhpMessageSource',
			),
			'errorHandler'=>array(
				'class'=>'CErrorHandler',
			),
			'securityManager'=>array(
				'class'=>'CSecurityManager',
			),
			'statePersister'=>array(
				'class'=>'CStatePersister',
			),
			'urlManager'=>array(
				'class'=>'CUrlManager',
			),
			'request'=>array(
				'class'=>'CHttpRequest',
			),
			'format'=>array(
				'class'=>'CFormatter',
			),
		);

		$this->setComponents($components);
	}
}
3. yii/base下CModule
abstract class CModule extends CComponent{
	public function setComponents($components,$merge=true)
	{
		foreach($components as $id=>$component)
			$this->setComponent($id,$component,$merge);
	}
	public function setComponent($id,$component,$merge=true)
	{
		if($component===null)
		{
			unset($this->_components[$id]);
			return;
		}
		elseif($component instanceof IApplicationComponent)
		{
			$this->_components[$id]=$component;

			if(!$component->getIsInitialized())
				$component->init();

			return;
		}
		elseif(isset($this->_components[$id]))
		{
			if(isset($component['class']) && get_class($this->_components[$id])!==$component['class'])
			{
				unset($this->_components[$id]);
				$this->_componentConfig[$id]=$component; //we should ignore merge here
				return;
			}

			foreach($component as $key=>$value)
			{
				if($key!=='class')
					$this->_components[$id]->$key=$value;
			}
		}
		elseif(isset($this->_componentConfig[$id]['class'],$component['class'])
			&& $this->_componentConfig[$id]['class']!==$component['class'])
		{
			$this->_componentConfig[$id]=$component; //we should ignore merge here
			return;
		}

		if(isset($this->_componentConfig[$id]) && $merge)
			$this->_componentConfig[$id]=CMap::mergeArray($this->_componentConfig[$id],$component);
		else
			$this->_componentConfig[$id]=$component;
	}
}

Second. 调用组件 例: Yii::app()->db

1. Yii::app()
# YiiBase.php
public static function app()
{
	return self::$_app;  # 上面 First.2 的Yii::setApplication($this); # self::$_app 赋值
}
2. ->db
# abstract class CModule extends CComponent
public function __get($name)
{
	if($this->hasComponent($name))
		return $this->getComponent($name);
	else
		return parent::__get($name);
}

public function getComponent($id,$createIfNull=true)
{
	if(isset($this->_components[$id]))
		return $this->_components[$id];
	elseif(isset($this->_componentConfig[$id]) && $createIfNull)
	{
		$config=$this->_componentConfig[$id];
		if(!isset($config['enabled']) || $config['enabled'])
		{
			Yii::trace("Loading \"$id\" application component",'system.CModule');
			unset($config['enabled']);
			$component=Yii::createComponent($config);
			$component->init();
			return $this->_components[$id]=$component;
		}
	}
}
# YiiBase.php
public static function createComponent($config)
{
	if(is_string($config))
	{
		$type=$config;
		$config=array();
	}
	elseif(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]);
		elseif($n===3)
			$object=new $type($args[1],$args[2]);
		elseif($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;
}

public static function import($alias,$forceInclude=false)
	{
		if(isset(self::$_imports[$alias]))  // previously imported
			return self::$_imports[$alias];

		if(class_exists($alias,false) || interface_exists($alias,false))
			return self::$_imports[$alias]=$alias;

		if(($pos=strrpos($alias,'\\'))!==false) // a class name in PHP 5.3 namespace format
		{
			$namespace=str_replace('\\','.',ltrim(substr($alias,0,$pos),'\\'));
			if(($path=self::getPathOfAlias($namespace))!==false)
			{
				$classFile=$path.DIRECTORY_SEPARATOR.substr($alias,$pos+1).'.php';
				if($forceInclude)
				{
					if(is_file($classFile))
						require($classFile);
					else
						throw new CException(Yii::t('yii','Alias "{alias}" is invalid. Make sure it points to an existing PHP file and the file is readable.',array('{alias}'=>$alias)));
					self::$_imports[$alias]=$alias;
				}
				else
					self::$classMap[$alias]=$classFile;
				return $alias;
			}
			else
				throw new CException(Yii::t('yii','Alias "{alias}" is invalid. Make sure it points to an existing directory.',
					array('{alias}'=>$namespace)));
		}

		if(($pos=strrpos($alias,'.'))===false)  // a simple class name
		{
			if($forceInclude && self::autoload($alias))
				self::$_imports[$alias]=$alias;
			return $alias;
		}

		$className=(string)substr($alias,$pos+1);
		$isClass=$className!=='*';

		if($isClass && (class_exists($className,false) || interface_exists($className,false)))
			return self::$_imports[$alias]=$className;

		if(($path=self::getPathOfAlias($alias))!==false)
		{
			if($isClass)
			{
				if($forceInclude)
				{
					if(is_file($path.'.php'))
						require($path.'.php');
					else
						throw new CException(Yii::t('yii','Alias "{alias}" is invalid. Make sure it points to an existing PHP file and the file is readable.',array('{alias}'=>$alias)));
					self::$_imports[$alias]=$className;
				}
				else
					self::$classMap[$className]=$path.'.php';
				return $className;
			}
			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);

				if(self::$enableIncludePath && set_include_path('.'.PATH_SEPARATOR.implode(PATH_SEPARATOR,self::$_includePaths))===false)
					self::$enableIncludePath=false;

				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)));
	}

ps:
目的是对PHP设计模式有进一步认识。(个人理解,欢迎纠错。)

偷摸的把yii2的研究思路记在这。针对我当前遇见的,看官们可以忽略

1. yii\base\Application::run
2. yii\web\Application::handleRequest
3. yii\base\Module::runAction
4. yii\base\Controller::runAction
5. yii\base\InlineAction::runWithParams
6. yii\web\Controller::bindActionParams
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值