Yii Framework Forum: How to set ActiveRecord table name dynamicly - Yii Framework Forum

Jump to content

Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

How to set ActiveRecord table name dynamicly Rate Topic: -----

#1 User is offline   kernel 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 91
  • Joined: 22-November 10

Posted 28 January 2012 - 11:40 AM

For instance:

$ar = new ArTable();
$ar->setTable('table_abc');
$ar->find();
...

My problem is:

Follw Yii ActiveRecord Design, table name must be set when constructed, especially for ::model() static method, that's losting lost of flexibility.
0

#2 User is offline   dstudio 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 38
  • Joined: 14-October 11

Posted 28 January 2012 - 12:10 PM

Can you tell us, please, some more details?

Looking for something like this?

public function actionSomething ($table){
   $ar = new ArTable();
   $ar->setTable($table);
   $ar->find();			
}


Open:
/project/?r=controller/something&table=users

and that will find everything from table users. Also, you can set default table by:

public function actionSomething ($table='some_table')


I hope that is what you are looking for.
0

#3 User is offline   kernel 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 91
  • Joined: 22-November 10

Posted 28 January 2012 - 12:21 PM

Hi, dstudio, It's about database sharding:

$ar = new ArTable();

This setTable(assumed) method:

$ar->setTable('shardding_table_1');
...

$ar->setTable('shardding_table_2');
...

will allow you to choose different sharding tables(set specific table name) after ArTable constructed.

Or can we assign table name to ArTable when it's constructed like:
$ar1 = new ArTable('shardding_table_1');
$ar2 = new ArTable('shardding_table_2');

That would be nice too, It's not realistic to creat every class file according to every shard_table which have the same database structure.

Or there is other way on current yii version? To set table name when ar class is initiating.
0

#4 User is offline   kernel 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 91
  • Joined: 22-November 10

Posted 28 January 2012 - 12:38 PM

public function tableName(){}


Won't work. Because getting a sharding table name must have a sharding key passed into the tableName() function, unless we introduce an external dependency in tableName():


class ArTable extends CActiveRecord{
 public $sharding_table;

 public function tableName(){
    if(!isset($this->sharding_table)){
       global $sharding_table;
       $this->sharding_table = $sharding_table;
    }
    return $this->sharding_table;
 }
}

The execution flow is(Just prototyping):

$sharding_table = 'table_1';

$ar1 = new ArTable();

..then $ar1 is with table_1

$sharding_table = 'table_2';

$ar2 = new ArTable();

..then $ar2 is with table_2





Though it's workable but not secure
0

#5 User is offline   jellysandwich 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 86
  • Joined: 03-May 11

Posted 28 January 2012 - 02:51 PM

Can you normalize the database table and use single table inheritance?

http://www.yiiframew...le-inheritance/
0

#6 User is offline   kernel 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 91
  • Joined: 22-November 10

Posted 28 January 2012 - 07:58 PM

View Postjellysandwich, on 28 January 2012 - 02:51 PM, said:

Can you normalize the database table and use single table inheritance?

http://www.yiiframew...le-inheritance/


That still need to create specific classes for different shards in my point:(
0

#7 User is offline   kernel 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 91
  • Joined: 22-November 10

Posted 28 January 2012 - 07:59 PM

In zend framework docs, I saw it can to this:

"The schema and table names may also be specified via constructor configuration directives, which override any default values specified with the $_name and $_schema properties. A schema specification given with the name directive overrides any value provided with the schema option."

http://framework.zen...d.db.table.html

which give flexibilities.
0

#8 User is offline   Yurko 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 3
  • Joined: 29-January 12
  • Location:Ukraine, Kyiv

Posted 29 January 2012 - 03:14 AM

View Postkernel, on 28 January 2012 - 12:38 PM, said:

public function tableName(){}


Won't work. Because getting a sharding table name must have a sharding key passed into the tableName() function, unless we introduce an external dependency in tableName():


class ArTable extends CActiveRecord{
 public $sharding_table;

 public function tableName(){
    if(!isset($this->sharding_table)){
       global $sharding_table;
       $this->sharding_table = $sharding_table;
    }
    return $this->sharding_table;
 }
}

The execution flow is(Just prototyping):

$sharding_table = 'table_1';

$ar1 = new ArTable();

..then $ar1 is with table_1

$sharding_table = 'table_2';

$ar2 = new ArTable();

..then $ar2 is with table_2





Though it's workable but not secure


Why should it be in such a strange manner? You don't need globals. Next code seem to be similar to what You need:
/**
 * @property string $shard Shard defining suffix to be added to table name.
 */
class ShardedActiveRecord extends CActiveRecord
{
    private $_shard;

    public function tableName(){
        return get_class($this) . '_' . $this->shard;
    }

    public function setShard($shard) {
        $this->_shard = $shard;
        return $this;
    }

    public function getShard() {
        //Just to have meaningful default behavior
        if($this->_shard === null){
            $this->_shard = 1;
        }
        return $this->_shard;
    }
}


class Model extends ShardedActiveRecord{
    /**
     * @static
     * @return Model
     */
    public static function model(){
        return parent::model(__CLASS__);
    }
}

$recordsFromShardOne = Model::model()->setShard(1)->findAll();

$model = new Model();
$model->shard = 2;

//do other stuff

1

#9 User is offline   kernel 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 91
  • Joined: 22-November 10

Posted 29 January 2012 - 04:12 AM

View PostYurko, on 29 January 2012 - 03:14 AM, said:

Why should it be in such a strange manner? You don't need globals. Next code seem to be similar to what You need:
/**
 * @property string $shard Shard defining suffix to be added to table name.
 */
class ShardedActiveRecord extends CActiveRecord
{
    private $_shard;

    public function tableName(){
        return get_class($this) . '_' . $this->shard;
    }

    public function setShard($shard) {
        $this->_shard = $shard;
        return $this;
    }

    public function getShard() {
        //Just to have meaningful default behavior
        if($this->_shard === null){
            $this->_shard = 1;
        }
        return $this->_shard;
    }
}


class Model extends ShardedActiveRecord{
    /**
     * @static
     * @return Model
     */
    public static function model(){
        return parent::model(__CLASS__);
    }
}

$recordsFromShardOne = Model::model()->setShard(1)->findAll();

$model = new Model();
$model->shard = 2;

//do other stuff



The point is:

IN THE Process OF CActiveRecord initiation, the __construct() or ::model() method will call tableName() immediately to read the table meta info , which give no chance to call setShard($shard), you will have to

First:

$ar = new ShardedActiveRecord(); <- In this inside __construct() tableName() will be called before setShard($shard) take place

Then:

$ar->setShard($shard);

================

I not sure if set table name after new ShardedActiveRecord() will work, It's not tested yet.
0

#10 User is offline   Yurko 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 3
  • Joined: 29-January 12
  • Location:Ukraine, Kyiv

Posted 29 January 2012 - 04:23 AM

I looked through the code in different places, and I think it should work with such an addition

/**
 * @property string $shard Shard defining suffix to be added to table name.
 */
class ShardedActiveRecord extends CActiveRecord
{
    private $_shard;

    public function tableName(){
        return get_class($this) . '_' . $this->getShard();
    }

    public function setShard($shard) {
        $this->_shard = $shard;
        call_user_func(array(get_class($this), 'model'))->_shard = $shard;
        $this->refreshMetaData();
        return $this;
    }

    public function getShard() {
        //Just to have meaningful default behavior
        if($this->_shard === null){
            $this->setShard(1);
        }
        return $this->_shard;
    }
}


You may also play with getMetaData() and getTableSchema() to make it return different values depending on current tableName() value;
1

#11 User is offline   Yurko 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 3
  • Joined: 29-January 12
  • Location:Ukraine, Kyiv

Posted 29 January 2012 - 05:24 AM

I've edited code above after some testing. Now it seems to work. :)
1

#12 User is offline   kernel 

  • Junior Member
  • Pip
  • Yii
  • Group: Members
  • Posts: 91
  • Joined: 22-November 10

Posted 29 January 2012 - 07:52 AM

Thanks Yurko, I'll try it out :)
0

#13 User is offline   Sumic 

  • Newbie
  • Yii
  • Group: Members
  • Posts: 6
  • Joined: 30-August 11

Posted 09 April 2012 - 03:03 AM

i got the same problem here my code
class AutoPay extends CActiveRecord
{
	public $tname = '';

	public function __construct($tname = '',$scenario='insert')
	{
		
		$this->tname = $tname;
		
		parent::__construct($scenario='insert');
		
	}
	/**
	 * Returns the static model of the specified AR class.
	 * @param string $className active record class name.
	 * @return Pay the static model class
	 */
	public static function model($className=__CLASS__)
	{
		return parent::model($className);
	}

	/**
	 * @return string the associated database table name
	 */
	public function tableName()
	{
		echo $this->tname;exit;
		return '{{'.$this->tname.'}}';
	}


error:Fatal error: Maximum function nesting level of '512' reached, aborting!
0

#14 User is offline   Giancarlo 

  • Standard Member
  • PipPip
  • Yii
  • Group: Members
  • Posts: 242
  • Joined: 20-December 11
  • Location:Turin, Italy

Posted 18 May 2012 - 10:35 AM

I have reached your own conclusion,
and the same error :-)


	private $tab = 'experiments';
/*	
	public function __construct($scenario) {
		$this->tab = 'well_it_works';		
		parent::__construct($scenario); // chiamo il costruttore padre
	}	
*/
	
	public function __construct($table = 'table_test',$scenario='search')
	{
		$this->tab = $table;
		parent::__construct($scenario); // chiamo il costruttore padre
	}



Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 261900 bytes) in /var/www/yii-1.1.9.r3527/framework/db/ar/CActiveRecord.php on line 48
Posted Image Non preoccuparti, รจ dentro il monitor!

Sapevi che cercando su google yii + "la funzione su cui stai impazzendo", trovi quasi sempre dei buoni indizi in italiano, per risolvere i tuoi problemi, senza perdere tempo a postare?
0

Share this topic:


Page 1 of 1
  • You cannot start a new topic
  • You cannot reply to this topic

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users