PHP从v7.4.16升级到v8.3.6

浏览数 13445 最后修改时间

一、升级相关的SDK,如阿里云的OSS SDK等等,否则会无法上传文件,如头像
1、切换到根目录,即 composer.json 所在的目录
2、升级OSS的SDK
composer update aliyuncs/oss-sdk-php

3、升级后提醒有安全漏洞问题,执行 composer audit 查看的确有
composer audit

4、升级存在安全问题的SDK,在 composer.json 文件中增加
        "guzzlehttp/guzzle": "^7.4.5",
        "guzzlehttp/psr7": "^2.4.5",
        "phpmailer/phpmailer": "^6.5.0"
增加后如下:
{
    "require": {
        "alibabacloud/client": "^1.5",
        "phpmailer/phpmailer": "^6.0",
        "aliyuncs/oss-sdk-php": "^2.3",
        "guzzlehttp/guzzle": "^7.4.5",
        "guzzlehttp/psr7": "^2.4.5",
        "phpmailer/phpmailer": "^6.5.0"
    }
}
然后执行升级命令
composer update
5、阿里云的OSS配置中增加region的字段,值为对应的地区
    //文件上传OSS配置
    'oss' => [
        'aliyun' => [
            'enable' => true,  //true可用,false不可用
            'accessKeyId' => 'bbbbbbbbbbb',
            'accessKeySecret' => 'bbbbbbbbbbbb',
            'endpoint' => 'oss-cn-shenzhen.aliyuncs.com',
            'stsEndpoint' => 'sts.cn-shenzhen.aliyuncs.com',
            'bucketName' => 'yiluphp',
            'region' => 'oss-cn-shenzhen',
            'visit_host' => 'https://yiluphp.oss-cn-shenzhen.aliyuncs.com/',
        ]
    ],

二、更新写项目日志的函数,否则某些情况下会报错
函数在入口文件中:/public/index.php
主要是修改了:
1、给 mb_detect_encoding() 加传了第二个参数;
2、把 iconv() 换成了mb_convert_encoding()函数。
/**
 * 写项目内日志
 * $level 定义值:ERROR错误、WARNING警告、DEBUG调试、NOTICE通知、VISIT访问、RESPONSE响应(HTML的不写,只写json和jsonp)、TRACE代码追溯
 * 其它可以自定义,先在配置log_level中定义,然后写日志时把它传给level值就行了
 * @param string $level
 * @param string $data
 * @return void
 */
function write_applog(string $level, string $data = '')
{
    if (empty($GLOBALS['config']['log_level']) || !is_array($GLOBALS['config']['log_level'])) {
        return;
    }
    $level = strtoupper($level);
    if (!in_array($level, $GLOBALS['config']['log_level'])) {
        return;
    }

    $datatime = '[' . date('Y-m-d H:i:s') . '] ' . $level . ': REQUEST_ID=' . $GLOBALS['Yilu_request_id'] . ' ';
    if ($level == 'TRACE') {
        $txt = $datatime . $_SERVER['REQUEST_URI'] . ' , GET:' . json_encode($_GET, JSON_UNESCAPED_UNICODE) . ' POST:' . json_encode($_POST) . ' , RESPONSE: ' . $data;
        $code = mb_detect_encoding($txt, 'ASCII, UTF-8, ISO-8859-1, JIS, EUC-JP, SJIS');
        if ($code && $code != 'UTF-8') {
            $txt = mb_convert_encoding($txt, 'UTF-8', $code);
        }
        $a = debug_backtrace();
        array_shift($a);
        foreach ($a as $value) {
            $txt .= "\n\t\t" . 'file:' . $value['file'] . ', line:' . $value['line'];
            unset($value['file'], $value['line']);
            $txt .= json_encode($value, JSON_UNESCAPED_UNICODE);
        }
    }
    else if ($level == 'VISIT') {
        $txt = $datatime . $_SERVER['REQUEST_URI'] . ' , GET: ' . json_encode($_GET, JSON_UNESCAPED_UNICODE) . ' POST: ' . json_encode($_POST, JSON_UNESCAPED_UNICODE) . ' $_SERVER: ' . json_encode($_SERVER, JSON_UNESCAPED_UNICODE);
    }
    else if ($level == 'RESPONSE') {
        $txt = $datatime . $_SERVER['REQUEST_URI'] . ' , GET: ' . json_encode($_GET, JSON_UNESCAPED_UNICODE) . ' POST: ' . json_encode($_POST, JSON_UNESCAPED_UNICODE) . ' $_SERVER: ' . json_encode($_SERVER, JSON_UNESCAPED_UNICODE) . ' , RESPONSE: ' . $data;
    }
    else {
        $txt = $datatime . $_SERVER['REQUEST_URI'] . ' , GET: ' . json_encode($_GET, JSON_UNESCAPED_UNICODE) . ' POST: ' . json_encode($_POST, JSON_UNESCAPED_UNICODE) . ' $_SERVER: ' . json_encode($_SERVER, JSON_UNESCAPED_UNICODE) . ' , RESPONSE: ' . $data;
    }
    $path = APP_PATH . 'logs/';
    if (!is_dir($path)) {
        mkdir($path, 0777, true);
    }
    $code = mb_detect_encoding($txt, 'ASCII, UTF-8, ISO-8859-1, JIS, EUC-JP, SJIS');
    if ($code && $code != 'UTF-8') {
        $txt = mb_convert_encoding($txt, 'UTF-8', $code);
    }
    if (defined('LOG_LOCAL5')) {
        openlog("qcloud_db", LOG_PID, LOG_LOCAL5);
        syslog(LOG_INFO, $txt);
        closelog();
    }
    $file = $path . date('Y-m-d') . '.log';
    file_put_contents($file, $txt . "\n\n", FILE_APPEND);
//    chmod($file,0755);
}

三、安装阿里云的邮件推送的新SDK,否则无法发送邮件,如邮箱验证码
1、切换到根目录,即 composer.json 所在的目录
2、运行以下命令安装SDK
相关官方文档:如何安装和使用PHP SDK_邮件推送(Direct Mail)-阿里云帮助中心 (aliyun.com)
composer require alibabacloud/dm-20151123 1.0.x

3、修改发送邮件的类
文件路径:/tool/tool_mailer.php
   1)在文件头部删除或注释掉引入老的阿里云SDK的代码
use PHPMailer\PHPMailer\Exception;
use Dm\Request\V20151123 as Dm;

   2)在文件头部引入新的阿里云SDK
use AlibabaCloud\SDK\Dm\V20151123\Dm;
use AlibabaCloud\Tea\Exception\TeaError;
use AlibabaCloud\Tea\Utils\Utils;

use Darabonba\OpenApi\Models\Config;
use AlibabaCloud\SDK\Dm\V20151123\Models\SingleSendMailRequest;
use AlibabaCloud\Tea\Utils\Utils\RuntimeOptions;

   3)把原来的阿里云发邮件的方法 ` public function send_by_aliyun() ` 删除掉,或者另取一个名称 ` public function send_by_aliyun_old() `  ;
   4)再建一个方法,名称和原来的一样 `  public function send_by_aliyun_old() `,这个方法实现“使用新的SDK发送邮件”,方法的代码如下:
/**
     * @name 使用阿里云发邮件
     * @return bool
     */
    public function send_by_aliyun()
    {
        if(empty($GLOBALS['config']['mailer']['aliyun']['access_key_id'])){
            write_applog('ERROR', '未设置阿里云邮件推送的access_key_id:'.json_encode($this->all_params()));
            return false;
        }
        if(empty($GLOBALS['config']['mailer']['aliyun']['access_key_secret'])){
            write_applog('ERROR', '未设置阿里云邮件推送的access_key_secret:'.json_encode($this->all_params()));
            return false;
        }
        if(empty($GLOBALS['config']['mailer']['aliyun']['from_name'])){
            write_applog('ERROR', '未设置阿里云邮件推送的from_name:'.json_encode($this->all_params()));
            return false;
        }
        if(empty($GLOBALS['config']['mailer']['aliyun']['from_email'])){
            write_applog('ERROR', '未设置阿里云邮件推送的from_email:'.json_encode($this->all_params()));
            return false;
        }
        $this->from_alias = $GLOBALS['config']['mailer']['aliyun']['from_name'];
        $this->from_email = $GLOBALS['config']['mailer']['aliyun']['from_email'];
        if(!$this->check_content()){
            write_applog('ERROR', '发送邮件失败,必填项缺失:'.json_encode($this->all_params()));
            return false;
        }

        // 建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/311677.html。
        $config = new Config([
            // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
            'accessKeyId' => $GLOBALS['config']['mailer']['aliyun']['access_key_id'],
            // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
            'accessKeySecret' => $GLOBALS['config']['mailer']['aliyun']['access_key_secret'],
        ]);
        // Endpoint 请参考 https://api.aliyun.com/product/Dm
        $config->endpoint = "dm.aliyuncs.com";
        $client = new Dm($config);

        $params = [
            'accountName'            => $this->from_email,  //管理控制台中配置的发信地址
            'addressType'            => 0,  //地址类型。取值:0:为随机账号,1:为发信地址
//            'clickTrace'             => 'ClickTrace',  //1:为打开数据跟踪功能,0(默认):为关闭数据跟踪功能。
            'fromAlias'              => $this->from_alias,  //发信人昵称,长度小于 15 个字符。例如:发信人昵称设置为”小红”,发信地址为 test***@example.net,收信人看到的发信地址为“小红”test***@example.net。
            'htmlBody'               => $this->html_body,  //邮件 html 正文,限制 28K。注意:HtmlBody 和 TextBody 是针对不同类型的邮件内容,两者必须传其一。
//            'ownerId'                => 'OwnerId',
//            'replyAddress'           => 'ReplyAddress',  //回信地址
//            'replyAddressAlias'      => 'ReplyAddressAlias',  //回信地址昵称
            'replyToAddress'         => false,  //是否启用管理控制台中配置好回信地址(状态须验证通过),取值范围是字符串 true 或者 false(不是 bool 值)。
//            'resourceOwnerAccount'   => 'ResourceOwnerAccount',
//            'resourceOwnerId'        => 'ResourceOwnerId',
            'subject'                => $this->subject,  //邮件主题
            'tagName'                => $this->tag_name,  //在邮件推送控制台创建的标签,用于分类所发送的邮件批次,可以通过标签来查询每批邮件的发送情况,另外如果开启邮件跟踪功能,发信必须使用邮件标签。
            'textBody'               => $this->html_body,  //邮件 text 正文,限制 28K。注意:HtmlBody 和 TextBody 是针对不同类型的邮件内容,两者必须传其一。
            'toAddress'              => $this->to_email,  //目标地址,多个 email 地址可以用逗号分隔,最多 100 个地址(支持邮件组)。
//            'unSubscribeFilterLevel' => 'UnSubscribeFilterLevel', //过滤级别。参照退订功能生成链接和过滤机制文档。disabled: 不过滤,default: 采用默认策略,批量地址采用发信地址级别过滤,mailfrom: 发信地址级别过滤,mailfrom_domain: 发信域名级别过滤,edm_id: 账号级别过滤。https://help.aliyun.com/document_detail/2689048.html?spm=api-workbench.api_explorer.0.0.3c3d4cf62Sfbjt
//            'unSubscribeLinkType'    => 'UnSubscribeLinkType',  //生成的退订链接类型。参照退订功能生成链接和过滤机制文档。disabled: 不生成,default: 采用默认策略:对批量类型的发信地址发给特定域名时会生成退订链接,如带有关键字"gmail", "yahoo", "google", "aol.com", "hotmail", "outlook", "ymail.com"等,zh-cn: 生成,给将来埋点到内容准备,en-us: 生成,给将来埋点到内容准备。https://help.aliyun.com/document_detail/2689048.html?spm=api-workbench.api_explorer.0.0.3c3d4cf62Sfbjt
        ];
        $singleSendMailRequest = new SingleSendMailRequest($params);
        $runtime = new RuntimeOptions([]);
        try {
            // 复制代码运行请自行打印 API 的返回值
            $client->singleSendMailWithOptions($singleSendMailRequest, $runtime);
        }
        catch (Exception $error) {
            if (!($error instanceof TeaError)) {
                $error = new TeaError([], $error->getMessage(), $error->getCode(), $error);
            }
            // 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
            // 错误 message
//            var_dump($error->message);
            // 诊断地址
//            var_dump($error->data["Recommend"]);
            if (!empty($GLOBALS['config']['weixin_robot']['xiaomei'])){
                $message = "使用阿里云发邮件失败了\r\n错误信息:{$error->message}\r\n诊断地址" . $error->data['Recommend'];
                tool_operate::I()->send_work_notice($message, $GLOBALS['config']['weixin_robot']['xiaomei']);
            }
            Utils::assertAsString($error->message);
        }
    }


我来说说