# 前提
`已废弃: 不要随便修改底层框架`

基于 [分表功能开发(初步)](./分表功能开发(初步)-hyperf版本.md) 缺陷。只能应付于简单的 Model 操作行为
```
VirtualRelation::where( 'brand_id', $brand_id )
    ->where( 'virtual_sn', $this->codeBaseInfo[ 'virtual_sn' ] )
    ->where( 'status', 1 )
    ->count();
```

但对于 联表的情况
```
WarehousingCode::query()
    ->leftJoin('fch_warehousing as w','fch_warehousing_code.warehousing_sn', '=', 'w.warehousing_sn')
    ->where('fch_warehousing_code.brand_id', $brandId)
    ->where('w.brand_id', $brandId)
    ->get();

// 或者
// 出库检查
$codeQuery = OutWarehousingCode::query()
    ->where( 'fch_out_warehousing_code.brand_id', $this->brandId )
    ->where( 'fch_out_warehousing.out_warehousing_from_id', $this->dealerId )
    ->where( 'fch_out_warehousing.brand_id', $this->brandId )
    ->leftJoin('fch_out_warehousing', 'fch_out_warehousing_code.out_warehousing_sn', '=', 'fch_out_warehousing.out_warehousing_sn');

```
如果两个表同时需要分表的情况下，这样 第一版的方案就不生效. 获取 如果 where 中写 `表名.xx`. 这样分表的情况下会指向原表，直接就报错了


# 优化点
## 依赖包
[hyperf/database]() - v2.2.0 版本

## Hyperf\Database\Model\Model 修改
```
// 增加 分表数据数组
protected $shardingTableInfo = [];

// 用于 在 app Model 层进行设置。这样就可以提供自定义分表数据
public function setShardingTableInfo($shardingData)
{ 
    $this->shardingTableInfo = $shardingData;
    return $this;
}

// getQueryGrammar() - 指向SQL 生成的实例
// shardingTableInfo() 方法 - 为分表数据添加方法
protected function newBaseQueryBuilder()
{
    $connection = $this->getConnection();
    if (!empty($this->shardingTableInfo)) {
        $connection->getQueryGrammar()->shardingTableInfo($this->shardingTableInfo);
    }

    return new QueryBuilder($connection, $connection->getQueryGrammar(), $connection->getPostProcessor());
}
```

## Hyperf\Database\Grammar 修改
```
// 分表数据
protected $shardingTableInfo = [];

// 添加分表数据
public function shardingTableInfo($data)
{
    $this->shardingTableInfo = $data;
    return $this;
}

// 表名统一处理方法
public function wrapTable($table)
{
    if (! $this->isExpression($table)) {
        if (!empty($this->shardingTableInfo)) {
            $table = $this->setShardingTableInfo($table);
        }
        return $this->wrap($this->tablePrefix . $table, true);
    }

    return $this->getValue($table);
}

// 分表数据处理
private function setShardingTableInfo($table)
{
    if (!empty($this->shardingTableInfo)) {
        if (stripos($table, ' as ') !== false) {
            $pos = stripos($table, ' as ');
            
            $preTable = substr($table, 0, $pos);
            if (isset($this->shardingTableInfo[$preTable])) {
                return $this->shardingTableInfo[$preTable].substr($table, $pos);
            }
            return $table;
        }
        return isset($this->shardingTableInfo[$table]) ? $this->shardingTableInfo[$table] : $table;
    }
}
    
```

## App\Model\Model
```
// 所有分表的数据，写入
public function __construct()
{
    $brandAuth = get_auth_brand();
    if ($brandAuth) {
        $brandId = $brandAuth->brandId();
        $this->setShardingTableInfo([
            $this->getTable() => $this->getTable() . '_' . $brandId, 'fch_warehousing' => 'fch_warehousing_111'
        ]);
        
    }
    parent::__construct();
}
```

## 最终效果
```
WarehousingCode::query()
    ->leftJoin('fch_warehousing as w','fch_warehousing_code.warehousing_sn', '=', 'w.warehousing_sn')
    ->where('fch_warehousing_code.brand_id', $brandId)
    ->where('w.brand_id', $brandId)
    ->toSql();
```

没有分表的情况
```
select * from `ydd_fch_warehousing_code` left join `ydd_fch_warehousing` as `ydd_w` on `ydd_fch_warehousing_code`.`warehousing_sn` = `ydd_w`.`warehousing_sn` where `ydd_fch_warehousing_code`.`brand_id` = ? and `ydd_w`.`brand_id` = ? and `ydd_fch_warehousing_code`.`deleted_at` is null

```

开启分表后的情况
```
select * from `ydd_fch_warehousing_code_1111` left join `ydd_fch_warehousing_111` as `ydd_w` on `ydd_fch_warehousing_code_1111`.`warehousing_sn` = `ydd_w`.`warehousing_sn` where `ydd_fch_warehousing_code_1111`.`brand_id` = ? and `ydd_w`.`brand_id` = ? and `ydd_fch_warehousing_code_1111`.`deleted_at` is null

```