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.
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.
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.
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.
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
Can you normalize the database table and use single table inheritance?
http://www.yiiframework.com/wiki/198/single-table-inheritance/
That still need to create specific classes for different shards in my point:(
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.zend.com/manual/en/zend.db.table.html
which give flexibilities.
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.
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;
I’ve edited code above after some testing. Now it seems to work.
Thanks Yurko, I’ll try it out
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!
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