用过Yii框架的人,一般都知道在Yii的配置里面,有个import参数。这个参数一般可以这样配置:
Yii::setPathOfAlias('docroot', '/data/php/classes');
$config = array(
....
'import' => array(
'docroot.services.*',
'docroot.models.*',
),
...
);
这样配置之后,当有些写好的类放在’/data/php/classes/services/’目录下面,或者放在’/data/php/classes/models’目录下面时,我们也可以在代码中直接使用,不论我们的项目放在哪里。那这是为什么呢?
假设我们现在写的是web应用。那么代码的流程大致如下:
①、Yii::createWebApplication($config)->run();
②、CApplication的构造方法。代码如下:
public function __construct($config=null){
Yii::setApplication($this);
// 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();
}
③、…..
后续的流程就不讲了,这里就讲一下在CApplication构造方法里面调用的configure方法。这个方法在其父类CModule里面实现。
public function configure($config){
if(is_array($config)){
foreach($config as $key=>$value)
$this->$key=$value;//这里注意了,这里会先调用这个类的魔术方法__set();
}
}
这段代码很简单,就是遍历config数组,然后调用其魔术方法:
public function __set($name,$value){
$setter='set'.$name;
if(method_exists($this,$setter))
return $this->$setter($value);
......
}
在魔术方法里面,会先寻找该类是否存在名为$setter的方法。比如当遍历config,遍历到import时,就会寻找该类中,是否存在名为setimport的成员函数,由于php函数名不区分大小写,所以,发现存在setImport函数,这个函数在CModule中实现。代码如下:
public function setImport($aliases){
foreach($aliases as $alias)//这里的$alias就是$config['import']
Yii::import($alias);
}
很简单,就是遍历$config[‘import’],然后调用Yii::import()函数。这个函数就在yii.php里面实现。这个函数主要是做什么事情呢?比如当遍历到
$config[‘import’]的第一个元素,然后将’docroot.services.‘这个值传给import函数。这个函数前面会做几个判断处理,这里我们不用管,一般用不着。然后,它会l调用Yii::getPathOfAlias()这个函数,将’docroot.services.‘转为正确的路径’/data/php/classes/services/*’,最后调用set_include_path()这个方法,将路径设到php的include_path中。这之后,假设在’/data/php/classes/services/’目录下有个’SayHelloService.php’类,当代码中需要的时候,只需要
include('SayHelloService.php');
$sayHello = new SayHelloService();
即可,而不需要给出SayHelloService.php的路径。