Dynamic Table Name In Relation

Hi everyone!

I created a “shard table manager” to be able to use my models with a dynamic name. The thing is, when I need to create a relation I have a problem, I can’t dynamically add the table extension to my relation. Here is the code I am using and that is not working:

class StatReport extends ShardedActiveRecord{


public function relations()


		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

			'StatInfos' => array(self::HAS_MANY, 'StatInfo'.$this->getShard(), 'report_id'),




It is not working because the model expect the file StatInfo<shard>.php to exist… Is there a way to dynamically allocate a relation with a reference to the StatInfo.php model page?

Thank you for your help!

you could always go back to good old query builder and do a join query

It is an option… But I wanted am looking for a model based solution… If it is possible!

I believe its possible but you probably have to digg into Yii core and figure out how relationships are implemented its a interesting problem I am trying to reproduce this might take me sometime

Thank you!

I have been thinking about this and I came up with a solution that should work! I had to reimplement the CActiveFinder and the CActiveRecord classes. I am not sure if everything I did is clean so here is the code, feel free to comment!

The ShardedActiveRecord class (Reimplementation of CActiveRecord):

class ShardedActiveRecord extends CActiveRecord{

	private $_shard;


	public function tableName(){

		return get_class($this) . $this->getShard();



	public function setShard($shard) {


		$command = $connection->createCommand("SHOW TABLES LIKE '".get_class($this).$shard."'");


			throw new CHttpException(404,'The specified table cannot be found.');


		$this->_shard = $shard;

		call_user_func(array(get_class($this), 'model'))->_shard = $shard;




		return $this;


	public function getShard() {

		if($this->_shard === null){



		return $this->_shard;



	public function createShardedTable($shard){


		$command = $connection->createCommand("CREATE TABLE IF NOT EXISTS ".get_class($this).$shard." LIKE ".get_class($this));




	public function beforeSave(){

		return parent::beforeSave();



	public function getMergedDataProvider($params, $criteria = null){

		$modelArray = array();

		$model = array();

		foreach ($params as $param){

			$tmpmodel = $this->model()->setShard($param);


			if($criteria === null){

				$data = $tmpmodel->findAll();


				$data = $tmpmodel->findAll($criteria);



			if(count($data) != 0){

				array_push($modelArray, $data);




		foreach($modelArray as $ma){

			$model = array_merge($model, $ma);


		return $model;



	public function getActiveFinder($with)


		return new ShardedActiveFinder($this,$with);



The ShardedActiveFinder class (Reimplementation of CActiveFinder):

class ShardedActiveFinder extends CActiveFinder{

	private $_shard;


	public function __construct($model,$with)






	public function getModel($className)


		return ShardedActiveRecord::model($className)->setShard($this->_shard);



Some feedback would be really appreciated! Thank you.