小破孩的小站 - 小破孩
type: channel
link: https://blog.8688web.com/index.php/author/1/
description: 小破孩
items: 【PHP】一个流行的 PHP 日期时间处理库 nesbot/carbon
items: PHP8.0 + 版本按数据处理类型分类的新增函数整理表格，包含函数名、对应版本、功能说明及可直接运行的用法示例
items: 【Elasticsearch】Elasticsearch 与数据库实时同步方案
items: 【Elasticsearch】IK 分词器安装指南和PHP使用实例
items: 【Elasticsearch】Elasticsearch 安装步骤与常见问题解决
items: 【Elasticsearch】 PHP 使用ES示例demo
items: 【MySQL】MySQL 各主要版本的区别
items: 【Linux】Linux 开发与运维命令终极手册 - 持续更新
items: 【PHP】境外微信支付生成平台证书 - wechatpay
items: 【Redis】Redis的操作方法整理

【PHP】一个流行的 PHP 日期时间处理库 nesbot/carbon
type: item
date: 2025-12-16T09:01:00+08:00
description: 官方文档：https://carbon.nesbot.com/docs/安装方法1. 基本安装# 在项目根目录执行 composer require nesbot/carbon2. 指定版本安装# 安装特定版本 composer require nesbot/carbon:^2.0 # 安装开发版本 composer require nesbot/carbon --dev基本使用方法1. 引入 Carbonuse Carbon\Carbon; // 获取当前时间 $now = Carbon::now(); echo $now; // 2023-10-27 14:30:00 // 创建指定时间 $date = Carbon::create(2023, 12, 25, 10, 30, 0);2. 常用方法示例use Carbon\Carbon; // 格式化输出 echo Carbon::now()->format('Y-m-d H:i:s'); echo Carbon::now()->toDateString(); // 2023-10-27 echo Carbon::now()->toDateTimeString(); // 2023-10-27 14:30:00 // 日期操作 $tomorrow = Carbon::now()->addDay(); $yesterday = Carbon::now()->subDay(); $nextWeek = Carbon::now()->addWeek(); // 日期比较 $date1 = Carbon::create(2023, 10, 27); $date2 = Carbon::create(2023, 10, 28); if ($date1->lt($date2)) { // less than echo "date1 在 date2 之前"; } // 时区设置 $date = Carbon::now('Asia/Shanghai'); $date->setTimezone('America/New_York');3. 本地化（中文支持）# 安装语言包 composer require carbonphp/carbon-doctrine-typesuse Carbon\Carbon; // 设置中文 Carbon::setLocale('zh'); echo Carbon::now()->diffForHumans(); // 刚刚 echo Carbon::now()->subMinutes(5)->diffForHumans(); // 5分钟前配置文件（可选）在 Laravel 项目中，可以在 config/app.php 中配置时区：'timezone' => 'Asia/Shanghai', 'locale' => 'zh-CN',验证安装创建测试文件验证安装：<?php require 'vendor/autoload.php'; use Carbon\Carbon; echo "当前时间：" . Carbon::now() . "\n"; echo "明天：" . Carbon::now()->addDay() . "\n"; echo "一周前：" . Carbon::now()->subWeek()->diffForHumans() . "\n";常见问题解决版本兼容性问题# 查看当前PHP版本支持的Carbon版本 php -v # 如果PHP版本较旧，使用Carbon 1.x composer require nesbot/carbon:^1.39内存问题# 清理composer缓存 composer clear-cache代理设置# 如果下载慢，使用国内镜像 composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/在框架中的使用LaravelCarbon 已集成在 Laravel 中，可直接使用：// 在Laravel中直接使用 $date = now(); // Carbon实例 echo $date->format('Y-m-d');其他框架// Slim, Symfony等框架 require __DIR__ . '/vendor/autoload.php'; use Carbon\Carbon; $carbon = new Carbon();这样就成功安装并可以使用 Carbon 来处理日期时间了。

PHP8.0 + 版本按数据处理类型分类的新增函数整理表格，包含函数名、对应版本、功能说明及可直接运行的用法示例
type: item
date: 2025-12-11T15:23:08+08:00
description: 分类函数名PHP版本功能说明用法示例字符串处理str_contains()8.0检查字符串是否包含指定子串（区分大小写），返回布尔值$str = "Hello PHP8"; var_dump(str_contains($str, "PHP8")); // bool(true)var_dump(str_contains($str, "php8")); // bool(false)字符串处理str_starts_with()8.0检查字符串是否以指定子串开头（区分大小写），返回布尔值$str = "2025-12-11"; var_dump(str_starts_with($str, "2025")); // bool(true)var_dump(str_starts_with($str, "2024")); // bool(false)字符串处理str_ends_with()8.0检查字符串是否以指定子串结尾（区分大小写），返回布尔值$str = "test.txt"; var_dump(str_ends_with($str, ".txt")); // bool(true)var_dump(str_ends_with($str, ".php")); // bool(false)字符串处理mb_str_split()8.0多字节安全的字符串分割，支持指定分割长度（解决str_split多字节乱码）$str = "你好PHP8"; print_r(mb_str_split($str)); // [0]=>你 [1]=>好 [2]=>P [3]=>H [4]=>P [5]=>8print_r(mb_str_split($str, 2)); // [0]=>你好 [1]=>PH [2]=>P8字符串处理strlcpy()8.1安全的字符串拷贝（限制长度，含终止符），返回源字符串总长度$dest = ''; $src = "Hello World";$len = strlcpy($dest, $src, 6); echo $dest; // Helloecho $len; // 11字符串处理mb_str_pad()8.3多字节安全的字符串填充（解决str_pad多字节长度计算错误）$str = "你好"; echo mb_str_pad($str, 5, "-", STR_PAD_RIGHT); // 你好---数组处理array_is_list()8.1检查数组是否为“列表”（索引从0开始、连续递增的整数索引），返回布尔值$list = [1,2,3]; $notList = [0=>1,2=>3];var_dump(array_is_list($list)); // bool(true) var_dump(array_is_list($notList)); // bool(false)数组处理array_find()8.3返回数组中第一个满足回调条件的元素，无则返回null$nums = [1,2,3,4,5]; $even = array_find($nums, fn($n) => $n % 2 === 0); echo $even; // 2数组处理array_find_key()8.3返回数组中第一个满足回调条件的键，无则返回null$users = ['a'=>18, 'b'=>22, 'c'=>19]; $key = array_find_key($users, fn($age) => $age > 20); echo $key; // b数组处理array_any()8.3检查数组是否存在至少一个满足回调条件的元素，返回布尔值$nums = [1,3,5]; var_dump(array_any($nums, fn($n) => $n%2===0)); // bool(false)$nums[]=8; var_dump(array_any($nums, fn($n) => $n%2===0)); // bool(true)数组处理array_all()8.3检查数组所有元素是否都满足回调条件，返回布尔值$nums = [2,4,6]; var_dump(array_all($nums, fn($n) => $n%2===0)); // bool(true)$nums[]=9; var_dump(array_all($nums, fn($n) => $n%2===0)); // bool(false)数值处理fdiv()8.0浮点数除法（优雅处理除0场景，返回INF/-INF/NaN，替代普通除法）var_dump(fdiv(10,2)); // float(5)var_dump(fdiv(10,0)); // float…

【Elasticsearch】Elasticsearch 与数据库实时同步方案
type: item
date: 2025-11-14T11:14:00+08:00
description: 在宝塔环境中实现 Elasticsearch 与数据库的实时同步，主要有以下几种方案：一、同步方案概览方案实时性复杂度数据一致性适用场景应用层双写最高中等最终一致新建项目，可修改代码Logstash JDBC分钟级低延迟一致已有项目，增量同步Canal秒级高最终一致MySQL 数据库，要求高实时性数据库触发器实时高强一致数据库层面同步二、方案一：应用层双写（推荐）实现原理在业务代码中同时写入数据库和 Elasticsearch。PHP 实现示例<?php /** * 应用层双写方案 * 在写入数据库的同时写入 Elasticsearch */ require '/www/wwwroot/your-site/vendor/autoload.php'; use Elasticsearch\ClientBuilder; class DualWriteService { private $esClient; private $db; public function __construct() { // 初始化 ES 客户端 $this->esClient = ClientBuilder::create() ->setHosts(['localhost:9200']) ->build(); // 初始化数据库连接 $this->initDatabase(); } private function initDatabase() { $host = 'localhost'; $dbname = 'your_database'; $username = 'your_username'; $password = 'your_password'; try { $this->db = new PDO( "mysql:host={$host};dbname={$dbname};charset=utf8mb4", $username, $password, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ] ); } catch (PDOException $e) { throw new Exception("数据库连接失败: " . $e->getMessage()); } } /** * 添加文章（双写） */ public function addArticle($articleData) { $dbResult = $this->writeToDatabase($articleData); if ($dbResult['success']) { $esResult = $this->writeToElasticsearch($articleData, $dbResult['id']); if (!$esResult['success']) { // ES 写入失败，记录日志或加入重试队列 $this->logSyncFailure('add', $dbResult['id'], $articleData); } return $dbResult; } return $dbResult; } /** * 更新文章（双写） */ public function updateArticle($id, $updateData) { $dbResult = $this->updateDatabase($id, $updateData); if ($dbResult['success']) { $esResult = $this->updateElasticsearch($id, $updateData); if (!$esResult['success']) { $this->logSyncFailure('update', $id, $updateData); } } return $dbResult; } /** * 删除文章（双写） */ public function deleteArticle($id) { $dbResult = $this->deleteFromDatabase($id); if ($dbResult['success']) { $esResult = $this->deleteFromElasticsearch($id); if (!$esResult['success']) { $this->logSyncFailure('delete', $id); } } return $dbResult; } /** * 写入数据库 */ private function writeToD…

【Elasticsearch】IK 分词器安装指南和PHP使用实例
type: item
date: 2025-11-13T11:38:00+08:00
description: IK 分词器安装指南是的，IK 分词器需要单独安装。 Elasticsearch 默认只提供标准分词器，对于中文分词效果不佳，IK 分词器是专门针对中文优化的分词插件。一、IK 分词器安装方法方法 1：手动安装（推荐）步骤 1：下载对应版本的 IK 分词器# 进入 Elasticsearch 插件目录 cd /www/server/elasticsearch/plugins # 创建 ik 目录 mkdir ik cd ik # 下载对应版本的 IK 分词器 # 注意：版本号必须与 Elasticsearch 版本一致！ # 查看 ES 版本：curl -X GET "localhost:9200/" wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.0/elasticsearch-analysis-ik-7.17.0.zip # 解压 unzip elasticsearch-analysis-ik-7.17.0.zip # 删除 zip 文件 rm -f elasticsearch-analysis-ik-7.17.0.zip # 返回插件目录上级，确保目录结构正确 cd .. ls -la ik/步骤 2：重启 Elasticsearch# 通过宝塔面板重启 # 或者使用命令 systemctl restart elasticsearch步骤 3：验证安装# 验证 IK 分词器是否安装成功 curl -X GET "localhost:9200/_cat/plugins?v" # 测试分词效果 curl -X POST "localhost:9200/_analyze" -H 'Content-Type: application/json' -d' { "analyzer": "ik_smart", "text": "中华人民共和国" }'正常响应：{ "tokens" : [ { "token" : "中华人民共和国", "start_offset" : 0, "end_offset" : 7, "type" : "CN_WORD", "position" : 0 } ] }方法 2：使用 Elasticsearch 插件命令安装# 进入 Elasticsearch 安装目录 cd /www/server/elasticsearch # 使用插件管理器安装 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.0/elasticsearch-analysis-ik-7.17.0.zip # 重启 Elasticsearch systemctl restart elasticsearch二、宝塔面板特有的安装方法通过宝塔终端操作打开宝塔面板 → 终端执行安装命令：# 切换到 elasticsearch 用户（宝塔环境可能需要） sudo -u elasticsearch /bin/bash # 进入 ES 插件目录 cd /www/server/elasticsearch/plugins # 下载并安装 IK 分词器 wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.0/elasticsearch-analysis-ik-7.17.0.zip unzip elasticsearch-analysis-ik-7.17.0.zip -d ik rm -f elasticsearch-analysis-ik-7.17.0.zip # 退出 elasticsearch 用户 exit # 重启 Elasticsearch 服务 systemctl restart elasticsearch宝塔文件管理器操作下载 IK 分词器：访问 IK 分词器 Releases下载对应版本的 ZIP 文件通过宝塔文件管理器上传：进入 /www/server/elasticsearch/plugins/创建 ik 文件夹上传 ZIP 文件到 ik 文件夹解压并删除 ZIP 文件重启服务：宝塔面板 → 软件商店 → Elasticsearch → 重启三、IK 分词器版本对应关系Elasticsearch 版本IK 分词器版本7.17.x7.17.07.16.x7.16.07.15.x7.15.07.14.x7.14.07.13.x7.13.07.12.x7.12.07.…

【Elasticsearch】Elasticsearch 安装步骤与常见问题解决
type: item
date: 2025-11-13T11:13:50+08:00
description: 1. 环境准备# 更新系统 sudo apt update && sudo apt upgrade -y # 安装 Java (Elasticsearch 需要 Java 环境) sudo apt install openjdk-11-jdk -y # 验证 Java 安装 java -version2. 安装 Elasticsearch方法一：使用 APT 仓库安装（推荐）# 导入 Elasticsearch GPG 密钥 wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add - # 添加 Elasticsearch 仓库 echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list # 更新并安装 sudo apt update sudo apt install elasticsearch方法二：手动下载安装# 下载 Elasticsearch wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.0-amd64.deb # 安装 sudo dpkg -i elasticsearch-7.17.0-amd64.deb3. 配置 Elasticsearch# 编辑配置文件 sudo vi /etc/elasticsearch/elasticsearch.yml主要配置项：# 集群名称 cluster.name: my-elasticsearch-cluster # 节点名称 node.name: node-1 # 数据存储路径 path.data: /var/lib/elasticsearch # 日志存储路径 path.logs: /var/log/elasticsearch # 网络绑定地址 network.host: 0.0.0.0 # HTTP 端口 http.port: 9200 # 集群初始主节点 cluster.initial_master_nodes: ["node-1"] # 允许跨域访问（用于开发） http.cors.enabled: true http.cors.allow-origin: "*"4. 启动和管理 Elasticsearch# 启动 Elasticsearch 服务 sudo systemctl start elasticsearch # 设置开机自启 sudo systemctl enable elasticsearch # 查看服务状态 sudo systemctl status elasticsearch # 重启服务 sudo systemctl restart elasticsearch # 停止服务 sudo systemctl stop elasticsearch5. 验证安装# 检查 Elasticsearch 是否运行 curl -X GET "localhost:9200/" # 查看集群健康状态 curl -X GET "localhost:9200/_cluster/health" # 查看节点信息 curl -X GET "localhost:9200/_nodes"正常响应示例：{ "name" : "node-1", "cluster_name" : "my-elasticsearch-cluster", "cluster_uuid" : "abcd1234", "version" : { "number" : "7.17.0", "build_flavor" : "default", "build_type" : "deb", "build_hash" : "abcdef123456", "build_date" : "2022-01-01T00:00:00.000Z", "build_snapshot" : false, "lucene_version" : "8.11.1", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }6. 安全配置（可选）# 安装 Elasticsearch 安全插件 sudo /usr/share/elastics…

【Elasticsearch】 PHP 使用ES示例demo
type: item
date: 2025-11-13T11:13:00+08:00
description: 1. 使用 Composer 安装# 安装 Composer（如果未安装） curl -sS https://getcomposer.org/installer | php sudo mv composer.phar /usr/local/bin/composer # 创建项目目录 mkdir elasticsearch-php-demo cd elasticsearch-php-demo # 初始化 Composer composer init # 安装 Elasticsearch PHP 客户端 composer require elasticsearch/elasticsearch2. 手动安装（不使用 Composer）<?php // 手动引入 Elasticsearch 客户端 require_once 'path/to/elasticsearch-php/autoload.php';示例 1：基础连接和索引操作<?php require 'vendor/autoload.php'; use Elasticsearch\ClientBuilder; class ElasticsearchDemo { private $client; public function __construct() { // 创建 Elasticsearch 客户端 $this->client = ClientBuilder::create() ->setHosts(['localhost:9200']) // ES 服务器地址 ->setRetries(2) // 重试次数 ->build(); // 检查连接 if (!$this->checkConnection()) { throw new Exception("无法连接到 Elasticsearch"); } } /** * 检查 Elasticsearch 连接 */ private function checkConnection() { try { return $this->client->ping(); } catch (Exception $e) { echo "连接失败: " . $e->getMessage() . "\n"; return false; } } /** * 创建索引 */ public function createIndex($indexName) { $params = [ 'index' => $indexName, 'body' => [ 'settings' => [ 'number_of_shards' => 2, 'number_of_replicas' => 1 ], 'mappings' => [ 'properties' => [ 'title' => [ 'type' => 'text', 'analyzer' => 'standard' ], 'content' => [ 'type' => 'text', 'analyzer' => 'standard' ], 'author' => [ 'type' => 'keyword' ], 'publish_date' => [ 'type' => 'date' ], 'views' => [ 'type' => 'integer' ] ] ] ] ]; try { $response = $this->client->indices()->create($params); echo "索引 {$indexName} 创建成功\n"; return $response; } catch (Exception $e) { echo "创建索引失败: " . $e->getMessage() . "\n"; return false; } } /** * 删除索引 */ public function deleteIndex($indexName) { $params = ['index' => $indexName]; try { // 检查索引是否存在 if ($this->client->indices()->exists($params)) { $response = $this->client->indices()->delete($params); echo "索引 {$indexName} 删除成功\n"; return $response; } else { echo "索引 {$indexName} 不存在\n"; return false; } } catch (Exception $e) { echo "删除索引失败: " . $e->getMessage()…

【MySQL】MySQL 各主要版本的区别
type: item
date: 2025-10-21T09:17:23+08:00
description: MySQL 版本演进概览MySQL 的主要版本发展可以概括为：5.1 -> 5.5 -> 5.6 -> 5.7 -> 8.0。目前，MySQL 5.7 已于 2023年10月结束官方支持，MySQL 8.0 是绝对的主流和未来。新项目都应选择 8.0 或更高版本。各主要版本核心区别与特性下面我们按版本从新到旧进行梳理，重点对比 5.7 和 8.0 这两个最关键版本。MySQL 8.0 (2018年发布，当前主流)8.0 是一个里程碑式的大版本，引入了大量革命性的新特性。类别核心特性与改进说明性能与存储事务性数据字典将系统表（如 user, db）从 MyISAM 引擎迁移到 InnoDB 引擎，并存储于数据字典表中，支持原子DDL，使元数据管理更安全、可靠。 直方图为优化器提供表中数据分布的统计信息，帮助优化器在非索引字段上生成更优的执行计划。 不可见索引可以将索引设置为“不可见”，优化器会忽略它，用于测试删除某个索引是否会对性能产生负面影响，而无需真正删除。 降序索引支持按降序存储索引，对于 ORDER BY column DESC 的查询性能大幅提升。SQL功能通用表表达式支持 WITH 语句，可以创建命名的临时结果集，支持递归查询，处理树状或层次结构数据非常方便。 窗口函数支持 ROW_NUMBER(), RANK(), LAG() 等强大的分析函数，无需分组即可对行数据进行复杂计算。 资源组可以将线程绑定到特定的CPU核心上，实现更精细化的资源管理。 JSON增强引入了 JSON_TABLE(), JSON_OBJECTAGG(), JSON_ARRAYAGG() 等更多JSON函数，功能更强大。安全与管理角色引入了数据库角色，可以批量管理用户权限，极大简化了权限管理。 默认字符集默认字符集从 latin1 改为 utf8mb4，更好地支持全球化和emoji表情。 默认认证插件默认的身份认证插件改为 caching_sha2_password，比之前的 mysql_native_password 更安全，但可能导致一些旧的客户端/驱动需要升级。 持久化系统变量使用 SET PERSIST 命令设置的变量在服务器重启后依然有效。MySQL 5.7 (2015年发布，已停止支持)5.7 是一个极其成功和稳定的版本，在其生命周期内是生产环境的绝对主力。类别核心特性与改进说明性能与复制InnoDB 增强在线缓冲池调整、在线修改 VARCHAR 长度、多线程页面清理等，提升了并发处理能力和在线操作能力。 组提交实现了多线程组提交，极大改善了在高并发写场景下的性能。 多源复制一个从库可以同时从多个主库复制数据，用于数据汇总。 增强的半同步复制引入了无损复制，保证主从数据强一致性。SQL功能原生JSON支持引入了 JSON 数据类型，并提供 JSON_EXTRACT, JSON_OBJECT 等函数，但功能不如 8.0 强大。 生成列可以创建由其他列计算得出的列，分为 VIRTUAL（不存储）和 STORED（存储）两种。 Sys Schema引入了一个名为 sys 的系统库，提供了一系列视图、函数和存储过程，让性能诊断和问题排查变得非常简单。 空间数据支持增强了对 GIS 数据的支持。安全密码验证策略引入了密码过期策略和密码强度验证插件。MySQL 5.6 (2013年发布，已停止支持)5.6 版本是 InnoDB 引擎和优化器能力大幅提升的版本。核心特性与改进说明InnoDB 性能提升成为绝对的默认存储引擎，提供了全文索引、独立的 undo tablespace。优化器改进引入了索引条件下推，可以在存储引擎层利用索引过滤数据，减少回表次数。复制增强支持基于库的并行复制，提升了从库的复制性能。支持 GTID，使主从切换和故障恢复更方便。在线DDL支持了更多种类的在线 DDL 操作，减少了对业务的影响。MySQL 5.5 (2010年发布，已停止支持)核心特性与改进说明InnoDB 成为默认引擎取代 MyISAM，标志着 MySQL 向事务安全型数据库的彻底转变。半同步复制提供了比异步复制更强的数据一致性保证。性能提升引入了 InnoDB 的缓冲池预加载等特性。总结与版本选择建议版本状态建议MySQL 8.0积极维护，长期支持强烈推荐。所有新项目都应选择此版本。它提供了最好的性能、最丰富的功能和最新的安全更新。MySQL 5.7已停止官方支持不推荐。仅适用于尚未完成升级的遗留系统，应尽快制定迁移计划至 8.0。MySQL 5.6 及更早已停止官方支持绝对禁止。存在已知安全漏洞且无修复，必须立即升级。升级路径通常的升级路径是：5.5/5.6 -> 5.7 -> 8.0。从 5.7 升级到 8.0 前，务必仔细阅读官方文档，进行充分的兼…

【Linux】Linux 开发与运维命令终极手册 - 持续更新
type: item
date: 2025-09-10T09:47:00+08:00
description: Linux 开发与运维命令终极手册封面与使用说明适用人群：PHP开发者、后端工程师、运维人员 核心价值：从日常开发到应急调试的全场景命令参考，兼顾效率与安全 使用方法：按「场景速查」快速定位，按「功能分类」系统学习，注意「安全警告」规避风险一、场景速查索引（紧急情况优先看）问题场景核心命令链功能分类网站突然卡顿/502错误top（看CPU/内存）→ ss -s（连接数）→ systemctl status php-fpm（服务状态）五、一.........二、系统基础与环境监控系统信息uname：查看系统信息uname -a # 完整信息 uname -r # 内核版本（确认Docker/Kernel兼容性）lsb_release：发行版信息lsb_release -a # 所有信息 lsb_release -c # 版本代号（适配apt/yum源）磁盘与存储df：磁盘空间df -h # 人类可读格式 df -i # inode使用情况（紧急清理时，满需删除大量小文件）du：目录大小分析du -sh * # 当前目录各项目大小 du -h --max-depth=1 /var # 一级目录分析 du -sh * \| sort -hr # 从大到小排列内存与负载free：内存监控free -h # 易读格式 free -m # MB单位 watch -n 5 "free -h" # 每5秒刷新（内存泄漏排查）uptime：系统负载uptime # 显示1/5/15分钟平均负载（负载>CPU核心数时需排查进程）高级监控iostat：磁盘IO监控iostat -x 5 # 每5秒显示IO详情（%util接近100%表示IO饱和）which/whereis：命令路径查找which php # 检查php路径 whereis mysql # 查找mysql（区分系统自带与手动安装的程序）三、文件与目录操作基本操作ls：列出内容ls -lh # 详细+大小 ls -lt # 按修改时间排序 # 现代替代：exa -l --git（带Git状态和颜色）cd：切换目录cd ~ # 家目录 cd - # 返回上一目录 # 技巧：cd .. 可简写为 ..（需配置bash）mkdir：创建目录mkdir -p app/{ctrl,model,view} # 递归创建多级目录（一次性创建项目结构）文件操作rm：删除文件 ⚠️极度危险rm file.txt # 删除文件 rm -rf dir/ # 递归强制删除目录 # ⚠️ 安全准则： # 1. 禁止执行 rm -rf / 或 rm -rf /* # 2. 删前先用 ls 确认路径：ls dir/ # 3. 替代方案：trash-put file（移到回收站，需安装trash-cli）cp：复制文件cp -a src/ dest/ # 保留权限复制 cp config.php{,.bak} # 备份（生成config.php.bak） cp *.conf{,.bak} # 批量备份（给所有conf文件加备份后缀）高级文件操作find：查找文件find ./ -name "*.php" -mtime -1 # 1天内修改的PHP文件 find ./ -name "*.log" -mtime +30 -print0 | xargs -0 rm -f # 安全批量处理（处理含空格的文件名）ln：创建链接ln -s /usr/local/php/bin/php /usr/bin/php # 创建软链接（解决命令路径问题）rsync：增量同步rsync -avz --delete ./local/ user@server:/remote/ # 镜像同步（部署代码比scp快）四、文件内容处理查看内容cat：查看文件内容cat config.php # 查看文件 # 现代替代：bat config.php（代码高亮+行号）tail：查看尾部tail -f error.log # 实时监控 tail -n 50 access.log # 最后50行 tail -F error.log # 日志轮转必备（文件重建后仍跟踪）文本处理grep：文本搜索grep -rni "数据库" ./app # 递归+行号+忽略大小写搜索 find ./ -name "*.php" | xargs grep "function getUser" # 结合find搜索sed：文本替换sed -i 's/old/new/g' file.php # 批量替换 sed -i '/^#/d' nginx.conf # 删除注释行 sed -i 's/debug=true/debug=false/g' *.php # 批量修改配置awk：按列处…

【PHP】境外微信支付生成平台证书 - wechatpay
type: item
date: 2025-09-05T17:56:00+08:00
description: 使用方法 $wechatPayPlatformCertInstance = new \addons\unidrink\library\pay\overseas\wechat\Certificate(); try { $platformCerts = $wechatPayPlatformCertInstance->getPlatformCerts(); if (!empty($platformCerts)) { // 获取最新的证书 $latestCert = $platformCerts[0]; // 返回成功信息 return json([ 'code' => 1, 'msg' => '平台证书生成成功', 'data' => [ 'serial_no' => $latestCert['serial_no'], 'effective_time' => $latestCert['effective_time'], 'expire_time' => $latestCert['expire_time'], 'cert_saved_path' => $wechatPayPlatformCertInstance->getCertPath() . $latestCert['serial_no'] . '.pem', ] ]); } else { throw new Exception('未获取到平台证书'); } } catch (Exception $e) { // 错误处理 return json([ 'code' => 0, 'msg' => '平台证书生成失败: ' . $e->getMessage(), 'data' => [] ]); } 下面是类 <?php namespace addons\unidrink\library\pay\overseas\wechat; use think\Exception; use think\Log; use WeChatPay\Crypto\Rsa; use WeChatPay\Formatter; use WeChatPay\Util\PemUtil; class Certificate { // 配置参数 private $config; // 证书保存路径 private $certPath; // 平台证书列表 private $platformCerts = []; /** * 构造函数 * @param array $config 微信支付配置 */ public function __construct($config = []) { // 默认配置 $defaultConfig = [ 'mch_id' => '', // 商户号 'serial_no' => '', // 商户API证书序列号 'private_key' => ROOT_PATH . 'public/cert/apiclient_key.pem', // 商户私钥内容或路径 'api_v3_key' => '', // APIv3密钥 'cert_path' => ROOT_PATH . 'public/cert/wechatpay/', // 证书保存目录 'ca_cert_path' => ROOT_PATH . 'public/cert/cacert.pem' // CA证书路径 ]; $this->config = array_merge($defaultConfig, $config); $this->certPath = $this->config['cert_path']; // 验证APIv3密钥长度 $this->validateApiV3Key(); // 创建证书目录并确保权限 $this->prepareDirectories(); } /** * 准备目录并确保权限 */ private function prepareDirectories() { // 创建证书目录 if (!is_dir($this->certPath)) { if (!mkdir($this->certPath, 0755, true)) { throw new Exception('无法创建证书目录: ' . $this->certPath); } } // 检查证书目录权限 if (!is_writable($this->certPath)) { throw new Exception('证书目录不可写: ' . $this->certPath); } // 确保CA证书目录可写 $caCertDir = dirname($this->config['ca_cert_path']); if (!i…

【Redis】Redis的操作方法整理
type: item
date: 2025-08-20T09:38:07+08:00
description: <?php // 配置连接的IP、端口、以及相应的数据库 $server = array( 'host' => '127.0.0.1', 'port' => 6379, 'database' => 15 ); $redis = new Client($server); // 普通set/get操作 $redis->set('library', 'predis'); $retval = $redis->get('library'); echo $retval; // 显示 'predis' // setex set一个存储时效 $redis->setex('str', 10, 'bar'); // 表示存储有效期为10秒 // setnx/msetnx相当于add操作,不会覆盖已有值 $redis->setnx('foo', 12); // true $redis->setnx('foo', 34); // false // getset操作,set的变种,结果返回替换前的值 $redis->getset('foo', 56); // 返回34 // incrby/incr/decrby/decr 对值的递增和递减 $redis->incr('foo'); // foo为57 $redis->incrby('foo', 2); // foo为59 // exists检测是否存在某值 $redis->exists('foo'); // true // del 删除 $redis->del('foo'); // true // type 类型检测,字符串返回string,列表返回 list,set表返回set/zset,hash表返回hash $redis->type('foo'); // 不存在,返回none $redis->set('str', 'test'); $redis->type('str'); // 字符串，返回string // append 连接到已存在字符串 $redis->append('str', '_123'); // 返回累加后的字符串长度8,此进str为 'test_123' // setrange 部分替换操作 $redis->setrange('str', 0, 'abc'); // 返回3,参数2为0时等同于set操作 $redis->setrange('str', 2, 'cd'); // 返回4,表示从第2个字符后替换,这时'str'为'abcd' // substr 部分获取操作 $redis->substr('str', 0, 2); // 表示从第0个起，取到第2个字符，共3个，返回'abc' // strlen 获取字符串长度 $redis->strlen('str'); // 返回4 // setbit/getbit 位存储和获取 $redis->setbit('binary', 31, 1); // 表示在第31位存入1,这边可能会有大小端问题?不过没关系,getbit 应该不会有问题 $redis->getbit('binary', 31); // 返回1 // keys 模糊查找功能,支持*号以及?号(匹配一个字符) $redis->set('foo1', 123); $redis->set('foo2', 456); $redis->keys('foo*'); // 返回foo1和foo2的array $redis->keys('f?o?'); // 同上 // randomkey 随机返回一个key $redis->randomkey(); // 可能是返回 'foo1'或者是'foo2'及其它任何一存在redis的key // rename/renamenx 对key进行改名,所不同的是renamenx不允许改成已存在的key $redis->rename('str', 'str2'); // 把原先命名为'str'的key改成了'str2' // expire 设置key-value的时效性,ttl 获取剩余有效期,persist 重新设置为永久存储 $redis->expire('foo', 1); // 设置有效期为1秒 $redis->ttl('foo'); // 返回有效期值1s $redis->expire('foo'); // 取消expire行为 // dbsize 返回redis当前数据库的记录总数 $redis->dbsize(); /* * 队列操作 */ // rpush/rpushx 有序列表操作,从队列后插入元素 // lpush/lpushx 和rpush/rpushx的区别是插入到队列的头部,同上,'x'含义是只对已存在的key进行操作 $…