1.背景

1.1组合支付支付方式过多,一一枚举过于繁琐,故采用此方案

2.使用

2.1 单种支付方式一一列举,现金=1/信用卡=2/储蓄卡=4/余额=8/扫码=16—-按照2的0次方/1次方等顺序排列

2.2 对应的现金+信用卡方式就是1+2=3,数据库支付方式字段存值为3

2.3如果想查出来所有订单里包含现金支付的订单 需要这样写 whereRaw(‘(pay_type & 1) > 0’)

2.4 如果想查出来这个订单都包含什么支付方式 需要这样写–返回数组[1,2,4]

function decomposeToPowersOfTwo($number)
{
    $powers =[];
    $power =0;
    while ($number > 0) {
        if ($number & 1) {
            $powers[] = pow(2, $power);
        }
        $number = $number >> 1;
        $power++;
    }
    return $powers;
}

/**
 * 获取组合方式里面多种支付方式的值
 * @param string $number 组合方式相加的和
 * @param string $payTypeNumber 支付方式几种
 * @return array|string
 */
function getPayType($number,$payTypeNumber)
{
    // 假设有五种支付方式--数组里面有X位,求出5-X的值,就是需要补全的位数,补全在数组的前面,全部补0
    //如果第一位是0就没有2次方最大的那个支付方式,是1就是有

    // 二进制位数验证
    $twoNum = (string)decbin($number);
    $binLength = strlen($twoNum);
    if ($payTypeNumber < $binLength) {
        throw new \Exception("参数 payTypeNumber 必须大于或等于组合值的二进制长度(当前二进制长度为 {$binLength})");
    }

    $twoNum = array_reverse(str_split($twoNum));

    $x = $payTypeNumber - count($twoNum);

    $totalArray = array_merge(array_fill(0, $x, 0), $twoNum);
    $payArray = [];
    for ($i = 0; $i < count($totalArray); $i++) {
        if ($totalArray[$i] == 1) {
            // 写成2的多少次方
            $payArray[] = pow(2, $payTypeNumber - $i-1);
        }
    }
    return  $payArray;
}

2.5 查现金+信用卡支付

->whereRaw(‘pay_type & 3 = 3’) // 3 = 1 + 2