PHP 字符串处理:去除 JSON 中多余的逗号 作者: Chuwen 时间: 2024-10-11 分类: PHP 评论 在处理 JSON 数据时,有时可能会遇到一些格式问题,比如在对象或数组的最后一个元素后意外多出一个逗号。这类格式错误会导致 `json_decode()` 函数解析失败。因此,我们可以在解析之前,预先清理这些多余的逗号。 ## 1. 使用正则表达式处理多余逗号 在处理 JSON 数据时,可以使用正则表达式来匹配并移除对象或数组最后一个元素后面的逗号。以下是一个示例代码,展示如何通过 `preg_replace` 来解决这个问题: ```php
记一次使用 Laravel Http Client 使用不当导致内存泄漏的问题 作者: Chuwen 时间: 2023-12-06 分类: PHP 评论 ## 背景 Laravel 的[ HTTP Client](https://laravel.com/docs/10.x/http-client " HTTP Client") 基于 Guzzle 二次封装,操作很方便,所以在业务代码上我就这么写了类似的代码 ```php $url = 'https://xxxx/xxx.json'; $json = Illuminate\Support\Facades\Http::get($url)->json(); // TODO 业务逻辑处理 ``` 项目使用了 [laravels](https://github.com/hhxsv5/laravel-s "laravels"),所以项目是常驻内存的,但是经过观察发 worker 内存会随着请求数量慢慢增加,并且不会自动回收内存,导致最终内存不足程序异常终止: ``` PHP Fatal error: Allowed memory size of 67108864 bytes exhausted (tried to allocate 360448 bytes) in /Users/shine/work/xxxxxx-project/vendor/guzzlehttp/psr7/src/Utils.php on line 414 Symfony\Component\ErrorHandler\Error\FatalError Allowed memory size of 67108864 bytes exhausted (tried to allocate 360448 bytes) at vendor/guzzlehttp/psr7/src/Utils.php:414 410▕ }); 411▕ 412▕ try { 413▕ /** @var string|false $contents */ ➜ 414▕ $contents = stream_get_contents($stream); 415▕ 416▕ if ($contents === false) { 417▕ $ex = new \RuntimeException('Unable to read stream contents'); 418▕ } Whoops\Exception\ErrorException Allowed memory size of 67108864 bytes exhausted (tried to allocate 360448 bytes) at vendor/guzzlehttp/psr7/src/Utils.php:414 410▕ }); 411▕ 412▕ try { 413▕ /** @var string|false $contents */ ➜ 414▕ $contents = stream_get_contents($stream); 415▕ 416▕ if ($contents === false) { 417▕ $ex = new \RuntimeException('Unable to read stream contents'); 418▕ } +1 vendor frames 2 [internal]:0 Whoops\Run::handleShutdown() ``` ## 解决方案 通过研究框架代码,发现是没有正常关闭 Guzzle stream,导致内存一直累积无法回收 然后又在在 [vendor/laravel/framework/src/Illuminate/Http/Client/Response.php:247](https://github.com/laravel/framework/blob/10.x/src/Illuminate/Http/Client/Response.php#L247 "vendor/laravel/framework/src/Illuminate/Http/Client/Response.php:247") 位置发现有一个 `close()` 方法,但这个方法没有在任何地方使用,应该是想让你手动调用进行关闭 stream 所以将代码改成如下就可以了 ```php $url = 'https://xxxx/xxx.json'; $response = Illuminate\Support\Facades\Http::get($url); $json = $response->json(); // 关闭 stream $response->close(); // TODO 业务逻辑处理 ``` ## 附测试内存泄漏代码 ```php json(); printf("Count: %d\tPHP Memory: %.1fMB\n", $i++, memory_get_usage(true) / 1024.00 / 1024.00); } ``` ![](https://cdn.nowtime.cc/2023/12/06/138987942.png) ## 附测试修复内存泄漏后的代码 ```php body()) / 1024); $response->close(); } ``` ![](https://cdn.nowtime.cc/2023/12/06/3782614807.png)
PHP 8.1 Enum (枚举) 根据名字取得枚举 作者: Chuwen 时间: 2023-09-21 分类: PHP 评论 灵感来源于:https://github.com/php/php-src/issues/9352#issuecomment-1216839118 ```php $enumClass * @param string $name * @return T|null */ function tryFromName(string $enumClass, string $name) { $constName = $enumClass . '::' . $name; return is_subclass_of($enumClass, UnitEnum::class) && defined($constName) ? constant($constName) : null; } // enum(Gender::UNKNOWN) var_dump(tryFromName(Gender::class, 'UNKNOWN')); // enum(Gender::MALE) var_dump(tryFromName(Gender::class, 'MALE')); // enum(Gender::FEMALE) var_dump(tryFromName(Gender::class, 'FEMALE')); // NULL var_dump(tryFromName(Gender::class, 'null')); ```
php-cs-fix 只格式化已经修改的代码 / 只格式化某次提交的代码 作者: Chuwen 时间: 2023-09-21 分类: PHP 评论 ## 前提 注意需要在 `composer.json` 中的 `scripts:` 部分添加 `"cs-fix": "php-cs-fixer fix $1"`,如下示例 ```json { "name": "hyperf/hyperf-skeleton", "type": "project", // ... "autoload": { "psr-4": { "App\\": "app/" }, "files": [] }, "scripts": { // ...... "cs-fix": "php-cs-fixer fix $1", // ...... }, } ``` ## 命令 ### 只格式化已经修改的代码 ```shell git diff --name-only --cached | grep '\.php$' | xargs -n1 composer cs-fix ``` 1. `git diff --name-only --cached`:这部分命令用于获取你已经暂存(staged)的修改文件的列表。 2. `grep '\.php$'`:通过管道将文件列表传递给grep命令,这将只选择扩展名为 `.php` 的文件。 3. `xargs -n1 composer cs-fix`:xargs命令将每个文件名作为参数传递给 `composer cs-fix` 命令,从而格式化每个文件的代码。 ### 格式化某次提交的代码 ```shell git diff-tree --no-commit-id --name-only -r | grep '\.php$' | xargs -n1 composer cs-fix ``` 1. `git diff-tree --no-commit-id --name-only -r `:这部分命令获取了特定提交记录中的修改文件列表。 > **** 可以从 `git log` 获取 2. `grep '\.php$'`:通过管道将文件列表传递给 `grep` 命令,这将只选择扩展名为 `.php` 的文件。 3. `xargs -n1 composer cs-fix`:`xargs` 命令将每个文件名作为参数传递给 `composer cs-fix` 命令,从而格式化每个文件的代码。
pecl install swoole 安装出错:fatal error: pcre2.h: No such file or directory 作者: Chuwen 时间: 2023-09-19 分类: PHP,其他分类 评论 安装错误日志: ```log In file included from /home/linuxbrew/.linuxbrew/Cellar/php@8.1/8.1.23/include/php/ext/spl/spl_iterators.h:22, from /home/linuxbrew/.linuxbrew/Cellar/php@8.1/8.1.23/include/php/ext/spl/spl_array.h:22, from /tmp/pear/temp/swoole/ext-src/swoole_coroutine.cc:27: /home/linuxbrew/.linuxbrew/Cellar/php@8.1/8.1.23/include/php/ext/pcre/php_pcre.h:23:10: fatal error: pcre2.h: No such file or directory 23 | #include "pcre2.h" | ^~~~~~~~~ compilation terminated. make: *** [Makefile:233: ext-src/swoole_coroutine.lo] Error 1 ERROR: `make' failed ``` ## 错误原因 这个错误消息表明编译或构建过程中缺少 pcre2.h 头文件,导致无法找到它。pcre2.h 是 PCRE2(Perl Compatible Regular Expressions)库的头文件,通常用于正则表达式操作。 ## 解决方案 **安装 PCRE2 库** 在 Ubuntu/Debian 上: ```shell sudo apt-get install libpcre2-dev ``` 在 CentOS/RHEL 上: ```shell sudo yum install pcre2-devel ``` 在 macOS 上,你可以使用 Homebrew 安装: ```shell brew install pcre2 ``` 最终完美解决,我这里正常安装 `swoole` 扩展 ``` Build process completed successfully Installing '/home/linuxbrew/.linuxbrew/Cellar/php@8.1/8.1.23/pecl/20210902/swoole.so' Installing '/home/linuxbrew/.linuxbrew/Cellar/php@8.1/8.1.23/include/php/ext/swoole/config.h' Installing '/home/linuxbrew/.linuxbrew/Cellar/php@8.1/8.1.23/include/php/ext/swoole/php_swoole.h' install ok: channel://pecl.php.net/swoole-5.0.3 Extension swoole enabled in php.ini ```