分类 默认分类 下的文章

IUS 是一个 yum 存储库,可为 RHEL 和 CentOS 提供选定软件的更新版本

Setup
To enable the IUS repository on your system, install the ius-release package. This package contains the IUS repository configuration and public package signing keys. Many IUS packages have dependencies from the EPEL repository, so install the epel-release package as well.

RHEL/CentOS 7

yum install \
https://repo.ius.io/ius-release-el7.rpm \
https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm

Testing
IUS packages are first made available in the ius-testing repository before being promoted to the main repository. When you install ius-release, the ius-testing repository is disabled by default. Enable it if you would like to participate in testing new IUS packages.

yum install yum-utils
yum-config-manager --enable ius-testing

PHP 7.x 版本与 5.6 版本之间有许多重要的差异和改进,同时也存在一些兼容性问题。下面将从几个方面进行分析。

1. 性能提升
PHP 7 的性能提升:PHP 7 相比于 PHP 5.6 提升了约两倍的性能,具体体现在执行速度和内存使用上。这主要得益于 Zend Engine 的重写,使用了更高效的内存管理。

2. 类型声明
新类型声明:PHP 7 引入了标量类型声明(如 int, float, string, bool)和返回类型声明。这使得函数的参数和返回值可以更明确,使得代码的可读性和可维护性大幅提升。

示例:

function add(int $a, int $b): int {
    return $a + $b;
}

3. 异常处理
基于异常的错误处理:在 PHP 7 中,引入了 Throwable 接口,所有可以被捕获的异常(Exception 和 Error)都实现了该接口。这提供了更一致的错误处理机制。

4. 新增语法特性
太多语法糖:PHP 7 增加了新特性,比如 null coalescing 操作符(??),可以更方便地处理未定义或为空的变量。

示例:

$username = $_GET['user'] ?? 'default_user';

5. 删除不推荐的功能
删除不再支持的功能:PHP 7 移除了多种在 5.6 中被标记为过时的功能。这包括支持的 mysql 扩展、ereg 扩展等,因此升级到 PHP 7 前需要检查代码中是否使用这些功能。

6. 兼容性问题
兼容性问题:由于上述删除不再支持的特性及语法改变,某些旧的代码在 PHP 7 中可能无法运行,需要进行修改和测试。

示例:
使用动态变量访问已定义的属性与方法仍然可行,但需确保在使用时遵循新的错误处理规范。
第三方库的兼容性:许多流行的 PHP 框架和库已经更新以支持 PHP 7,但某些旧版本的库可能无法在 PHP 7 中正常工作。

总结
PHP 7.x 版本相较于 5.6 版本提供了显著的性能提升和丰富的新特性,同时引入了更严格的类型声明以及一致的错误处理机制。然而,开发者在迁移到 PHP 7 时需要注意兼容性问题,检查和更新代码以适应新的语法和功能。建议在升级前做好充分的测试和准备。

注意:本文参考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];
    }
}