分类 php_function 下的文章

  • array_diff_assoc2
array_diff_assoc 在比对两个带key的数组时, 如果右边的数组没有对应的key, 左边对应的key是数组, 那没事, 不然就会转换左边的内容为字符串带来警告
function array_diff_assoc2($array, $array2)
{
    $d = [];
    foreach ($array as $key => $item) {
        if (array_key_exists($key, $array2)) {
            if (is_array($item)) {
                if (is_array($array2[$key])) {
                    if ($item != $array2[$key]) {
                        $d[$key] = $item;
                    }
                } else if (
                    (strpos($array2[$key], '[') === false 
                        && strpos($array2[$key], '{') === false)
                    || $item != json_decode($array2[$key], true)
                ) {
                    $d[$key] = $item;
                }
            } else if (is_array($array2[$key])) {
                if ($item != json_encode($array2[$key], 256)) {
                    $d[$key] = $item;
                }
            } else if ($item . '' != $array2[$key] . '') {
                $d[$key] = $item;
            }
        } else {
            $d[$key] = $item;
        }
    }
    return $d;
}
  • json_encode [php特殊环境下无法使用该方法的过度办法]
function json_encodes($arr)
{
    $parts = array();
    $is_list = false;
    //Find out if the given array is a numerical array
    if (is_array($arr)) {
        $keys = array_keys($arr);
        $max_length = count($arr) - 1;
        if (
            !is_null($keys)
            && array_key_exists('0', $keys)
            && ($keys [0] === 0)
            && ($keys [$max_length] === $max_length)) { //See if the first key is 0 and last key is length - 1
            $is_list = true;
            for ($i = 0; $i < count($keys); $i++) { //See if each key correspondes to its position
                if ($i != $keys [$i]) { //A key fails at position check.
                    $is_list = false; //It is an associative array.
                    break;
                }
            }
        }
        foreach ($arr as $key => $value) {
            if (is_array($value)) { //Custom handling for arrays
                if ($is_list)
                    $parts [] = json_encodes($value); /* :RECURSION: */
                else
                    $parts [] = '"' . $key . '":' . json_encodes($value); /* :RECURSION: */
            } else {
                $str = '';
                if (!$is_list)
                    $str = '"' . $key . '":';
                //Custom handling for multiple data types
                if (is_numeric($value) && $value === $value * 1) {
                    $str .= $value;
                } elseif ($value === false)
                    $str .= 'false'; //The booleans
                elseif ($value === true)
                    $str .= 'true';
                elseif ($value === null)
                    $str .= 'null';
                else
                    $str .= '"' . addslashes($value) . '"'; //All other things
                // :TODO: Is there any more datatype we should be in the lookout for? (Object?)
                if (is_string($str)) {
                    $str = str_replace(PHP_EOL, '\r\n', $str);
                }
                $parts [] = $str;
            }
        }
    }

    $json = implode(',', $parts);
    if ($is_list)
        return '[' . $json . ']'; //Return numerical JSON
    return '{' . $json . '}'; //Return associative JSON
}

  • 数组部分
将原数组倒序 array_reverse()
  • 移除数值无意义的0
$num = '0.123456789012345678900000000000';
echo rtrim(rtrim($num, '0'), '.');

function numToWord($num)
{
    $chiNum = array('零', '一', '二', '三', '四', '五', '六', '七', '八', '九');
    $chiNum['-'] = '负';
    $chiNum['+'] = '正';
    $chiUni = array('', '十', '百', '千', '万', '亿', '十', '百', '千');
    $num_str = (string)$num;
    $count = strlen($num_str);
    $last_flag = true; //上一个 是否为0
    $zero_flag = true; //是否第一个
    $temp_num = null; //临时数字
    $chiStr = '';//拼接结果
    if ($count == 2) {//两位数
        $temp_num = $num_str[0];
        $chiStr = $temp_num == 1 ? $chiUni[1] : $chiNum[$temp_num] . $chiUni[1];
        $temp_num = $num_str[1];
        $chiStr .= $temp_num == 0 ? '' : $chiNum[$temp_num];
    } else if ($count > 2) {
        $index = 0;
        for ($i = $count - 1; $i >= 0; $i--) {
            $temp_num = $num_str[$i];
            if ($temp_num == 0) {
                if (!$zero_flag && !$last_flag) {
                    $chiStr = $chiNum[$temp_num] . $chiStr;
                    $last_flag = true;
                }
            } else {
                $chiStr = $chiNum[$temp_num] . $chiUni[$index % 9] . $chiStr;
                $zero_flag = false;
                $last_flag = false;
            }
            $index++;
        }
    } else {
        $chiStr = $chiNum[$num_str[0]];
    }
    return $chiStr;
}
$num = -44;
echo numToWord($num);

输出

负四十四

今天无语中查了下阿里云虚拟主机的访问历史, 发现之前使用WordPress被莫名其妙的写入一堆英文的文章的原因查到了, 登录接口被暴力破解导致的, 所有时间比较急, 就写了个简单的POST请求的安全控制的代码, 使用也很简单, 直接在程序入口直接require 这个文件即可, 需要保证这个配置文件定义的限流锁文件保存路径具有写权限

可以看出, 一个登录请求了那么多次, 没办法, 紧急写了个比较粗糙的代码

<?php

// 简单的全局请求安全限制接口
class RequestLimit
{

    protected $configFilePath = 'request_limit.lock';
    protected $config = [
        'GET' => [],// 定义需要限流的类型, 如果不想写配置, 那么就默认以default配置为准
    ];
    protected $default = [
        'rate' => '10/60|20/600|30/3600|100/43200|200/86400', // 限制10次/60s, 20次/10分钟, 30次一小时
        'try_cont' => 0,
        'save_history_count' => 100, // 保留历史条数
        'try_history' => [],
    ];

    public function __construct()
    {
        if (file_exists($this->configFilePath)) {
            $this->config = json_decode(file_get_contents($this->configFilePath), true);
        }
    }

    public function handle($method)
    {
        if (!array_key_exists($method, $this->config)) {
            return;
        }
        if (empty($this->config[$method])) {
            $this->config[$method] = $this->default;
        }
        $this->config[$method]['try_history'] = empty($this->config[$method]['try_history']) ? [] : $this->config[$method]['try_history'];
        // 再次请求频率判断, 通过才让继续
        foreach (explode('|', $this->config[$method]['rate']) as $item) {
            [$x, $y] = explode('/', $item);
            if (!empty($this->config[$method]['try_history'][$x - 1]) && $this->config[$method]['try_history'][$x - 1] + $y >= time()) {
                header('HTTP/1.1 429 Too Many Requests');
                echo '429 Too Many Requests';
                exit;
            }
        }
        if (empty($this->config[$method]['save_history_count'])) {
            $this->config[$method]['save_history_count'] = 100;
        }
        array_unshift($this->config[$method]['try_history'], time());
        $this->config[$method]['try_history'] = array_slice($this->config[$method]['try_history'], 0, $this->config[$method]['save_history_count']);
        $this->config[$method]['try_cont'] = empty($this->config[$method]['try_cont']) ? 1 : $this->config[$method]['try_cont'] + 1;
        $this->saveConfig();
    }

    public function saveConfig()
    {
        file_put_contents($this->configFilePath, json_encode($this->config, 256));
    }
}

$q = new RequestLimit();
$q->handle($_SERVER['REQUEST_METHOD']);