Yii 2自動分表モデル

5797 ワード

実はある同級生の「ダイナミックモデル」を参考にしました
redis;
        if($redis->sismember(static::$tableSetKey, $tableName))
            return $tableName;

        //if hit db
        $db = static::getDb();
        if($db->createCommand("SHOW TABLES LIKE '{$tableName}'")->queryAll()){
            $redis->sadd(static::$tableSetKey, $tableName);
            return $tableName;
        }else{ //maybe
            $redis->srem(static::$tableSetKey, $tableName);
        }

        //just do it
        $originalTable = static::$originalName;
        $createTableRet = $db->createCommand("SHOW CREATE TABLE `{$originalTable}`")->queryOne();
        $createTable = str_replace("`{$originalTable}`","`{$tableName}`",$createTableRet['Create Table']);
        $createTable = preg_replace('/\sAUTO_INCREMENT=\d+/','',$createTable);
        try{
            $db->createCommand($createTable)->execute();
            $redis->sadd(static::$tableSetKey, $tableName);
        }catch (Exception $ex){
            throw new Exception("Error execute sql: {$createTable}");
        }

        return $tableName;

    }

    /**
     *    find
     * @param $targetKey
     * @return \yii\db\ActiveQuery
     */
    public static function findx($targetKey = null){
        static::$tableName = static::renderTable($targetKey);
        return Yii::createObject(ActiveQuery::className(), [get_called_class(), ['from' => [static::tableName()]]]);
    }

    /**
     *    findAll
     * @param null $targetKey
     * @param array $params
     * @return \yii\db\ActiveQuery[]
     */
    public static function findAllx($targetKey = null,$params = []){
        return static::findByConditionx($targetKey, $params)->all();
    }

    /**
     * @Override
     * @param array $row
     * @return static
     */
    public static function instantiate($row){
        return new static(static::$targetKey);
    }

    /**
     *     findBySql
     * @param string $sql
     */
    public static function findBySql($sql){
        throw new InvalidCallException("not allowed. {$sql}");
    }

    /**
     *    findOne
     * @param null $targetKey
     * @param array $condition
     * @return null|static|ActiveQuery
     */
    public static function findOnex($targetKey = null, $condition = []){
        return static::findByConditionx($targetKey, $condition)->one();
    }

    /**
     *     
     * @param null $targetKey
     * @param $condition
     * @return ActiveQuery[]|ActiveQuery
     * @throws InvalidConfigException
     */
    protected static function findByConditionx($targetKey = null, $condition){

        $query = static::findx($targetKey);

        if (!ArrayHelper::isAssociative($condition)) {
            // query by primary key
            $primaryKey = static::primaryKey();
            if (isset($primaryKey[0])) {
                $condition = [$primaryKey[0] => $condition];
            } else {
                throw new InvalidConfigException('"' . get_called_class() . '" must have a primary key.');
            }
        }

        return $query->andWhere($condition);
    }

}

サブテーブルモデル
where([]);
 * @use Test::findAllx($vip_card,[]);
 * @use Test::findOnex($vip_card,[]);
 *
 */

class Test extends Modelx
{
    //    ,     
    protected static $originalName = 'test';
    //redis  set key
    protected static $tableSetKey = 'project:tableset';

    /**
     *            
     * @Override
     * @return string
     */
    public static function getTableName(){
        return static::$originalName . '_'. (static::$targetKey % 10);
    }


}

サブテーブルは元のテーブルをテンプレートとして使用して構造コピーを行い、コピーしたサブテーブル構造は、元のテーブルの構造、インデックスなどの変更を同期しません.
表を分割して使用する前に、元の表を十分に最適化することをお勧めします.
サブテーブル後のModelではfindBySqlメソッドはサポートされていません.