Yii的Log组件为什么要在Preload里才能生效

如题,我在使用log组建配置了DBLogRoute,也就是说我会把log写入到数据库中。

我的项目碰巧最近由于某个接口由于访量很大导致数据库并发过多而down掉。

但是我这个接口并没有访问数据库的行为,最后排查发现是每次访问这个接口时,都会建立一个到日志数据库的链接,无论是否有日志记录行为。

我尝试在proload中把log组件去掉,但是这样做却无法把日志写入到数据库中,程序上也没有报错。

请问如何让log组建的数据库日志模块按需建立数据库链接,而不是每次加载时就链接数据库呢?

我浏览了下框架源代码,发现这里有一个设计缺陷违背了了Yii按需加载的模式。

CDbLogROute.php

/**


 * Initializes the route.


 * This method is invoked after the route is created by the route manager.


 */


public function init()


{


	parent::init();





	$db=$this->getDbConnection();


	$db->setActive(true);





	if($this->autoCreateLogTable)


	{


		$sql="DELETE FROM {$this->logTableName} WHERE 0=1";


		try


		{


			$db->createCommand($sql)->execute();


		}


		catch(Exception $e)


		{


			$this->createLogTable($db,$this->logTableName);


		}


	}


}

$db=$this->getDbConnection();

$db->setActive(true);

这两行代码我认为完全可以放到下面的判断里,需要自动创建LOG表时候在链接数据库。

真正写入的日志的时候会再次调用数据库链接获取方法,这时候在链接也不迟:

protected function processLogs($logs)


{


	$sql="

INSERT INTO {$this->logTableName}

(level, category, logtime, message) VALUES

(:level, :category, :logtime, :message)

";

	$command=$this->getDbConnection()->createCommand($sql);


	foreach($logs as $log)


	{


		$command->bindValue(':level',$log[1]);


		$command->bindValue(':category',$log[2]);


		$command->bindValue(':logtime',(int)$log[3]);


		$command->bindValue(':message',$log[0]);


		$command->execute();


	}


}

在这里:$command=$this->getDbConnection()->createCommand($sql);

所以我不得不HACK了下框架 :( 希望强哥下个版本考虑改进下:)

原来是这样

你这个问题 新版中早纠正了 是你用的yii版本太低了 :lol:

CDbLogRoute 源码