miliguy 2012-05-23 12:03:57 10865次浏览 2条回复 3 0 0

在项目中很难不会遇到分表分库的情况,但是有时候想如果能够不通过建立model而使用YII AR 中的一些方法是不是很方便呢???

首先,我们想不建立表对应的model,那么我们就得将表明传进AR类中,让人兴奋的是YII在model中可以传入表名。

<?php
/**
 * 
 * 动态表处理
 * @author miliguy
 *
 */
class MAR extends CActiveRecord {
	
	public static $tableName;
	
	public function __construct($table_name = '') {
		
		if ($table_name === null) {
			parent::__construct ( null );
		} else {
			self::$tableName = $table_name;
			parent::__construct ();
		}
	}
	
	public static function model($table_name = '', $className = __CLASS__) {
		
		self::$tableName = $table_name;	
		return parent::model ( $className );
	}
	
	public function tableName() {		
		return self::$tableName;
	}

}

首先建立一个MAR是我自己的AR 继承YII的CAR类,然后建立一个公用的model,让其他不建立model的表都走这个model,代码如下:

<?php
/**
 * 
 * 一些小表不建立自己的model,将使用这个公共的model
 * @author miliguy
 *
 */
class Models extends MAR{
    
    public function __construct($tableName){
        
        parent::__construct($tableName);
        
    }
    
    public static function model($tableName,$className=__CLASS__){ 
        
        return parent::model($tableName,$className);
        
    }
    
	/**
	 * @return string the associated database table name
	 */
	public function tableName()
	{
		return parent::$tableName;
	}
}

这样在调用的时候,直接这样调用 $Model = new Models($table_name) 或者 Models::model($table_name) 然后CAR 提供的各种方法我们都可以直接进行调用了。

到此以为成功了,但是这样会遇到一个问题,这个问题是因为YII的AR实例化缓存机制造成的。AR中缓存各个实例的是一个私有的静态的数组 $_models,这个数组是以类名作为键名的,问题就出在这了。因为我们的类名都是Models这个类,所以当你在一个controller中实例化两次那个Models,永远使用的是最开始的那个实例,这样我们前面的工作就算白做了。

现在的解决方案是有两个,其中都会对CAR类进行简单修改。现放一种方案,在CAR类中添加这个方法:

/**
     * 
     * 销毁AR实例的缓存,以适应多表在同一个控制器中调用的请款
     * @param string $name
     * @author miliguy 
     * 2012-5-23
     */
	protected function unsetModels($name){
	    if(isset(self::$_models[$name]))
	        unset(self::$_models[$name]);
	}

在models类中添加这个方法:

public function usetModels($name=__CLASS__)
{
    parent::unsetModels($name);
}

在controller中调用的时候这样调用:

$model = new Models('post_topic_user_0');
$model->usetModels();     
$model = new Models('post_topic_user_1');

这种方式会修改CAR类,不是太完美的方式。但是用着很HAppy

您需要登录后才可以回复。登录 | 立即注册