我有一个Yii2模型,它使用多个具有相同结构的表。表名将根据登录的用户而变化,表名非常独特,取决于用户名。如何动态地将此表名分配给模型?到目前为止我已经这样做了。
在我的模特中:
protected $table;
public function __construct($table)
{
$this->table='custom_risk_assignment_table';//logic to obtain the table name goes here
}
public static function tableName()
{
return $this->table;
}
但这样做会导致错误Using $this when not in object context
,因为function tableName()
是static
函数。
我怎么能这样做呢?任何帮助表示赞赏。谢谢!
编辑:详细图片
假设我有ABC公司的用户。我的应用程序中有很多进程,比如PQR就是其中之一。如果ABC公司的用户登录并选择进程PQR,我需要在我的数据库中创建一个表ABC_PQR(如果不存在),或者如果已经创建了表,则加载该表。我需要将这个表名放入我的模型中。同样可能有用户和许多进程。管理数据库的最佳方法是什么。
答案 0 :(得分:5)
由于tableName
是静态方法(正是错误消息所说的),因此您无法访问非静态属性。 (您无法使用$this
关键字)
所以你必须声明一个静态属性:
protected static $table;
public function __construct($table)
{
self::$table = $table;
}
public static function tableName()
{
return self::$table;
}
/* UPDATE */
public static function setTableName($table)
{
self::$table = $table;
}
更新:
好的,我的错。如果您调用updateAll
,find
等静态方法,则不会调用构造函数。$table
将不会被设置。所以你有不同的选择。
public static function setTableName($tableName)
,并在每次成功登录时调用它。答案 1 :(得分:1)
在没有黑客的情况下摆脱这种情况的一种方法是不改变tableName
的返回值,而是为不同的表使用不同的类。这些类只会在tableName
:
abstract class Foo extends ActiveRecord
{
// your existing code goes here
abstract function tableName();
}
class FooOne extends Foo
{
function tableName() { return 'table1'; }
}
class FooTwo extends Foo
{
function tableName() { return 'table2'; }
}
然后,在您的应用中的某个适当位置,您将决定要使用哪个表并记住该表的模型。类似的东西:
if ($username == "anne") {
$fooModel = new FooOne();
}
else if ($username == "bob") {
$fooModel = new FooTwo();
}
在此之后,您只需使用$fooModel
作为调用目标,查询将自动影响相应的表。例如:
$foos = $fooModel::findAll();
答案 2 :(得分:0)
这个问题已经存在很长时间了,但是我只是看到了这个问题并提出了一些想法,希望对以后的人们有所帮助。
通过构造函数动态设置表名并不友好。我们可以通过设置工厂方法来绑定表名,例如:
class MyTableModel extends \yii\db\ActiveRecord {
protected static $table;
public static function useTable($table) {
static::$table = $table;
return new static();
}
public static function tableName() {
return static::$table;
}
}
使用时,通过useTable
绑定表名称,例如:
// find
MyTableModel::useTable('tableName1')::find()->where(...)->all(); // use tableName1
MyTableModel::useTable('tableName1')::findAll(); // use tableName1
MyTableModel::useTable('tableName1')::updateAll(); // use tableName1
MyTableModel::useTable('tableName2')::findAll(); // use tableName2
// create
$table = MyTableModel::useTable('tableName2');
$table->attributes = $attributes;
$table->save()
使用useTable
方法来实现完全绑定的目标。
请注意,这不是用闭包完成的,而是设置MyTableModel::$table
静态变量的值。因此,多次调用useTable
将使用最后设置的值