PHP从v7.4.16升级到v8.3.6
浏览数 13445
最后修改时间
1、切换到根目录,即 composer.json 所在的目录
2、升级OSS的SDK
composer update aliyuncs/oss-sdk-php
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);
}
}