Deprecated: parse_url(): Passing null to parameter #1 ($url) of type string is deprecated in /www/wwwroot/blog_qqvbc_com/usr/plugins/Access/Access_Core.php on line 339

Deprecated: parse_url(): Passing null to parameter #1 ($url) of type string is deprecated in /www/wwwroot/blog_qqvbc_com/usr/plugins/Access/Access_Core.php on line 392

Deprecated: parse_url(): Passing null to parameter #1 ($url) of type string is deprecated in /www/wwwroot/blog_qqvbc_com/usr/plugins/Access/Access_Core.php on line 394
Joyber 的博客

注意:本文参考AI生成内容,其中某些内容不保证正确性。

PHP 8.0 引入了许多新特性和改进,增强了语言的功能和性能。以下是一些主要的新特性总结:

联合类型: 允许函数参数和返回值可以指定多个类型,使用 | 符号。例如:

function foo(int|float $number): int|float {
    return $number;
}

命名参数: 允许在函数调用时使用参数名称,而不是依赖于参数的顺序,增强了函数调用的可读性。

function example($param1, $param2) {
    // ...
}
example(param2: 'value2', param1: 'value1');

匹配表达式: 引入了类似于 switch 的新的控制结构,支持更简洁的语法。

$result = match ($value) {
    'a' => 'Result A',
    'b' => 'Result B',
    default => 'Default Result',
};

属性类型: 支持在类属性上直接声明类型。

class User {
    public string $name;
}

空安全操作符: ?-> 操作符可以在访问对象属性或方法时,如果对象为 null,则自动返回 null,而不是引发错误。

throw 表达式: 可以使用 throw 作为表达式,使其可以在更广泛的上下文中使用。

$result = (condition) ? $value : throw new Exception("Error!");

改进的错误处理: 更改错误处理机制,改进了异常的类型,增强了错误信息的准确性。

JIT(即时编译): 引入 JIT 编译,能够显著提高某些类型的计算性能,尤其是 CPU 密集型任务。

字符串插值中的转义字符: 在双引号字符串中,可以使用转义字符更灵活地处理变量和字符。

新函数和改进:
新增了一些内置函数和改进了已有的函数,如 str_contains()、str_starts_with() 和 str_ends_with() 等。

这些新特性使 PHP 8.0 更加灵活和强大,提高了开发者的生产力和代码的可维护性。

PHP 8.0 引入了一些新的内置函数、类和方法,同时也有一些与 7.x 版本不兼容的语法和特性。以下是相关的总结:

新增的内置函数
1、字符串处理函数:

  • str_contains($haystack, $needle): 检查字符串中是否包含另一个字符串。
  • str_starts_with($haystack, $needle): 检查字符串是否以指定字符串开头。
  • str_ends_with($haystack, $needle): 检查字符串是否以指定字符串结尾。

2、其他新函数:

  • get_debug_type($var): 获取变量的调试类型。
  • preg_last_error_msg(): 返回最后一个 PCRE 正则表达式错误的信息。
  • finfo_buffer(): 获取文件信息的功能。

新增的类和方法

  • Stringable 接口: 所有实现了 __toString() 方法的类现在都隐式实现了 Stringable 接口。
  • ReflectionUnionType 类: 提供对联合类型的反射支持。

不兼容的语法和特性
1、废弃的功能:

  • 之前的 create_function() 函数在 PHP 8.0 中被移除。
  • 一些旧的 serialize() 选项和不推荐使用的算法。

2、从 catch 中捕获 Throwable:

PHP 8.0 中,catch 语句可以捕获 Throwable,而在之前的版本中,如果在 catch 中未声明类型,可能会导致问题。

3、类型提示改进:

在 PHP 8.0 中,类型提示和返回类型支持 union types 和 nullable types,可能会影响依赖旧型式的代码。

4、动态变量名限制:

$example->$dynamicProperty; 像这样的动态调用对象属性的特性更严格,当该属性未被定义,虽然在 PHP 7.x 中,这可能不会立即报错(取决于上下文),但在 PHP 8.0 中,将导致致命错误,使用要小心,先检查是否存在再调用。

系统运行生成了一些日志文件,需要定期清理掉,以下是一个代码参考,用到了exec函数执行shell命令完成日志打包和删除:

日志文件处理、清理说明:

  • 每月执行一次,可用crontab执行protected/yii logFile run [--test=0|1]
  • 处理 protected/runtime 目录下的日志文件,将其移动到 protected/runtime/bak 目录下,打包成zip文件,并删除原文件
  • 删除 protected/runtime/bak 目录下超过 180 天的zip文件

BaseConsoleCommand.php

<?php


class BaseConsoleCommand extends CConsoleCommand {

    protected $debugEnable = false;

    protected function msg($message, $exitCode=null) {
        echo date('Y-m-d H:i:s') . ": {$message}\n";
        if (!is_null($exitCode)) return exit($exitCode);
    }

    protected function cliOut($message) {
        if (is_array($message)) $message = json_encode($message, JSON_UNESCAPED_UNICODE);
        echo "{$message}\n";
    }

}

LogfileCommand.php

<?php
require_once __DIR__ . '/BaseConsoleCommand.php';

class LogfileCommand extends BaseConsoleCommand
{

    private $debug = false;
    private $logPath, $logBackPath;

    public function init()
    {
        parent::init(); // TODO: Change the autogenerated stub

        //日志文件目录路径,以/结尾
        $this->logPath = Yii::app()->basePath . '/runtime/';
        //日志文件备份目录路径,以/结尾
        $this->logBackPath = Yii::app()->basePath . '/runtime/bak/';
    }

    /**
     * 日志文件处理、清理
     * 每月执行一次
     * 处理 protected/runtime 目录下的日志文件,将其移动到 protected/runtime/bak 目录下,打包成zip文件,并删除原文件
     * 删除 protected/runtime/bak 目录下超过 180 天的zip文件
     * 通过调用shell命令完成操作
     * 不提供手动定义文件名的参数,以免对系统文件造成误操作
     * @param int $test 测试模式,0为正式执行,1为测试执行
     * @return void
     */
    public function actionRun($test = 0)
    {
        $this->debug = boolval($test);

        if (!$this->checkShellRun()) return;

        $prevMonth = date('Ym', strtotime('-1 month'));
        $date = date('Ymd');
        /**
         * 待处理日志文件列表,格式:[文件名=>zip文件名,文件名=>zip文件名,...],文件名可以用*代替多个任意字符,参考shell语法
         * 如果不想备份直接删除文件,则把zip文件名设置为 NULL 空值
         */
        $logFileList = [
            'role-assign.log'               => "role-assign-{$date}.log.zip",
            'caijicluemeituan.log'          => "caijicluemeituan-{$date}.log.zip",
            'supplies.log'                  => "supplies-{$date}.log.zip",
            'log.txt'                       => "log-{$date}.txt.zip",
            'task_oceanengine.log'          => "task_oceanengine-{$date}.log.zip",
            'cluetyd_assign.log'            => "cluetyd_assign-{$date}.log.zip",
            'wxwork_callback.log'           => "wxwork_callback-{$date}.log.zip",
            "site_all_log{$prevMonth}*.log" => "site_all_log{$prevMonth}-{$date}.log.zip",
        ];

        //循环处理待处理日志文件列表
        foreach ($logFileList as $filename => $zipFileName) {
            $this->msg("处理待处理日志文件:{$filename}");
            $logFile = $this->logPath . $filename;
            //执行shell命令移动文件,并压缩
            $zipFile = $this->logBackPath . $zipFileName;
            if (is_null($zipFileName)) {
                //直接删除原文件
                $cmd = "rm -f {$logFile}";
            } else {
                //移动文件到备份目录,然后压缩目标文件后删除目标文件
                $logFileMoved = $this->logBackPath . $filename;
                $cmd = "mv {$logFile} {$this->logBackPath} && zip -r {$zipFile} {$logFileMoved} && rm -f {$logFileMoved}";
            }
            $this->exec($cmd);
            echo "\n";
        }

        /**
         * 删除 protected/runtime/bak 目录下超过 180 天的zip文件
         */
        $this->msg("删除 protected/runtime/bak 目录下超过 180 天的zip文件");
        $cmd = "find {$this->logBackPath} -mtime +180 -name '*.zip' -delete";
        $this->exec($cmd);
    }

    /**
     * 检查shell命令是否可用
     * @return bool
     */
    private function checkShellRun()
    {
        //判断shell_exec 或者 exec 是否可用
        if (!function_exists('shell_exec') && !function_exists('exec')) {
            $this->msg('需要取消禁用 shell_exec 或者 exec 函数,请检查php配置!');
            return false;
        }
        return true;
    }

    /**
     * 执行shell命令
     * @param $cmd
     * @return array [code, ret] 执行结果 code:0=成功,1=失败
     */
    private function exec($cmd)
    {

        $this->msg("执行shell命令:{$cmd}");

        $code = 0;
        if ($this->debug) {
            //测试
            $ret = '测试模式,未真实执行命令'; //shell_exec($cmd);
        } else {
            //判断使用哪个函数执行命令
            if (function_exists('exec')) {
                exec($cmd, $ret, $code);
                $ret = implode("\n", $ret);
            } elseif (function_exists('shell_exec')) {
                $ret = shell_exec($cmd);
                $code = $ret === false ? 1 : 0;
            } else {
                $ret = 'shell_exec 或者 exec 函数不可用,请检查php配置!';
                $code = 1;
            }
        }

        $this->msg("执行结果:code: {$code}; ret:{$ret}");
        return [$code, $ret];
    }
}

在查看jenkins进程的时候,看到一个命令:bash -c ulimit -S -c 0

root     10513  0.0  0.0 115676   640 ?        S    Apr18   0:00 /bin/sh /etc/rc.d/init.d/jenkins start
root     10517  0.0  0.0 144420   924 ?        S    Apr18   0:00 runuser -s /bin/bash jenkins -c ulimit -S -c 0 >/dev/null 2>&1 ; /usr/lib/jvm/jdk-21-oracle-x64/bin/java -Djava.awt.headless=true -DJENKINS_HOME=/var/lib/jenkins -jar /usr/lib/jenkins/jenkins.war --logfile=/var/log/jenkins/jenkins.log --webroot=/var/cache/jenkins/war --httpPort=8080
jenkins  10520  0.0  0.0 113284   416 ?        Ss   Apr18   0:00 bash -c ulimit -S -c 0 >/dev/null 2>&1 ; /usr/lib/jvm/jdk-21-oracle-x64/bin/java -Djava.awt.headless=true -DJENKINS_HOME=/var/lib/jenkins -jar /usr/lib/jenkins/jenkins.war --logfile=/var/log/jenkins/jenkins.log --webroot=/var/cache/jenkins/war --httpPort=8080
jenkins  10521  0.2  7.7 4907240 621872 ?      Sl   Apr18 524:12 /usr/lib/jvm/jdk-21-oracle-x64/bin/java -Djava.awt.headless=true -DJENKINS_HOME=/var/lib/jenkins -jar /usr/lib/jenkins/jenkins.war --logfile=/var/log/jenkins/jenkins.log --webroot=/var/cache/jenkins/war --httpPort=8080

bash -c ulimit -S -c 0 这条命令的含义如下:

  • bash:启动一个新的 Bash shell
  • -c:表示接下来的字符串是要执行的命令。
  • ulimit:这是一个内置命令,用于限制和查看系统资源的使用情况。
  • -S:表示设置软限制(soft limit),与硬限制(hard limit)相对。
  • -c:表示控制核心转储文件的大小。
  • 0:这表示将核心转储文件的大小限制为 0,意味着禁止生成核心转储文件。
    因此,整体来看,这条命令在新启动的 Bash shell 中执行,将核心转储文件的软限制设为 0,从而禁止任何核心转储的产生。

在执行程序之前执行hash -c ulimit -S -c 0 命令会有以下几个作用:

  • 禁止核心转储:设置核心转储大小为 0,意味着系统在程序崩溃时不会生成核心转储文件。核心转储文件通常用于调试程序崩溃的原因。通过禁止生成这些文件,可以避免占用额外的磁盘空间。
  • 保护隐私和安全:核心转储文件可能包含程序的内存内容,涉及敏感数据。禁止生成这些文件可以在一定程度上提升程序的安全性,防止敏感信息泄露。
  • 系统资源管理:在某些情况下,可以通过限制核心转储文件的生成来维持系统的稳定性和性能,尤其是在高负载环境中。

总之,执行这个命令可以控制程序在发生崩溃时的行为,从而减少潜在的资源消耗和安全隐患。

WINDOW电脑桌面以及文件夹内的文件图标一直闪,就像是一直按到F5键一直刷新一样,刷新的频率大概1秒1次,并且重启后现象持续,请问怎么解决这个问题?

这里提供一些思路:

桌面和文件夹内的文件图标持续闪烁,通常可能是由于以下几种原因导致的。你可以尝试以下几种解决方案:

检查显示驱动程序:

更新或重新安装显卡驱动程序。可以通过设备管理器找到显示适配器,右键选择更新驱动程序,或访问显卡制造商网站下载安装最新的驱动程序。
关闭自动刷新功能:

一些软件可能导致桌面刷新。检查是否有第三方软件在后台运行,可以尝试关闭或卸载这些软件。
检查文件管理器设置:

确保文件或文件夹的设置没有启用自动刷新。右键点击桌面或文件夹,选择“属性”,检查相关设置。
禁用桌面图标自动排列:

右键桌面,选择“查看”,取消勾选“自动排列图标”,看看是否能解决问题。
系统文件检查:

使用Windows内置的系统文件检查工具。打开命令提示符(管理员),输入命令sfc /scannow并回车,等待扫描完成。
创建新用户账户:

可以尝试创建一个新的用户账户,看看在新账户下是否仍然出现闪烁的情况。如果新账户没有此问题,可能是当前用户配置文件损坏。
检查硬件问题:

如果以上方法都无法解决,可能需要检查硬件问题,比如显卡接触不良或其他硬件故障。
请尝试上述方法,希望能够解决你的问题。如果问题依然存在,建议联系专业技术支持。

关于文章中的空白字符:文本是AI生成的,其中有大量的公式是图片所以搬过来的时候图片无法搬运,出现大量空白字符,本文仅作为记录参考之用。

使用随机投点法求圆周率
在数学中,圆周率是圆的周长与直径的比值,用希腊字母π表示。而在程序设计中,我们可以通过一种巧妙的方法来近似计算圆周率。

一段程序在单位正方形(范围是((0, 0), (1, 1)))中随机生成大量的点,通过判断点是否落在单位正方形的内接圆中,来逐步逼近圆周率的值。判断点是否在圆内的条件是看该点  到圆心  的距离是否小于半径 。这里涉及到圆的方程         ,对于单位正方形内接圆,圆心坐标为  ,半径   ,所以圆方程就是           。而平面上两点  和  之间的距离公式为 ,依据此距离公式,若点到圆心的距离小于半径,则该点落在圆内。

随着生成的点越来越多,落在圆内的点的数量与总点数的比值会逐渐趋近于圆的面积与正方形面积的比值。单位正方形面积为 1,单位圆的面积为     。所以当总点数足够多时,   就近似等于圆周率 。

圆周率的定义是什么?
圆周率是圆的周长与直径的比值,用希腊字母π表示。对于任何一个圆,其周长与直径的比值都是一个固定的常数,即圆周率。在数学中,圆周率是一个无理数,它的值约为 3.1415926……其小数部分无限不循环。圆周率在几何、物理、工程等众多领域都有广泛的应用。

这段程序为什么能计算圆周率
仓颉代码:

import std.random.*

main() {
    let random = Random()
    var totalPoints = 0
    var hitPoints = 0

    do {
        // 在 ((0, 0), (1, 1)) 这个正方形中随机取点
        let x = random.nextFloat64()
        let y = random.nextFloat64()
        // 判断是否落在正方形内接圆里
        if ((x - 0.5) ** 2 + (y - 0.5) ** 2 < 0.25) {
            hitPoints++
        }
        totalPoints++
    } while (totalPoints < 1000000)

    let pi = 4.0 * Float64(hitPoints) / Float64(totalPoints)
    println("圆周率近似值为:${pi}")
}

这段程序通过随机投点法来计算圆周率。

原理如下:

1. 程序在单位正方形(边长为 1,范围是((0, 0), (1, 1)))中随机生成大量的点。
2. 对于每个随机点,判断其是否落在单位正方形的内接圆中。内接圆的半径为 0.5,圆心在(0.5, 0.5),如果点  到圆心的距离小于半径(即满足         ),则该点落在圆内。
3. 随着生成的点越来越多,落在圆内的点的数量(hitPoints)与总点数(totalPoints)的比值会逐渐趋近于圆的面积与正方形面积的比值。
4. 单位正方形面积为 1,单位圆的面积为π×(0.5)² = π/4。所以当总点数足够多时,4×(hitPoints/totalPoints)就近似等于圆周率π。

怎么证明是否落在圆内的方法是正确的

可以通过以下方式证明判断点是否落在圆内的方法是正确的。

1. 圆的方程推导:

  • 单位圆的方程为         ,其中圆心坐标为  ,半径为 。
  • 对于单位正方形内接圆,圆心坐标为  ,半径为 ,则圆的方程为         。
    2. 距离公式解释:
  • 平面上两点  和  之间的距离公式为 。
  • 那么点  到圆心  的距离就是 。
    3. 条件判断正确性:
  • 当点到圆心的距离小于半径时,点在圆内。
  • 已知半径为 ,所以当         时,点  落在圆内,这个判断条件是符合圆的定义和性质的。

综上所述,可以证明程序中判断点是否落在圆内的方法是正确的。

0.25怎么来的

在这段程序中,判断点是否在圆内的条件中有“0.25”,这个值是由内接圆的半径为 0.5 得来的。

单位正方形内接圆的半径是 0.5。根据圆的方程         ,其中圆心坐标为  ,半径为 。对于这个内接圆,圆心坐标为  ,半径   。

那么圆方程就是         ,而   。所以在判断条件中出现了“0.25”这个值。

圆的方程怎么推导的

圆的标准方程推导如下:

1. 建立平面直角坐标系:

  • 设圆心坐标为  ,圆上任意一点坐标为  。
    2. 依据距离公式确定方程:
  • 根据圆的定义,圆上任意一点到圆心的距离都等于半径 。
  • 两点  和  之间的距离公式为 。
  • 那么点  到圆心  的距离为 ,由于这个距离等于半径 ,所以就得到方程         。

这就是圆的标准方程的推导过程。

两个坐标点的距离怎么推导的

平面上两点  和  之间的距离公式推导如下:

1. 构建直角三角形:

  • 在平面直角坐标系中,连接两点  和  。
  • 过这两点分别向坐标轴作垂线,这样就构成了一个直角三角形。
    2. 确定三角形的边长:
  • 直角三角形的两条直角边的长度分别为   和   。
    3. 应用勾股定理:
  • 根据勾股定理,直角三角形的斜边长度(也就是两点之间的距离)等于两条直角边的平方和的平方根。
  • 设两点间距离为 ,则   。
  • 由于       的算术平方根,       的算术平方根,所以距离公式进一步化简为   。