

统一声明:
1.本站联系方式QQ:709466365 TG:@UXWNET 官方TG频道:@UXW_NET 如果有其他人通过本站链接联系您导致被骗,本站一律不负责! 2.需要付费搭建请联系站长QQ:709466365 TG:@UXWNET 3.免实名域名注册购买- 游侠云域名 4.免实名国外服务器购买- 游侠网云服务
这篇全攻略专为新手到高手的成长路径设计:从最基础的环境搭建、常用指令(比如php -v
查版本、php -f
运行脚本)、参数传递(位置参数、长/短选项)讲起,用“一步一操作”帮你打通入门关;接着通过真实场景实战——比如写一个批量导出数据库的脚本、做一个定时清理日志的定时任务,教你把CLI用在实际工作中;最后深入进阶技巧:如何优化脚本性能(比如减少内存占用)、如何捕获致命错误、如何规范日志管理,帮你写出稳定可靠的CLI程序。
不管你是想解决“重复劳动”的痛点,还是想补全PHP全栈能力,这篇文章都能带你从“怕碰命令行”到“熟练写CLI工具”。每部分都有具体例子和避坑指南,看完就能动手实践,真正把PHP-CLI变成提升效率的“利器”。
你有没有过这种情况?做PHP Web开发时写接口、调框架都顺风顺水,可一旦要写个命令行脚本——比如批量导数据、定时清日志,立刻就慌了:明明语法熟,却不知道怎么在终端运行;传个参数要么收不到要么格式错;脚本跑着跑着突然崩了,连错在哪都找不到?其实我刚接触PHP-CLI时也这样,第一次帮朋友写清理日志的脚本,没配环境变量,Windows下打开cmd输php
直接提示“不是内部命令”,折腾了半小时才搞定;后来写参数传递,用$_GET
居然没反应,查了PHP官方文档才知道CLI模式没有HTTP请求,得用$_SERVER['argv']
(引用自PHP官方CLI文档:https://www.php.net/manual/zh/features.commandline.phpnofollow)。今天这篇全攻略,就是把我从新手到能独立写CLI工具的经验揉碎了讲,不管你是刚碰命令行的小白,还是想补全技能的PHP开发者,跟着走就能解决80%的CLI问题。
从0到1:PHP-CLI入门必须踩稳的3个台阶
入门CLI的核心不是记多少指令,而是解决“跑不起来”“传不对”“崩了找不到原因”这三个基础问题。我见过很多人一开始就去学复杂的框架,结果基础没打牢,遇到小问题还是卡壳——不如先把这三个台阶踩稳。
很多人入门的第一个坑是“脚本跑不起来”,其实90%的问题出在环境配置或指令用错。先讲环境:Windows系统要先把PHP的安装目录加到环境变量里——比如你装在C:php-8.2.0
,就把这个路径加到系统变量的Path
里,然后打开cmd输php -v
,能看到版本号(比如PHP 8.2.0 (cli)
)就对了;Linux系统一般默认装了PHP,但可能版本旧,比如Ubuntu可以用apt install php8.2-cli
装最新的CLI版本(注意要装cli
包,不是apache2
或fpm
包),装完同样输php -v
验证。
接下来是基础指令,这几个是我每天用得最多的:
php -v
:查PHP版本,确认环境没问题;php -f 脚本路径
:运行指定脚本,比如php -f test.php
,这是最常用的;php -r "代码"
:执行单行PHP代码,比如php -r "echo date('Y-m-d');"
,适合快速测试小功能;php -i
:查看PHP的配置信息,比如查有没有装mysqli
扩展,输php -i | grep mysqli
就能看到。我之前帮一个刚学PHP的朋友调脚本,他说“我写了个echo 'hello'
的脚本,双击没反应”——后来发现他直接双击.php
文件,系统用浏览器打开了,其实应该用cmd进脚本目录,输php test.php
才对。CLI的本质是“用终端调用PHP解释器执行脚本”,别把Web模式的习惯带过来。
Web开发里传参数用$_GET
或$_POST
,但CLI模式没有HTTP请求,参数是通过命令行输入传给脚本的。这里要记两个核心方法:位置参数和选项参数。
先讲位置参数,用$_SERVER['argv']
获取——比如你写个test.php
,里面写print_r($_SERVER['argv']);
,然后在终端输php test.php a b c
,会输出一个数组:Array([0] => test.php [1] => a [2] => b [3] => c)
。第一个元素是脚本路径,后面的是你传的参数。我之前写过一个计算两个数相加的脚本,用$_SERVER['argv'][1]
和$_SERVER['argv'][2]
取参数,比如php add.php 1 2
,输出3
,简单但实用。
再讲选项参数,比如你需要传“name 张三 age 20
”这种键值对,就得用getopt
函数。比如脚本里写:
$options = getopt('n:a:', ['name:', 'age:']);
print_r($options);
这里的'n:a:'
代表短选项-n
(冒号表示必须传值),'name:'
是长选项name
(同样要传值)。然后你输php test.php -n 张三 age 20
,$options
会输出Array([n] => 张三 [age] => 20)
。我之前帮公司写接口测试脚本时,用getopt
传接口地址、请求方法、参数,比如php test_api.php url http://example.com/api method POST data '{"id":1}'
,这样脚本里就能根据这些参数发请求,特别灵活。
CLI脚本不像Web项目有浏览器提示错误,一旦崩了如果没日志,根本不知道哪错了。我之前帮朋友写个读取文件的脚本,没加错误处理,遇到文件不存在直接输出“Warning: file_get_contents(xxx.txt): Failed to open stream: No such file or directory
”然后退出,他来找我时说“脚本突然停了,不知道为什么”。后来我帮他加了错误处理函数,把错误写到日志文件里:
set_error_handler(function($errno, $errstr, $errfile, $errline) {
$log = date('Y-m-d H:i:s') . " 错误级别: $errno 错误信息: $errstr 文件名: $errfile 行号: $errlinen";
file_put_contents('error.log', $log, FILE_APPEND);
});
这样再遇到错误,就能在error.log
里看到详细信息(比如“2024-05-20 14:30:00 错误级别: 2 错误信息: file_get_contents(xxx.txt): Failed to open stream: No such file or directory 文件名: test.php 行号: 5
”),排查起来特别快。 对于可预知的错误(比如数据库连接失败),可以用try-catch
抓异常:
try {
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', 'password', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
} catch (PDOException $e) {
echo "数据库连接失败: " . $e->getMessage() . "n";
exit(1); // 非0退出表示出错,方便定时任务判断结果
}
加了这两步,脚本崩了也能快速定位问题——这是我踩过很多坑才 出来的经验。
实战进阶:用PHP-CLI解决工作中80%的自动化需求
CLI的核心价值是自动化——把重复的、耗时间的工作交给脚本做,比如每天导出数据、每周清理日志、批量测接口,这些都是我工作中常遇到的场景,用CLI脚本就能省大量时间。
我之前在电商公司做开发时,运营每天要导出前一天的订单数据,手动用PHPMyAdmin查库、导出,要花10分钟,遇到数据多还容易卡。后来我写了个CLI脚本,每天凌晨2点自动跑,把数据导出到CSV,运营早上来直接拿文件就行。
脚本的逻辑很简单,但要注意异常处理和路径问题:
SELECT order_id, user_id, amount, create_time FROM orders WHERE create_time >= CURDATE()
INTERVAL 1 DAY
;关键代码比如:
try {
$pdo = new PDO('mysql:host=localhost;dbname=shop', 'root', 'password', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
$stmt = $pdo->query("SELECT order_id, user_id, amount, create_time FROM orders WHERE create_time >= CURDATE()
INTERVAL 1 DAY");
$orders = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 生成CSV文件路径(比如/var/exports/orders_20240520.csv)
$csvPath = '/var/exports/orders_' . date('Ymd') . '.csv';
$csvFile = fopen($csvPath, 'w');
// 写入表头
fputcsv($csvFile, array_keys($orders[0]));
// 写入数据
foreach ($orders as $order) {
fputcsv($csvFile, $order);
}
fclose($csvFile);
echo "导出成功:$csvPathn";
} catch (Exception $e) {
echo "导出失败:" . $e->getMessage() . "n";
exit(1);
}
然后用crontab
定时执行:输crontab -e
,加一行0 2 php /path/to/export_orders.php
(每天凌晨2点跑)。运营后来跟我说,这个脚本帮他们省了每天10分钟,一个月就是5小时,能多做很多事。
我之前帮一个做SaaS的朋友处理过服务器问题——他们的应用日志存在/var/log/app
里,每天生成1G日志,没清理过,结果硬盘满了导致应用崩了。后来我写了个CLI脚本,每周日凌晨3点自动清理30天前的日志。
脚本的逻辑更简单,但要注意文件判断(别删错文件):
$logDir = '/var/log/app';
$expireDays = 30;
$expireTime = $expireDays 86400; // 30天的秒数
// 遍历日志目录里的.log文件
$files = glob($logDir . '/.log');
foreach ($files as $file) {
if (is_file($file)) {
$fileTime = filemtime($file);
// 如果文件修改时间超过30天,删除
if (time()
$fileTime > $expireTime) {
unlink($file);
echo "Deleted: $filen";
}
}
}
然后用crontab
定时:0 3 0 php /path/to/clean_logs.php
(每周日凌晨3点跑)。朋友后来跟我说,服务器硬盘使用率从90%降到了30%,运维再也没找过他麻烦。
做接口开发时,我常要测多个参数组合的情况,比如测用户登录接口,要测“正确账号密码”“错误密码”“空账号”这几种情况,用Postman要手动改参数,麻烦。后来我写了个CLI脚本,用curl
扩展发请求,批量测接口,还能生成测试报告。
脚本的逻辑是定义测试用例→循环发请求→对比结果:
// 定义测试用例
$tests = [
[
'name' => '正确账号密码',
'url' => 'http://example.com/api/login',
'method' => 'POST',
'data' => ['username' => 'admin', 'password' => '123456'],
'expected' => ['code' => 200, 'msg' => '登录成功']
],
[
'name' => '错误密码',
'url' => 'http://example.com/api/login',
'method' => 'POST',
'data' => ['username' => 'admin', 'password' => 'wrong'],
'expected' => ['code' => 401, 'msg' => '密码错误']
],
[
'name' => '空账号',
'url' => 'http://example.com/api/login',
'method' => 'POST',
'data' => ['username' => '', 'password' => '123456'],
'expected' => ['code' => 400, 'msg' => '账号不能为空']
]
];
// 循环测试
foreach ($tests as $test) {
echo "测试用例:{$test['name']}...";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $test['url']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// POST请求处理
if ($test['method'] == 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($test['data']));
}
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
// 对比结果
if ($result['code'] == $test['expected']['code'] && $result['msg'] == $test['expected']['msg']) {
echo "通过!n";
} else {
echo "失败!响应:" . json_encode($result) . "n";
}
}
跑这个脚本就能一次性测所有用例,比Postman快多了。我之前测一个支付接口,用这个脚本测了10个用例,只用了2分钟,要是用Postman得10分钟。
附:PHP-CLI常用指令表
下面是我整理的高频CLI指令,记下来能省很多查文档的时间:
指令 | 作用 | 示例 |
---|---|---|
php -v | 查看PHP版本 | php -v |
php -f | 运行指定PHP脚本 | php -f test.php |
php -r | 执行单行PHP代码 | php -r “echo ‘Hello CLI’;” |
php -i | 查看PHP配置信息 | php -i | grep mysqli |
php help | 查看所有CLI指令帮助 | php help |
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,请使用WINRAR解压,如遇到无法解压的请联系管理员!
8. 精力有限,不少源码未能详细测试(解密),不能分辨部分源码是病毒还是误报,所以没有进行任何修改,大家使用前请进行甄别!
站长QQ:709466365 站长邮箱:709466365@qq.com