input type="range" 滑块

[type="range"] {
            border:none !important;
            outline: none !important;
            -webkit-appearance: none;
            appearance: none;
            margin: 0;
            background-color: transparent;
            width: 500px;
        }
        [type="range"]::-webkit-slider-runnable-track {
            height: 4px;
            background: #eee;
        }
        [type="range" i]::-webkit-slider-container {
            height: 20px;
            overflow: hidden;
        }
        [type="range"]::-webkit-slider-thumb {
            -webkit-appearance: none;
            appearance: none;
            width: 20px;
            height: 20px;
            border-radius: 50%;
            background-color: #f44336;
            border: 1px solid transparent;
            margin-top: -8px;
            border-image: linear-gradient(#f44336,#f44336) 0 fill / 8 20 8 0 / 0px 0px 0 2000px;
        }
<input type="range" name="salary" class="form-control mb-3" step="10" min="1000" max="50000">

效果图
2023-03-11T14:18:43.png

PHP日志记录函数2

//创建日志保存所需目录
function make_dir($folder)
{
    $reval = false;
    if(!file_exists($folder))
    {
        /* 如果目录不存在则尝试创建该目录 */
        @umask(0);
        /* 将目录路径拆分成数组 */
        preg_match_all('/([^\/]*)\/?/i', $folder, $atmp);
        /* 如果第一个字符为/则当作物理路径处理 */
        $base = ($atmp[0][0] == '/') ? '/' : '';
        /* 遍历包含路径信息的数组 */
        foreach ($atmp[1] AS $val)
        {
            if ('' != $val)
            {
                $base .= $val;
                if ('..' == $val || '.' == $val)
                {
                    /* 如果目录为.或者..则直接补/继续下一个循环 */
                    $base .= '/';
                    continue;
                }
            }
            else
            {
                continue;
            }
            $base .= '/';
            if (!file_exists($base))
            {
                /* 尝试创建目录,如果创建失败则继续循环 */
                if (@mkdir(rtrim($base, '/'), 0777))
                {
                    @chmod($base, 0777);
                    $reval = true;
                }
            }
        }
    }
    else
    {
        /* 路径已经存在。返回该路径是不是一个目录 */
        $reval = is_dir($folder);
        /** 如果是文件夹,则强制改为0777 **/
        if($reval){ @chmod($folder, 0777); }
    }
    clearstatcache();
    return $reval;
}
//生成日志文件,并设置权限777
function chmod_custom($filename, $mode = 0777)
{
    return file_exists($filename)? chmod($filename, $mode) : FALSE;
}

//写入日志
function log_message($level = 'error', $message, $dir_path = '', $file_affix = '')
{
    // 验证允许记录的日志类型
    $level = strtoupper($level);

    $dir_path = trim($dir_path);
    $dir_path = storage_path("logs/{$dir_path}");
    // 如果创建文件夹失败,则返回FALSE
    
    if(!make_dir($dir_path)){
        return FALSE;
    }

    $cache_file_path = $dir_path . '/' . $file_affix. '.log';
    /** 如果文件已存在,则强制改为可写状态 **/
    chmod_custom($cache_file_path, 0777);
    $message =  $level . ' - ' . date('Y-m-d H:i:s') . ' --> ' . $message . "\r\n";
    return file_put_contents($cache_file_path, $message, FILE_APPEND | LOCK_EX);
}

MySQL死锁排查

查询正打开的表

show OPEN TABLES where In_use > 0;

查询正在进行的进程

show processlist;

查看当前运行的所有事务

select * from information_schema.INNODB_TRX;

查看存储引擎的状态

show engine innodb status

查询死锁表

-- 查询死锁表 8.0之前
SELECT * from INFORMATION_SCHEMA.INNODB_LOCKS;

-- 查询死锁等待时间 8.0之前
select * from information_schema.INNODB_LOCK_waits;

-- 查询死锁表 8.0之后
select * from performance_schema.data_locks;
-- 查询死锁等待时间 8.0之后
select * from performance_schema.data_lock_waits;

编写shell脚本快速切换PHP版本

由于我是在windows的wsl搭建的PHP环境,包括7.3、7.4、8.0多个PHP版本,测试的时候,有的程序需要某个版本才能运行,手动创建环境变量太麻烦,于是写了我的第一个shell,于是记录下

#!/bin/bash
#第一次提示
read -p "请输入版本号【7.3】、【7.4】、【8】:" version

#如果未输入,则强制要求输入
while [ ! "$version" ]
        do
        if [ ! -n "$version" ]; then
                read -p "必须输入版本号【7.3】、【7.4】、【8】:" version
        fi
done


#先删除现在的环境
rm -rf /usr/bin/php
rm -rf /usr/bin/phpize
rm -rf /usr/bin/php-fpm

#根据输入的版本号创建新的环境变量
case $version in
        7.3)
                #echo "你输入了${version} (7.3 对吗?)"
                ln -s  /usr/local/php/bin/php /usr/bin/php
                ln -s  /usr/local/php/bin/phpize /usr/bin/phpize
                ln -s  /usr/local/php/sbin/php-fpm /usr/bin/php-fpm
        ;;
        7.4)
                #echo "你输入了${version}(7.4对吗)"
                ln -s  /usr/php/74/bin/php /usr/bin/php
                ln -s  /usr/php/74/bin/phpize /usr/bin/phpize
                ln -s  /usr/php/74/sbin/php-fpm /usr/bin/php-fpm
        ;;
        8)
                #echo "你输入了${version}(8对吗)"
                ln -s  /usr/local/php8/bin/php /usr/bin/php
                ln -s  /usr/local/php8/bin/phpize /usr/bin/phpize
                ln -s  /usr/local/php8/sbin/php-fpm /usr/bin/php-fpm
        ;;
        *)
                echo "当前系统未安装此版本号的PHP,无法切换"
        ;;
esac

#检查下是否成功切换
        echo "你已成功切换到${version}"![微信截图_20211029113209.png][1]
        echo "======================================================"
                php -v
        echo "======================================================"

请输入图片描述

PHP 表格导入时间字段处理

使用 PhpOffice 导入 2020/1/1 这类的格式 的时候 最终获取到的 是 45000 类的数字,要将数组转为实际的日期

在excel中:40847对应2011-10-31,是日期的数值型表现形式。
在PHP中,echo date('Y-m-d H:i:s',40847);//结果1970-01-01 11:52:30

原因:

PHP 的时间函数是从1970-1-1日开始计算的,单位是秒数。但是 EXCEL的是从1900-1-1日开始算的单位是天数。
如果只计算1970以后的时间的话,就好处理了。
先获得 EXCEL中 1970-1-1 代表的数字,我查了是25569。
现在要把excel中的40947,在php中用函数正确的显示出来
代码如下:

  $time = (42747 – 25569) * 24*60*60; //获得秒数
  echo date('Y-m-d', $time);   //出来 2020-01-31

解决TP5在命令行创建文件没有权限写入的方法

例如workerman指定user为www运行
在cli模式下创建的文件是root权限的,无法写入log导致程序无法执行

找到 thinkphp\library\think\log\driver\File.php 文件
write 方法中 最后一行添加以下代码

try {
//判断操作文件不是0777权限 就修改
if (substr(base_convert(fileperms($destination),10,8),-4) != '0777') {
  chmod($destination, 0777);
}
            
} catch (\Exception $e) {

}

php生成 ssl 证书

<?php 
//需要开启 openssl 扩展
$privkeypass = 'qqpp123cqs'; //私钥密码

$config = array(
    "private_key_bits" => 1024,                     //字节数    512 1024  2048   4096 等
    "private_key_type" => OPENSSL_KEYTYPE_RSA,     //加密类型
    // "config" => "D:/phpStudy/PHPTutorial/Apache/conf/openssl.cnf"  //注意 openssl.cnf 文件所在位置
);

$privkeypass = $privkeypass;
$numberofdays = 365;     //有效时长
$cerpath = "./test.cer"; //生成证书路径
$pfxpath = "./test.pfx"; //密钥文件路径

$dn = array(
    "countryName" => "UK",                                  //所在国家
    "stateOrProvinceName" => "Somerset",                    //所在省份
    "localityName" => "Glastonbury",                        //所在城市
    "organizationName" => "The Brain Room Limited",         //注册人姓名
    "organizationalUnitName" => "PHP Documentation Team",   //组织名称
    "commonName" => "Wez Furlong",                          //公共名称
    "emailAddress" => "wez@example.com"                     //邮箱
);

// 生成公钥私钥资源
$res = openssl_pkey_new($config);

// 导出私钥 $priKey
openssl_pkey_export($res, $priKey,null,$config);

//  导出公钥 $pubKey
$pubKey = openssl_pkey_get_details($res);
$pubKey = $pubKey["key"];
//print_r($priKey); 私钥
//print_r($pubKey); 公钥

//直接测试私钥 公钥
echo '-------------------公私钥加解密-START---------------------','<br>';
$data = '测试公私钥加解密成功!';
// 公钥加密
openssl_public_encrypt($data, $encrypted, $pubKey);
// 私钥解密
openssl_private_decrypt($encrypted, $decrypted, $priKey);

echo '公钥加密:',base64_encode($encrypted),'私钥解密:','<br>',$decrypted,'<br>';
echo '-------------------公私钥加解密-END---------------------','<br>';

//生成文件
$csr = openssl_csr_new($dn, $priKey,$config); //基于$dn生成新的 CSR (证书签名请求)
$sscert = openssl_csr_sign($csr, null, $priKey, 365,$config);//根据配置自己对证书进行签名
openssl_x509_export($sscert, $csrkey); //将公钥证书存储到一个变量 $csrkey,由 PEM 编码格式命名。
openssl_pkcs12_export($sscert, $privatekey, $priKey, $privkeypass); //将私钥存储到名为的出 PKCS12 文件格式的字符串。 导出密钥$privatekey

//生成证书文件
$fp = fopen($cerpath, "w");
fwrite($fp, $csrkey);
fclose($fp);
//生成密钥文件
$fp = fopen($pfxpath, "w");
fwrite($fp, $privatekey);
fclose($fp);


echo '<br>','<br>','<br>','<br>';
echo '----------------------自签名验证-START----------------------','<br>';
// 测试私钥 秘钥
$privkeypass = $privkeypass; //私钥密码
$pfxpath = "./test.pfx"; //密钥文件路径
$priv_key = file_get_contents($pfxpath); //获取密钥文件内容
$data = "测试数据!"; //加密数据测试test
//私钥加密
openssl_pkcs12_read($priv_key, $certs, $privkeypass); //读取公钥、私钥
$prikeyid = $certs['pkey']; //私钥
openssl_sign($data, $signMsg, $prikeyid,OPENSSL_ALGO_SHA1); //注册生成加密信息
$signMsg = base64_encode($signMsg); //base64转码加密信息


//公钥解密
$unsignMsg=base64_decode($signMsg);//base64解码加密信息
openssl_pkcs12_read($priv_key, $certs, $privkeypass); //读取公钥、私钥
$pubkeyid = $certs['cert']; //公钥
$res = openssl_verify($data, $unsignMsg, $pubkeyid); //验证
echo $res?'证书测试成功!':'证书测试失败!';echo '<br>'; //输出验证结果,1:验证成功,0:验证失败

echo '-----------------------签名验证-END------------------------','<br>';








function sha1_thumbprint($file)
 {
    $file = preg_replace('/\-+BEGIN CERTIFICATE\-+/','',$file);
    $file = preg_replace('/\-+END CERTIFICATE\-+/','',$file);
    $file = trim($file);
    $file = str_replace( array("\n\r","\n","\r"), '', $file);
    $bin = base64_decode($file);
    return sha1($bin);
 }

$fingerprint = str_replace("SHA1 Fingerprint=", '', system('openssl x509 -noout -in /path/to/your/cert.pem -fingerprint'));

//查看sha1指纹
var_dump(sha1_thumbprint(file_get_contents('./test.cer')));

php批量检测文件bom头

有时候在ajax返回的json数据前多出一些不明的字符,就是所谓的bom头,导致javascript解析json格式失败,下面贴出一段PHP代码实现检测和去除bom头。

<?php
header('content-Type: text/html; charset=utf-8');
if (isset($_GET['dir'])) { //设置文件目录,如果没有设置,则自动设置为当前文件所在目录
    $basedir = $_GET['dir'];
} else {
    $basedir = '.';
}
$auto = 0;/*设置为1标示检测BOM并去除,设置为0标示只进行BOM检测,不去除*/

echo '当前查找的目录为:' . $basedir . '当前的设置是:';
echo $auto ? '检测文件BOM同时去除检测到BOM文件的BOM<br />' : '只检测文件BOM不执行去除BOM操作<br />';

checkdir($basedir);
function checkdir($basedir)
{
    if ($dh = opendir($basedir)) {
        while (($file = readdir($dh)) !== false) {
            if ($file != '.' && $file != '..') {
                if (!is_dir($basedir . '/' . $file)) {
                    echo '文件: ' . $basedir . '/' . $file . checkBOM($basedir . '/' . $file) . ' <br>';
                } else {
                    $dirname = $basedir . '/' . $file;
                    checkdir($dirname);
                }
            }
        }
        closedir($dh);
    }
}

function checkBOM($filename)
{
    global $auto;
    $contents = file_get_contents($filename);
    $charset[1] = substr($contents, 0, 1);
    $charset[2] = substr($contents, 1, 1);
    $charset[3] = substr($contents, 2, 1);
    if (ord($charset[1]) == 239 && ord($charset[2]) == 187 && ord($charset[3]) == 191) {
        if ($auto == 1) {
            $rest = substr($contents, 3);
            rewrite($filename, $rest);
            return (' <font color=red>找到BOM并已自动去除</font>');
        } else {
            return (' <font color=red>找到BOM</font>');
        }
    } else {
        return (' 没有找到BOM');
    }
}

function rewrite($filename, $data)
{
    $filenum = fopen($filename, 'w');
    flock($filenum, LOCK_EX);
    fwrite($filenum, $data);
    fclose($filenum);
}

PHP图片按等比压缩

/**
        * desription 压缩图片
        * @param sting $imgsrc 图片路径
        * @param string $imgdst 压缩后保存路径
        */
    public function compressedImage($imgsrc, $imgdst) {
        list($width, $height, $type) = getimagesize($imgsrc);
        $new_width = $width; //压缩后的图片宽
        $new_height = $height; //压缩后的图片高
        if ($width >= 600) {
            $per = 600 / $width; //计算比例
            $new_width = $width * $per;
            $new_height = $height * $per;
        }
        switch ($type) {
        case 1:
            $giftype = check_gifcartoon($imgsrc);
            if ($giftype) {
                header('Content-Type:image/gif');
                $image_wp = imagecreatetruecolor($new_width, $new_height);
                $image = imagecreatefromgif($imgsrc);
                imagecopyresampled($image_wp, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
                            //90代表的是质量、压缩图片容量大小
                imagejpeg($image_wp, $imgdst, 90);
                imagedestroy($image_wp);
                imagedestroy($image);
            }
            break;
        case 2:
            header('Content-Type:image/jpeg');
            $image_wp = imagecreatetruecolor($new_width, $new_height);
            $image = imagecreatefromjpeg($imgsrc);
            imagecopyresampled($image_wp, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
                     //90代表的是质量、压缩图片容量大小
            imagejpeg($image_wp, $imgdst, 90);
            imagedestroy($image_wp);
            imagedestroy($image);
            break;
        case 3:
            header('Content-Type:image/png');
            $image_wp = imagecreatetruecolor($new_width, $new_height);
            $image = imagecreatefrompng($imgsrc);
            imagecopyresampled($image_wp, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
                     //90代表的是质量、压缩图片容量大小
            imagejpeg($image_wp, $imgdst, 90);
            imagedestroy($image_wp);
            imagedestroy($image);
            break;
        }
    }

微信公众号授权H5登录

第一步

进入微信公众号管理中心配置可信域名和回调域名以及服务器IP白名单

第二步

composer 安装 easywechat

第三步

    //发起授权地址
    public function warranty()
    {
        $config = [
            'app_id' => 'app_id',
            'secret' => 'secret',
            'response_type' => 'array',
        ];
        $app = Factory::officialAccount($config);
        /*return $app->oauth->scopes(['snsapi_userinfo'])->redirect(cdnurl('/visitor_api/user/login',true));*/
        //或者以下方法
        $oauth = $app->oauth;
        $oauth->redirect('您的回调地址')->send();
    }



   //授权成功后的回调地址
    public function login()
    {
        $config = [
            'app_id' => 'app_id',
            'secret' => 'secret',
            'response_type' => 'array',
        ];

        $app = Factory::officialAccount($config);
        $oauth = $app->oauth;
        // 获取 OAuth 授权结果用户信息
        $user = $oauth->user();
        
        dump($user);//打印用户信息 - 参见第四步
   }

第四步(处理用户信息)


object(Overtrue\Socialite\User)#134 (1) {
  ["attributes":protected] => array(10) {
    ["id"] => string(28) "o7Dzs337bEPl_pg886oVTgrab6Wg"
    ["name"] => string(12) "岁暮天寒"
    ["nickname"] => string(12) "岁暮天寒"
    ["avatar"] => string(132) "https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLBVGiayuTS7ptprfHtSfwD43iaXY1Akkz27vq4qNPdxrESAxb9pHwXktCSibH6kE6Tia1RMtZrjgKfag/132"
    ["email"] => NULL
    ["original"] => array(10) {
      ["openid"] => string(28) "o7Dzs337bEPl_pg886oVTgrab6Wg"
      ["nickname"] => string(12) "岁暮天寒"
      ["sex"] => int(1)
      ["language"] => string(5) "zh_CN"
      ["city"] => string(6) "杭州"
      ["province"] => string(6) "浙江"
      ["country"] => string(6) "中国"
      ["headimgurl"] => string(132) "https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLBVGiayuTS7ptprfHtSfwD43iaXY1Akkz27vq4qNPdxrESAxb9pHwXktCSibH6kE6Tia1RMtZrjgKfag/132"
      ["privilege"] => array(0) {
      }
      ["unionid"] => string(28) "ogN8NwK3ZHykG2tVtXHoG9oUEm_w"
    }
    ["token"] => string(89) "46_eD_Ghm0AfLLh54gdDTmvbN-7uIHweXCJbShx5OeBp_skNaPhArO_nEhi3yHJ2gQJK-Yfuk-hsX9vOg6K2AH_BQ"
    ["access_token"] => string(89) "46_eD_Ghm0AfLLh54gdDTmvbN-7uIHweXCJbShx5OeBp_skNaPhArO_nEhi3yHJ2gQJK-Yfuk-hsX9vOg6K2AH_BQ"
    ["refresh_token"] => string(89) "46_dv6nwCx5q3OLoaPtVMIuTiMREHZGcEV9tY2y5uqkjumHNDUC_6dvCZSxGRQ8fyo5XqdpqMtrRXNjyzN9a73oyQ"
    ["provider"] => string(6) "WeChat"
  }
}object(Overtrue\Socialite\User)#134 (1) {
  ["attributes":protected] => array(10) {
    ["id"] => string(28) "o7Dzs337bEPl_pg886oVTgrab6Wg"
    ["name"] => string(12) "岁暮天寒"
    ["nickname"] => string(12) "岁暮天寒"
    ["avatar"] => string(132) "https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLBVGiayuTS7ptprfHtSfwD43iaXY1Akkz27vq4qNPdxrESAxb9pHwXktCSibH6kE6Tia1RMtZrjgKfag/132"
    ["email"] => NULL
    ["original"] => array(10) {
      ["openid"] => string(28) "o7Dzs337bEPl_pg886oVTgrab6Wg"
      ["nickname"] => string(12) "岁暮天寒"
      ["sex"] => int(1)
      ["language"] => string(5) "zh_CN"
      ["city"] => string(6) "杭州"
      ["province"] => string(6) "浙江"
      ["country"] => string(6) "中国"
      ["headimgurl"] => string(132) "https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLBVGiayuTS7ptprfHtSfwD43iaXY1Akkz27vq4qNPdxrESAxb9pHwXktCSibH6kE6Tia1RMtZrjgKfag/132"
      ["privilege"] => array(0) {
      }
      ["unionid"] => string(28) "ogN8NwK3ZHykG2tVtXHoG9oUEm_w"
    }
    ["token"] => string(89) "46_eD_Ghm0AfLLh54gdDTmvbN-7uIHweXCJbShx5OeBp_skNaPhArO_nEhi3yHJ2gQJK-Yfuk-hsX9vOg6K2AH_BQ"
    ["access_token"] => string(89) "46_eD_Ghm0AfLLh54gdDTmvbN-7uIHweXCJbShx5OeBp_skNaPhArO_nEhi3yHJ2gQJK-Yfuk-hsX9vOg6K2AH_BQ"
    ["refresh_token"] => string(89) "46_dv6nwCx5q3OLoaPtVMIuTiMREHZGcEV9tY2y5uqkjumHNDUC_6dvCZSxGRQ8fyo5XqdpqMtrRXNjyzN9a73oyQ"
    ["provider"] => string(6) "WeChat"
  }
}