PHP cli模式执行脚本 -- 通过getopt()接收参数

发布时间 2023-04-14 16:30:16作者: azsd

学习记录 留作参考
祝君好运

用于执行Linux定时任务的PHP文件,通过接收不同参数实现不同功能。

使用cli模式执行一些操作

PHP官方文档:执行PHP文件

# 可以使用下面两个命令执行filename.php文件,-f 参数可以省略

php filename.php

php -f filename.php

PHP用于定时任务的代码

<?php

/**
 * 专门用于执行定时任务的PHP脚本。
 * 需要做的功能是定时从三方平台同步数据到本地。
 * 想要实现的功能有如下几点:
 * 1.必传业务参数,接收一个值,根据此参数值实现不同功能;
 * 2.可选时间参数,接收一个值,根据传的形式不同,分为传递起止时间和仅开始时间(默认结束时间为现在);
 * 3.可通过 -h 命令,打印脚本使用说明。
 */

$options = getopt('p:t:h');

if ($options === false || count($options) === 0) {
    echo "No params\n";
    echo "You can use param -h to study how to use this php file.\n";
    exit;
}

// 命令行的用法
if (isset($options['h'])) {
    $str = <<<EOF
Provide 2 parameters to complete the task:
    -p=taskName     Required param. The task name is determined by 
                    the different php file.
    -t=timestamp    Optional param. Timestamps can have two forms:
                    1672502400 means loop execution some code from
                    this time to now.
                    1672502400-1672588800 means execution some
                    code during the start and end time.

提供2个参数来完成任务:
    -p=任务名   必选字段。任务名需要根据具体业务确定。
    -t=时间戳   可选字段。时间戳可以有两种形式:
                1672502400 从指定的时间戳开始循环执行某代码段直到现在
                1672502400-1672588800 表示起止时间段内执行某段代码

EOF;
    if (PHP_OS === 'WINNT' && version_compare(PHP_VERSION, '7.0.0', '<')) {
        // 如果是win平台,而且php版本较低,切换命令行窗口编码,防止中文乱码
        exec("chcp 65001"); // 切换命令行窗口的编码为utf-8,65001代表该编码。
    }
    echo $str;
    exit;
}

// 业务参数
if (!isset($options['p'])) {
    echo "You mast give param p to run this php file.\n";
    exit;
}

$start = $end = null;
if (!empty($options['t'])) {
    $timeArr = explode('-', $options['t']);
    if (count($timeArr) === 1 && is_numeric($timeArr[0])) {
        $start = intval($timeArr[0]);
        if ($start >= time()) {
            echo "the start time is wrong.\n";
            exit;
        }
    } else if (count($timeArr) === 2 && is_numeric($timeArr[0]) && is_numeric($timeArr[1])) {
        $start = intval($timeArr[0]);
        $end = intval($timeArr[1]);
        if ($start >= $end || $start >= time()) {
            echo "the start time and end time is wrong.\n";
            exit;
        }
    }
}

$param = $options['p'];
// 根据参数不同,做不同的处理
if ($param === 'order') {
    // 同步订单
    $timeNow = time();
    $space = 604800; // 首尾时间间隔-7天

    // 如果没有给开始时间,则默认1天前
    if ($start === null) {
        $start = strtotime(date('Y-m-d', strtotime('-1 day')));
    }

    $theLast = false; // 是否是最后一次执行
    while (true) {
        if (($end === null) || (($start - $end) == 1)) {
            $end = $start + $space - 1;
            if ($end > $timeNow) {
                $end = $timeNow;
                $theLast = true;
            }
        } else {
            $theLast = true;
        }

        someMethod($start, $end); // 执行一些业务逻辑
        $start = $end + 1;

        if ($theLast) break;
    }
} else if ($param === 'items') {
    // 同步商品--与同步订单的处理同理
} else {
    echo "Invalid param: p\n";
    exit;
}

/**
 * 这是一个示例方法,
 * 实际是需要调用具体业务代码的
 */
function someMethod($start, $end)
{
}

使用 getopt() 获取命令行参数

php通过命令行接收参数可以执行更多的处理。

PHP官方文档: getopt

getopt(string $short_options, array $long_options = [], int &$rest_index = null): array|false

short_options

这里只介绍第一个参数 $short_options
该字符串中的每个字符会被当做选项字符,匹配传入脚本的选项以单个连字符 (-) 开头。
只允许 a-z、A-Z 和 0-9。

short_options 可能包含了以下元素:

  • 单独的字符 - 此选项不接收值
  • 后面跟随一个冒号的字符 - 此选项需要值
  • 后面跟随两个冒号的字符 - 此选项的值可选

注意:

  1. 如果是单独的字符,通过 getopt() 接收到的参数值总是 bool(false)
  2. 可选值传参,如果解析到参数名,但没有接收到参数值,其值默认为 bool(false)
  3. 可选值传参,参数名与参数值之间需要使用等号连接或者不加连字符。
  4. 必选值传参,可以通过 空格、等号这种连字符,或者中间不加连字符传参。

使用:

PHP 文件如下:

// 表示 -p 必须接收一个参数;-t 可接收一个参数 -h不接收参数
var_dump(getopt('p:t::h'));

shell内执行的命令如下:

示例1:

php example.php -pvalue
php example.php -p=value
php example.php -p value

# 以上三条命令含义相同,输出均为:

array(1) {
  ["p"]=>
  string(5) "value"
}

示例2:

php example.php -p -t 123

# 以上输出为:

array(1) {
  ["p"]=>
  string(2) "-t"
}
# 因为 -p 必须接收一个参数,所以会把后面的第一个字符串解析为对应的值。
# 也不管它是不是参数名

示例3:

php example.php -p value -t 123

# 以上输出为:

array(2) {
  ["p"]=>
  string(5) "value"
  ["t"]=>
  bool(false)
}

# 此时发现 -t 的值为 false ,不是预期的 123 .
# 因为 -t 为可选传值,不能使用空格连字符。必须要使用 = 连接,或者不加任何连字符。

# 正确用法如下:

php example.php -p value -t123
php example.php -p value -t=123

# 以上输出均为:

array(2) {
  ["p"]=>
  string(5) "value"
  ["t"]=>
  string(3) "123"
}

示例4:

php example.php -p value -t123 -h
php example.php -p value -t123 -h 456

# 以上命令,因为 -h 不接收参数,所以输出相同:

array(3) {
  ["p"]=>
  string(5) "value"
  ["t"]=>
  string(3) "123"
  ["h"]=>
  bool(false)
}

示例5:

php example.php -p value1 -p=value2 -t123 -t=456
php example.php -p value1 -t123 -t=456 -p=value2

# 可以给一个参数多次传值-无顺序要求,此时对应的参数值会从字符串变成数组格式:

array(2) {
  ["p"]=>
  array(2) {
    [0]=>
    string(6) "value1"
    [1]=>
    string(6) "value2"
  }
  ["t"]=>
  array(2) {
    [0]=>
    string(3) "123"
    [1]=>
    string(3) "456"
  }
}