首页 > 解决方案 > 如何在 Yii2 中创建一个模型,每个月都增加表

问题描述

我有一个考勤系统,每个月都会增加一张桌子。比如 2020 年 4 月表的名称是 att202004,2020 年 5 月表的名称是 att202005 等等。如您所知,Yii2 中的模型名称和命名文件是静态的,我每个月都必须创建新模型。如何创建一个模型来处理所有月份的出勤情况。TQ

标签: phpdatabasemodelyii2frameworks

解决方案


如果您只需要为有限数量的表创建模型,例如仅针对当前月份,您可以使用事实,即表名是在静态方法中定义的,因此您可以拥有动态表名。

class CurrentMonth extends yii\db\ActiveRecord
{
    public static function tableName()
    {
        return 'att' . date('Ym');
    }

    //... other definitions
}

如果您需要为每个现有表创建模型,您可以使用自动加载器动态创建类。

在 autoload.php 中实现并注册您的自动加载器。在这个例子中,我将假设表被命名为 likeatt202005并且创建的模型将是\app\dynamicModels\Att202005.

class DynamicModelFactory
{
    protected static function classBasename($class)
    {
        $split = explode('\\', $class);
        return end($split);
    }

    public static function autoload($class)
    {
        if (strpos($class, 'app\\dynamicModels') !== 0) {
            //skip if the class is not in app\dynamicModels namespace
            return;
        }

        $className = static::classBasename($class);
        //get table name from class name by converting the first letter to lower case
        $tableName = lcfirst($className);

        $template = static::template();
        $template = str_replace(
            ['{className}', '{tableName}'],
            [$className, $tableName],
            $template
        );

        eval($template);
    }

    protected static function template()
    {
        $code = <<<CODE
namespace app\dynamicModels;

class {className} extends \yii\db\ActiveRecord
{
    public static function tableName()
    {
        return '{tableName}';
    }
}
CODE;
        return $code;
    }
}

spl_autoload_register(['DynamicModelFactory', 'autoload']);

然后修改你的 index.php 以在 Yii 自动加载器之前要求这个自动加载脚本:

require __DIR__ . '/../vendor/autoload.php';
require __DIR__ . '/autoload.php'; // <- this is our autoloader
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';

如果您需要模型类更复杂的代码,您可以将其放入独立文件并加载它,file_get_content而不是直接放入自动加载器类中。您还可以添加代码,如果您愿意,可以在创建模型类之前检查数据库中表的存在。


推荐阅读