Yii2中的动态表名称

时间:2014-05-09 07:16:16

标签: php oop yii2

我有一个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(如果不存在),或者如果已经创建了表,则加载该表。我需要将这个表名放入我的模型中。同样可能有用户和许多进程。管理数据库的最佳方法是什么。

3 个答案:

答案 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;
}

更新:

好的,我的错。如果您调用updateAllfind等静态方法,则不会调用构造函数。$table将不会被设置。所以你有不同的选择。

  1. 在使用静态db操作方法之前手动调用构造函数。
  2. 向模型添加静态设置器,如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将使用最后设置的值