我有一个Yii模型将使用(稍后)多个数据库,表前缀将基于代码。
例如:
AMI_tablename,BMI_ AMI_tablename等
这些表格相同,但在不同的数据库中。
我想知道如何在运行时向Yii模型提供动态表名?
我尝试使用setter函数,但是父类CActiveRecord给出了一个错误,因为它没有从子模型类中获取值。
所以这是我的模型代码(只有我有问题的部分)
class RevShareModel extends CActiveRecord
{
public $prefix;
public static function model($className=__CLASS__)
{
return parent::model($className);
}
/**
* @return string the associated database table name
*/
public function tableName()
{
return $this->prefix . '_revshare_model';
}
现在在我的控制器的某个地方
$obj = RevShareModel::model();
$obj->prefix ="BMI";
$obj->tableName();
$obj->findByPk(1);
exit;
但我得到的错误是:
CDbException
The table "_revshare_model" for active record class "RevShareModel" cannot be found in the database.
C:\wamp\www\framework\db\ar\CActiveRecord.php(2264)
似乎当CActiveRecord调用tableName()方法时,它不会获得$前缀。
答案 0 :(得分:5)
您遇到此类错误,因为表名实际存储在模型的元数据中。您可以通过检查返回$model->getMetaData()
对象的CActiveRecordMetaData
的内容来查看。要更新元数据,您应在更改模型的'prefix'属性后调用$model->refreshMetaData()
,例如:
...
$obj->prefix ="BMI";
$obj->refreshMetadata();
...
这绝对可以解决问题。
答案 1 :(得分:2)
您必须覆盖CActiveRecord::tableName
方法(可能在模型的抽象基类中)。这是默认情况下的作用:
public function tableName()
{
return get_class($this);
}
以下是您可以将其更改为:
abstract class MyActiveRecord extends CActiveRecord
{
public $prefix; // should probably be private, your call
public function tableName()
{
return $prefix.'_'.get_class($this);
}
}
答案 2 :(得分:1)
这就是我解决这个问题的方法。
private static $_tableName;
public function __construct($tableName)
{
if(strlen($tableName) == 0)
{
return false;
}
if(strlen($tableName)>0){
self::$_tableName = $tableName;
}
self::setIsNewRecord(true);
}
public static function model($tableName)
{
if(strlen($tableName) == 0)
{
return false;
}
$className=__CLASS__;
if(strlen($tableName)>0){
self::$_tableName = $tableName;
}
return parent::model($className);
}
public function tableName()
{
return '{{'.self::$_tableName.'}}';
}
public function setTableName($tableName)
{
self::$_tableName = $tableName;
}
...
当我使用这个模型时,我只是将表的名称放在括号中:
$model = new ClassName($tableName);
答案 3 :(得分:1)
我有同样的问题。 我有一个模型,但我希望将数据保存在不同的表中。所以我在保存数据之前更改了表名。
public $tbl_name = 'tbl_user_1';//default table
public function tableName()
{
return $this->tbl_name;
}
public function saveDataReg(){
$mKey = $this->selfMHash($this->username);
$modKey = $mKey % 2;
$this->tbl_name = 'tbl_user_' . $modKey;
$this->refreshMetadata();//change the default Metadata
$this->save();
}
public function selfMHash($key){
$md5 = substr(md5($key), 0, 8);
$seed = 31;
$hash = 0;
for($i=0; $i<8; $i++){
$hash = $hash * $seed + ord($md5{$i});
$i++;
}
return $hash & 0x7FFFFFFF;
}
现在我发现在使用refreshMetadata功能时不会更改元数据。 最后我更改了原始代码
public function refreshMetaData()
{
$finder=self::model(get_class($this));
$finder->_md=new CActiveRecordMetaData($finder);
if($this!==$finder)
$this->_md=$finder->_md;
//return var_dump($this);
}
public function new_refreshMetaData()
{
$finder=self::model(get_class($this));
$finder->_md=new CActiveRecordMetaData($this);
if($this!==$finder)
$this->_md=$finder->_md;
//return var_dump($this);
}
我重写了refreshMetaData的功能,并查找了CActiveRecordMetaData的参数。
$this->new_refreshMetadata();//use new function
然后它奏效了。 我不明白问题的原因。
答案 4 :(得分:0)
您可以使用MyModel::model()->tableName()
,但请不要忘记写{{table}}
。