<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>PHP on Wi1dcard</title><link>https://wi1dcard.dev/tags/php/</link><description>Recent content in PHP on Wi1dcard</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Fri, 22 Mar 2019 19:09:26 +0000</lastBuildDate><atom:link href="https://wi1dcard.dev/tags/php/index.xml" rel="self" type="application/rss+xml"/><item><title>我如何实现 Laravel-China 全自动系列文章发布</title><link>https://wi1dcard.dev/posts/automatic-learnku-deploy-bot/</link><pubDate>Fri, 22 Mar 2019 19:09:26 +0000</pubDate><guid>https://wi1dcard.dev/posts/automatic-learnku-deploy-bot/</guid><description>&lt;p>在早期 &lt;a href="https://github.com/wi1dcard/laravel-deployment" target="_blank">轻松部署 Laravel 应用&lt;/a> 课程开始编写之前，就考虑到一个非常重要的问题：&lt;strong>如何保证 Laravel-China 上发布的文章与 GitHub 仓库内的 Markdown 源文件保持同步&lt;/strong>？&lt;/p></description></item><item><title>将 PHP 应用快速打包为 PHAR</title><link>https://wi1dcard.dev/posts/packaging-apps-with-phar/</link><pubDate>Tue, 15 Jan 2019 00:03:57 +0000</pubDate><guid>https://wi1dcard.dev/posts/packaging-apps-with-phar/</guid><description>&lt;p>&lt;a href="https://github.com/humbug/box" target="_blank">humbug/box&lt;/a> 是一款快速的、零配置的 PHAR 打包工具。&lt;/p>
&lt;p>还记得前些天的《&lt;a href="https://laravel-china.org/articles/19742" target="_blank">SMProxy,让你的数据库操作快三倍！&lt;/a>》吗，该项目的 PHAR 便是使用 Box 打包完成的。&lt;/p></description></item><item><title>在 PHP 中格式化并高亮 SQL 语句</title><link>https://wi1dcard.dev/posts/format-sql-statements-in-php/</link><pubDate>Thu, 10 Jan 2019 21:27:06 +0000</pubDate><guid>https://wi1dcard.dev/posts/format-sql-statements-in-php/</guid><description>&lt;p>&lt;a href="https://github.com/jdorn/sql-formatter" target="_blank">jdorn/sql-formatter&lt;/a> 是一个轻量级的 PHP 类用于格式化 SQL 语句。&lt;/p>
&lt;p>它支持自动进行缩进、添加换行，甚至还支持语法高亮。&lt;/p></description></item><item><title>Laravel 二级域名绑定子目录 Nginx 配置</title><link>https://wi1dcard.dev/posts/laravel-nginx-subdomains/</link><pubDate>Mon, 15 Oct 2018 16:55:07 +0000</pubDate><guid>https://wi1dcard.dev/posts/laravel-nginx-subdomains/</guid><description>二级域名绑定子目录 Nginx + PHP-FPM 配置，内置 Laravel 重写规则，可用于本地多项目开发。
在 Nginx 的站点配置目录新增站点后，增加以下代码块即可。
server_name ~^(.*)\.laravel\.test$; # 正则二级域名 root /Users/jootu/web/$1/public; index index.html index.htm index.php; location / { try_files $uri $uri/ /index.</description></item><item><title>PSR-7 与 HTTPlug</title><link>https://wi1dcard.dev/posts/psr7-and-httplug/</link><pubDate>Sat, 06 Oct 2018 16:05:41 +0000</pubDate><guid>https://wi1dcard.dev/posts/psr7-and-httplug/</guid><description>前言 最近国庆期间没继续开发项目，据说要有大变动，等国庆后开会讨论，内心有点方张。
Updated: 国庆后的第一天，果然砍了。难受。
趁着假期，封装了两个扩展包。
中国行政区划地址库 SDK &amp;#43; 爬虫 &amp;#43; 数据 百度小程序第三方 PHP SDK 在构建后者的时候，考虑到 PSR-7 逐渐在 PHP 生态圈被大众接受，经过斟酌决定将 HTTP 客户端与 SDK 自身逻辑分离，完全遵循 PSR-7，所有请求都实现为 RequestInterface，随后使用任意兼容 PSR-7 的客户端发送即可，扩展包本身不关注 HTTP 协议的数据传输。</description></item><item><title>Laravel 5.7 重写软删除字段为时间戳</title><link>https://wi1dcard.dev/posts/laravel-model-override-soft-delete/</link><pubDate>Tue, 25 Sep 2018 13:47:38 +0000</pubDate><guid>https://wi1dcard.dev/posts/laravel-model-override-soft-delete/</guid><description>0x00 背景 Laravel 自带软删除使用特殊值 NULL 表示此记录未被删除。由此引出一个问题。
设想，某表内需要建立索引，索引字段为 name, deleted_at。
假设此索引条件必定唯一，可建立 Uniuqe 索引。然而 deleted_at 允许 NULL 存在，导致索引无效，在查询时降级为 Index。
因此，在绝大多数场景下，我们查询未被删除（deleted_at IS NULL）的数据，唯一索引都没有卵用。</description></item><item><title>Laravel 5.7 模型常用属性集合</title><link>https://wi1dcard.dev/posts/laravel-eloquent-model-properties/</link><pubDate>Tue, 18 Sep 2018 09:15:25 +0000</pubDate><guid>https://wi1dcard.dev/posts/laravel-eloquent-model-properties/</guid><description>Laravel 5.7 于前几天发布，迫不及待给正在开发的新项目做了升级。
在此整理一下模型常用属性，以备日后查询。
$fillable = [ &amp;#39;可批量填充的字段&amp;#39; ]; $guarded = [ &amp;#39;与上相反&amp;#39; ]; $hidden = [ &amp;#39;模型转换为数组时应当隐藏的字段&amp;#39; ]; $visable = [ &amp;#39;与上相反&amp;#39; ]; $appends = [ &amp;#39;模型转换为数组时应当追加的虚拟字段&amp;#39; // 例如访问器 ]; $with = [ &amp;#39;应当预加载的关联关系&amp;#39;, ]; $attributes = [ &amp;#39;字段名&amp;#39; =&amp;gt; &amp;#39;字段默认值&amp;#39; ]; $casts = [ &amp;#39;字段名&amp;#39; =&amp;gt; &amp;#39;自动类型转换的目标类型&amp;#39; ]; $dates = [ &amp;#39;应当被转换为日期时间的字段&amp;#39; ]; $touches = [ &amp;#39;模型更新时应当一并更新的关联关系&amp;#39; ]; // 以下为扩展包使用的属性 // https://github.</description></item><item><title>Packagist（Composer）中国镜像</title><link>https://wi1dcard.dev/posts/packagist-mirror-in-china/</link><pubDate>Wed, 05 Sep 2018 09:31:33 +0000</pubDate><guid>https://wi1dcard.dev/posts/packagist-mirror-in-china/</guid><description>&lt;p>从七月份得知国内镜像开始「体检」之后，一直没有收到恢复的消息。&lt;/p></description></item><item><title>我的周报工具箱</title><link>https://wi1dcard.dev/posts/weekly-report-toolkit/</link><pubDate>Thu, 30 Aug 2018 13:42:06 +0000</pubDate><guid>https://wi1dcard.dev/posts/weekly-report-toolkit/</guid><description>大概在两个月以前，刚入职目前所在的公司，要求写周报，而且要求比较详细，每天的任务都需要列清楚。
对于我这种很健忘，并且喜欢以结果为导向，专注于代码的程序员简直要命。
所以下决心，搞个帮我写周报的工具。于是这个项目诞生了。
自己用了一阵子感觉还不错，经过一番整理完善决定开源。
仓库地址：https://github.com/wi1dcard/weekly-report
其实没什么技术含量，无非就是利用 Git 的提交记录，编排成 Markdown。
BTW，其实或许用 Python 写会更合适。
最后，我的周报项目 VS Code 配置如下。
{ &amp;#34;[markdown]&amp;#34;: { &amp;#34;editor.wordWrap&amp;#34;: &amp;#34;off&amp;#34;, &amp;#34;editor.</description></item><item><title>Yii2 获取当前请求的路由信息</title><link>https://wi1dcard.dev/posts/yii2-get-current-request-route/</link><pubDate>Wed, 29 Aug 2018 13:48:19 +0000</pubDate><guid>https://wi1dcard.dev/posts/yii2-get-current-request-route/</guid><description>如题，有两种方案实现。
方案一：
Yii::$app-&amp;gt;controller-&amp;gt;route; 方案二：
Yii::$app-&amp;gt;requestedRoute 看过源码后才知道这俩的区别。
方案一是根据当前请求已创建的 module / controller / action，也就是实际处理当前请求的模块、控制器、方法所组合而成的路由，绝对规范。
方案二是根据 UrlManager::routeParam 等配置，解析请求 URL 取得的访问路由，不一定规范，但对用户可见。
通常情况下两种方法应该是等效的；某些特殊场景，例如修改过根据路由解析创建控制器的过程、内部反代重写过 URL 等，则有可能导致两方得到的值不一致。</description></item><item><title>Laravel 5.6 自定义迁移桩代码</title><link>https://wi1dcard.dev/posts/laravel-custom-migration-stub/</link><pubDate>Tue, 28 Aug 2018 13:33:16 +0000</pubDate><guid>https://wi1dcard.dev/posts/laravel-custom-migration-stub/</guid><description>书接上回，前面说到在迁移内给 Blueprint 增加自定义的 Macro。那么，当我们每次使用 php artisan make:migration 都需要手动修改一次模板吗？这不清真 = =。
0x00 思路 自定义 make:migration 所使用的 stub（「桩」，可以理解为模板）文件即可。
在开始之前，你首先需要创建属于你的 stubs 文件，我建议直接从 Laravel 5.</description></item><item><title>Laravel 5.6 给 Blueprint 增加自定义方法</title><link>https://wi1dcard.dev/posts/laravel-blueprint-macro/</link><pubDate>Tue, 28 Aug 2018 02:41:00 +0000</pubDate><guid>https://wi1dcard.dev/posts/laravel-blueprint-macro/</guid><description>PHP 基本功足够扎实的情况下，强烈建议学习 Laravel 的过程除了阅读官方文档外，仔细阅读框架源码；或许会有小惊喜哟。
0x00 准备 Laravel 5.6 php artisan make:migration ... 近期在项目过程中，遇到这么个需求：在所有模型表内都需要支持自增主键 id、创建时间、更新时间以及软删除，以备不时之需。
于是乎。传统的做法是，在每个迁移 Schema::create 回调内，都写一遍 $table-&amp;gt;increments + softDeletes + timestamps，就像这样：</description></item><item><title>PHP JSON Serializer</title><link>https://wi1dcard.dev/posts/php-json-serializer/</link><pubDate>Tue, 21 Aug 2018 19:14:26 +0000</pubDate><guid>https://wi1dcard.dev/posts/php-json-serializer/</guid><description>Serialize &amp;amp; unserialize data to &amp;amp; from JSON. Compatible with serialized data and supported accessing unserialized data as a object &amp;amp; array.</description></item><item><title>Laravel 5.6 路由参数排除匹配</title><link>https://wi1dcard.dev/posts/laravel-route-pattern-exclude/</link><pubDate>Sat, 18 Aug 2018 01:52:37 +0000</pubDate><guid>https://wi1dcard.dev/posts/laravel-route-pattern-exclude/</guid><description>Laravel 提供 where 方法和 Route::pattern 方法，用于设置某个路由参数必须匹配指定表达式，则此路由才会被匹配。
那么，如何设置排除某个「关键词」（或者我们称它为「特殊参数值」），只有这个关键词不匹配，其它都匹配呢？
举个例子 Route::domain(&amp;#39;{user}.example.com&amp;#39;); Route::pattern(&amp;#39;user&amp;#39;, &amp;#39;???&amp;#39;); ??? 处代表二级域，通常不可以设置为一些敏感保留词，比如 www / admin 等。
解决方案 实际上，Laravel 的路由参数匹配，使用的正是正则表达式。所以，这就好办了。</description></item><item><title>Laravel 5.6 使用 MongoDB 存储框架日志</title><link>https://wi1dcard.dev/posts/laravel-logging-with-mongodb/</link><pubDate>Wed, 15 Aug 2018 12:36:19 +0000</pubDate><guid>https://wi1dcard.dev/posts/laravel-logging-with-mongodb/</guid><description>网上的文章普遍是 Laravel 5.5 版本，而日志系统在 5.6 版本升级时进行了部分改动，原有方法基本都失效了。本文根据 Laravel 5.6 文档的指引，实现使用 MongoDB 存储框架日志。
0x00 准备 MongoDB Engine 首先，安装 MongoDB，参见 官方文档。
MongoDB Driver（PHP Extension） 其次，安装 PHP mongodb 扩展，参见 官方文档。</description></item><item><title>PHP 快速扫描列表创建无限极分类树</title><link>https://wi1dcard.dev/posts/php-fastest-create-tree-from-list/</link><pubDate>Mon, 06 Aug 2018 11:40:06 +0000</pubDate><guid>https://wi1dcard.dev/posts/php-fastest-create-tree-from-list/</guid><description>书接上回。上文结尾，讲解了引用的妙用。刚好，在我现在所处公司的业务里有一处用递归实现的「省市区」分级列表；本文将这一用途搬进生产环境，通过优化此省市区列表，试试真正的效果如何。
废话不多说，上代码。
省市区列表结构 array( 1 =&amp;gt; array( &amp;#39;id&amp;#39; =&amp;gt; 1, &amp;#39;name&amp;#39; =&amp;gt; &amp;#39;中华人民共和国&amp;#39;, &amp;#39;parent_id&amp;#39; =&amp;gt; 0, &amp;#39;level&amp;#39; =&amp;gt; &amp;#39;country&amp;#39;, ), 2 =&amp;gt; array( &amp;#39;id&amp;#39; =&amp;gt; 2, &amp;#39;name&amp;#39; =&amp;gt; &amp;#39;北京市&amp;#39;, &amp;#39;parent_id&amp;#39; =&amp;gt; 1, &amp;#39;level&amp;#39; =&amp;gt; &amp;#39;province&amp;#39;, ), 20 =&amp;gt; array( &amp;#39;id&amp;#39; =&amp;gt; 20, &amp;#39;name&amp;#39; =&amp;gt; &amp;#39;天津市&amp;#39;, &amp;#39;parent_id&amp;#39; =&amp;gt; 1, &amp;#39;level&amp;#39; =&amp;gt; &amp;#39;province&amp;#39;, ), 38 =&amp;gt; array( &amp;#39;id&amp;#39; =&amp;gt; 38, &amp;#39;name&amp;#39; =&amp;gt; &amp;#39;河北省&amp;#39;, &amp;#39;parent_id&amp;#39; =&amp;gt; 1, &amp;#39;level&amp;#39; =&amp;gt; &amp;#39;province&amp;#39;, ), 218 =&amp;gt; array( &amp;#39;id&amp;#39; =&amp;gt; 218, &amp;#39;name&amp;#39; =&amp;gt; &amp;#39;山西省&amp;#39;, &amp;#39;parent_id&amp;#39; =&amp;gt; 1, &amp;#39;level&amp;#39; =&amp;gt; &amp;#39;province&amp;#39;, ), 349 =&amp;gt; array( &amp;#39;id&amp;#39; =&amp;gt; 349, &amp;#39;name&amp;#39; =&amp;gt; &amp;#39;内蒙古自治区&amp;#39;, &amp;#39;parent_id&amp;#39; =&amp;gt; 1, &amp;#39;level&amp;#39; =&amp;gt; &amp;#39;province&amp;#39;, ), 465 =&amp;gt; array( &amp;#39;id&amp;#39; =&amp;gt; 465, &amp;#39;name&amp;#39; =&amp;gt; &amp;#39;辽宁省&amp;#39;, &amp;#39;parent_id&amp;#39; =&amp;gt; 1, &amp;#39;level&amp;#39; =&amp;gt; &amp;#39;province&amp;#39;, ), .</description></item><item><title>PHP 引用详解 - 踩坑与妙用</title><link>https://wi1dcard.dev/posts/php-reference-variable/</link><pubDate>Mon, 06 Aug 2018 10:33:41 +0000</pubDate><guid>https://wi1dcard.dev/posts/php-reference-variable/</guid><description>最近在关注「PHP 引用」这一话题，看过不少深度文章，对 PHP 里的「引用」有了更深的理解。
0x00 首先看如下代码：
$foo[&amp;#39;hello&amp;#39;] = &amp;#39;0&amp;#39;; $bar = &amp;amp;$foo[&amp;#39;hello&amp;#39;]; // 引用！ $tipi = $foo; $tipi[&amp;#39;hello&amp;#39;] = &amp;#39;1&amp;#39;; print_r($foo); 问：输出 0 还是输出 1？答案是 1。</description></item><item><title>PHP 获取不带命名空间的类名</title><link>https://wi1dcard.dev/posts/php-class-name-without-namespace/</link><pubDate>Tue, 24 Jul 2018 00:24:40 +0000</pubDate><guid>https://wi1dcard.dev/posts/php-class-name-without-namespace/</guid><description>方法很多，列出几个，以供参考。
Laravel 源码里扒出来的 class_basename 辅助函数
basename(str_replace(&amp;#39;\\&amp;#39;, &amp;#39;/&amp;#39;, $class)); substr 实现
substr(strrchr($class, &amp;#34;\\&amp;#34;), 1); // or substr($class, strrpos($class, &amp;#39;\\&amp;#39;) + 1); explode 实现</description></item><item><title>Yii2 输出文件下载响应</title><link>https://wi1dcard.dev/posts/yii2-response-send-file/</link><pubDate>Sat, 14 Jul 2018 13:52:46 +0000</pubDate><guid>https://wi1dcard.dev/posts/yii2-response-send-file/</guid><description>最近为了尽可能优雅地实现产品需求，天天看 Yii 源码，感觉还是非常爽的。本文将要介绍如何使用 Yii 内置的方法，输出文件、流、字符串为下载响应。
通过查看 yii\web\Response 源码可知，其提供如下方法：
public function sendFile($filePath, $attachmentName = null, $options = []); public function sendContentAsFile($content, $attachmentName, $options = []); public function sendStreamAsFile($handle, $attachmentName, $options = []); 那么如何在控制器内调用此方法输出呢？</description></item><item><title>Yii2 在模块内映射 Controller 到其它控制器</title><link>https://wi1dcard.dev/posts/yii2-redirect-controller-in-module/</link><pubDate>Fri, 13 Jul 2018 15:56:08 +0000</pubDate><guid>https://wi1dcard.dev/posts/yii2-redirect-controller-in-module/</guid><description>上文讲解关于如何映射 Action，本文讲解如何映射 Controller。
0x00 实现 首先，在你的 Module 里，定义一个 $controllerRedirectMap 变量。
public $controllerRedirectMap = []; 重写 createControllerByID 方法。
public function createControllerByID($id) { if(isset($this-&amp;gt;controllerRedirectMap[$id])) { $id = $this-&amp;gt;controllerRedirectMap[$id]; } return parent::createControllerByID($id); } 0x01 用法 public $controllerRedirectMap = [ &amp;#39;foo&amp;#39; =&amp;gt; &amp;#39;bar&amp;#39; // 访问 `module/foo/index` 将会被重定向至 `module/bar/index` &amp;#39;foo/bar&amp;#39; =&amp;gt; &amp;#39;bar/foo&amp;#39; // 访问 `module/foo/bar/index` 将会被重定向至 `module/bar/foo/index` ]; 0x02 感想 一口气写三篇关于 Yii2 的博文，算是对自己近期项目中用到 Yii 以来的技巧小结吧。</description></item><item><title>Yii2 在控制器内映射 Action 到其它动作</title><link>https://wi1dcard.dev/posts/yii2-redirect-action-in-controller/</link><pubDate>Fri, 13 Jul 2018 12:02:50 +0000</pubDate><guid>https://wi1dcard.dev/posts/yii2-redirect-action-in-controller/</guid><description>本文讲解：如何把控制器内的任意一个 Action 映射到另一个 Action。
0x00 准备 Yii ^ 2.0.7 0x01 代码 首先定义一个 RedirectAction 类。
class RedirectAction { protected $actionId; public function __construct($actionId) { $this-&amp;gt;actionId = $actionId; } public function __invoke($id, \yii\base\Controller $controller) { return $controller-&amp;gt;createAction($this-&amp;gt;actionId); } } 接着在控制器内重写实现 actions() 方法，用于映射 Action ID =&amp;gt; 实际的动作。</description></item><item><title>Yii2 允许控制器内直接返回数组</title><link>https://wi1dcard.dev/posts/yii2-return-array-in-controller/</link><pubDate>Fri, 13 Jul 2018 12:01:36 +0000</pubDate><guid>https://wi1dcard.dev/posts/yii2-return-array-in-controller/</guid><description>类似 Laravel 的效果：直接 return 数组输出 JSON 响应。办法有很多，目前我找到的最优解决方案如下。
/** * Enable JSON response if app returns Array or Object * * @return void */ protected function enableJsonResponse() { $this-&amp;gt;response-&amp;gt;on(\yii\web\Response::EVENT_BEFORE_SEND, function ($event) { /** @var \yii\web\Response $response */ $response = $event-&amp;gt;sender; if (is_array($response-&amp;gt;data) || is_object($response-&amp;gt;data)) { $response-&amp;gt;format = \yii\web\Response::FORMAT_JSON; } } ); } 或者在配置内定义也可以：</description></item><item><title>PHP 批量替换字符串</title><link>https://wi1dcard.dev/posts/php-str-replace-in-associative-array/</link><pubDate>Wed, 11 Jul 2018 15:14:36 +0000</pubDate><guid>https://wi1dcard.dev/posts/php-str-replace-in-associative-array/</guid><description>PHPer 们应该都知道 str_replace 函数，而如何使用数组批量替换某字符串内的子串，这里有个骚操作。
话不多说，直接上代码：
$map = [ &amp;#39;foo&amp;#39; =&amp;gt; &amp;#39;bar&amp;#39;, // ... ]; $str = str_replace(array_keys($map), array_values($map), $str);</description></item><item><title>PHP 使用 array_map 替代 foreach</title><link>https://wi1dcard.dev/posts/php-array-map-instead-of-foreach/</link><pubDate>Wed, 11 Jul 2018 14:44:18 +0000</pubDate><guid>https://wi1dcard.dev/posts/php-array-map-instead-of-foreach/</guid><description>讲个 PHP 的骚操作。论如何实现：把二维数组内某二维元素的值，单独提出来组成一维数组。
0x00 传统操作 $pieces = []; foreach($whole as $item) { $pieces[] = $item[&amp;#39;foo&amp;#39;]; } return $pieces; 0x01 骚操作 return array_map( function ($item) { return $item[&amp;#39;foo&amp;#39;]; }, $whole ); 省掉两个变量（$pieces、$item），对于业务逻辑比较复杂的位置，省一个变量说不定就少死十个脑细胞&amp;hellip;</description></item><item><title>PHPCPD - 检查复制粘贴的 PHP 代码</title><link>https://wi1dcard.dev/posts/php-copy-paste-detector/</link><pubDate>Wed, 04 Jul 2018 11:12:14 +0000</pubDate><guid>https://wi1dcard.dev/posts/php-copy-paste-detector/</guid><description>最近突然对代码质量检查感兴趣，决定对公司项目的代码冗余进行彻查。经过搜索发现一款不错的工具，针对复制粘贴的代码有不错的识别率，在此推荐。
0x00 准备 项目地址：https://github.com/sebastianbergmann/phpcpd
0x01 安装 直接下载代码包 wget https://phar.phpunit.de/phpcpd.phar chmod +x phpcpd.phar 或使用 Composer 全局安装 composer global require sebastian/phpcpd 0x02 使用 使用方法非常简单，只要带上代码文件夹路径即可。</description></item><item><title>PHP intval() 与 (int) 转换的区别</title><link>https://wi1dcard.dev/posts/php-intval-vs-int-casting/</link><pubDate>Mon, 18 Jun 2018 20:43:46 +0000</pubDate><guid>https://wi1dcard.dev/posts/php-intval-vs-int-casting/</guid><description>说到字符串转整型，PHP 里常用的两个方法相信各位都有了解，但其中微小的区别缺鲜为人知。本文简单梳理，以备日后查阅。
功能 对于十进制的转换，两种方式的功能是完全一致的：
$int = intval($str); // 等价于 $int = (int) $str; 而 intval() 具备一个可选参数 $base 默认值为 10，用于转换不同来自进制的数据：
$int = intval(&amp;#39;0123&amp;#39;, 8); // == 83 由这个参数，又引起另一条需要注意的点，先看例子：</description></item><item><title>AMH 面板重复加载 MySQL 扩展</title><link>https://wi1dcard.dev/posts/amh-loaded-mysql-module-twice/</link><pubDate>Thu, 14 Jun 2018 14:38:42 +0000</pubDate><guid>https://wi1dcard.dev/posts/amh-loaded-mysql-module-twice/</guid><description>真是天下没有不坑的面板&amp;hellip; 相继宝塔和 WDCP 之后，AMH 也出了问题。
0x00 表象 报错如下：
PHP Warning: Module 'mysql' already loaded in Unknown on line 0
logs/amh-php-errors.log 文件内也有偶尔出现的记录。</description></item><item><title>宝塔面板 PHP 打开文件失败原因排查</title><link>https://wi1dcard.dev/posts/baota-open-basedir-restriction/</link><pubDate>Wed, 13 Jun 2018 10:18:52 +0000</pubDate><guid>https://wi1dcard.dev/posts/baota-open-basedir-restriction/</guid><description>近期在使用宝塔面板部署 PHP 项目时，上传文件的场景，PHP 无法对临时文件进行打开操作，无法计算sha1、md5，遂进行排查。
0x00 报错 sha1_file(): open_basedir restriction in effect. File(/www/wwwroot/tmp/***) is not within the allowed path(s): (***)
0x01 原因 新版宝塔面板创建站点时默认添加 .</description></item><item><title>PHP 相对路径转绝对路径</title><link>https://wi1dcard.dev/posts/php-true-realpath/</link><pubDate>Fri, 08 Jun 2018 14:11:22 +0000</pubDate><guid>https://wi1dcard.dev/posts/php-true-realpath/</guid><description>PHP has a very handy function to convert relative pathnames to absolute paths: realpath(). However, it’s limited in at least two aspects which both make it inconvenient (and sometimes impossible) to use:</description></item><item><title>json_encode() 序列化非公开属性</title><link>https://wi1dcard.dev/posts/json-encode-non-public-properties/</link><pubDate>Fri, 08 Jun 2018 10:56:00 +0000</pubDate><guid>https://wi1dcard.dev/posts/json-encode-non-public-properties/</guid><description>近期项目过程中，有一处场景需要使用 json_encode 方法序列化某对象内的 protected 属性。
0x00 实现 谈到 json_encode 自然想到 &amp;lt;code&amp;gt;JsonSerializable&amp;lt;/code&amp;gt; 接口，此接口提供一个抽象方法：
abstract public mixed JsonSerializable::jsonSerialize ( void ) 于是我们可以这样实现：</description></item><item><title>PHP 实现类似 C# MakeRelativeUri 方法</title><link>https://wi1dcard.dev/posts/php-getting-releative-path/</link><pubDate>Mon, 04 Jun 2018 10:32:08 +0000</pubDate><guid>https://wi1dcard.dev/posts/php-getting-releative-path/</guid><description>在使用 C# 的过程中，几乎可以全程只靠 MSDN，很多方法微软在 .NET 内封装了很规范的实现；而近期在使用 PHP 开发项目时遇到个小问题：获取文件或目录 A 相对与 B 的路径，翻了下 PHP Manual 发现 PHP 内核并没有提供官方实现，于是谷歌之，找到一份比较规范的实现，在此记录，以备查询。
0x00 原文 https://stackoverflow.com/questions/2637945/getting-relative-path-from-absolute-path-in-php</description></item><item><title>phpize 简易入门</title><link>https://wi1dcard.dev/posts/get-started-with-phpize/</link><pubDate>Mon, 30 Apr 2018 22:31:53 +0000</pubDate><guid>https://wi1dcard.dev/posts/get-started-with-phpize/</guid><description>本文以安装 mongodb 扩展为例，简单讲解使用 phpize 给多版本 php 编译安装扩展。
0x00 准备 假设你的服务器有多个版本 php，你首先要找到对应版本 php 的 phpize、php-config 程序。通常它们与 php 所处目录相同。
接下来下载你的扩展源码包，多数扩展源码都能在 github 或 pecl 下载到。</description></item><item><title>PHPBrew - 多版本 PHP 共存开发神器</title><link>https://wi1dcard.dev/posts/phpbrew-documention/</link><pubDate>Sat, 17 Mar 2018 09:37:18 +0000</pubDate><guid>https://wi1dcard.dev/posts/phpbrew-documention/</guid><description>phpbrew 是一个构建、安装多版本 PHP 到用户根目录的工具。
GitHub：https://github.com/phpbrew/phpbrew
phpbrew 能做什么？
配置选项简化为「Variants」，无需担心路径问题。 支持使用 PDO，mysql，sqlite，debug 等不同「Variants」编译 PHP。 针对不同版本，分别编译 apache php 模块，互不冲突。 无需 root 权限将 PHP 安装到用户根目录。 集成至 bash / zsh shell 等，易于切换版本。 支持自动特性检测。 易于安装、启用 PHP 扩展。 支持在系统环境下安装多个 PHP。 路径检测针对 HomeBrew 以及 MacPorts 进行了优化。 安装需求 在开始之前，请先查看：Requirement（英文）。 确保已安装依赖包的开发版本用于编译 PHP。</description></item><item><title>纠结！纯内网 Web 控制智能硬件的技术选型之路</title><link>https://wi1dcard.dev/posts/controlling-smart-device-on-web/</link><pubDate>Sun, 11 Mar 2018 12:22:48 +0000</pubDate><guid>https://wi1dcard.dev/posts/controlling-smart-device-on-web/</guid><description>通常情况下，我们采用 TCP Socket 与智能硬件进行通信。外网环境中，有无数种解决方案：Swoole（PHP），Node.js，SuperSocket（.NET）…… 而在政企事业单位的内网环境，事情或许就不那么好办了。
0x01 目的 接收来自硬件的数据，并在 Web 端展示。 通过 Web 端操作，将指令下发至硬件。 0x02 限制 浏览器需要支持 IE 等老版本浏览器。 服务端需要支持 Windows Server 虚拟机（最低版本 2008）。 纯内网环境，无法访问外网源，无法使用各类包管理器（其实可以自己搭建内网源，但过于复杂，人力成本太高）。 0x03 思路 目前公司 Web 后端语言均为 PHP，所以以下思路全部围绕 PHP 开展。</description></item><item><title>Thumb - 自带缓存配置的单文件 PHP 缩略图库</title><link>https://wi1dcard.dev/posts/php-thumb/</link><pubDate>Fri, 09 Mar 2018 17:22:51 +0000</pubDate><guid>https://wi1dcard.dev/posts/php-thumb/</guid><description>PHP GD 扩展提供了图像处理的接口，本文为大家介绍一款非常小巧易用的缩略图库，支持多种缩放方式、多种输出格式、自带缓存配置……
0x00 源码 首先当然是放源码：
wi1dcard/Thumb
原作者代码因为多年没有维护，我进行了大量调整和优化，暂时就不合并了。
0x01 使用 使用方法非常简单，将thumb.php复制到 Web 服务器目录下，打开此文件。文件头部提供一些可供修改的参数，包括缓存目录等。
我们在此目录下创建cache文件夹，并确保 PHP 拥有rw权限。
接下来，随便找一张图片放在此目录下，接着使用 Postman 访问：</description></item><item><title>由浅入深：Laravel Broadcast 实现 WebSocket B/S 实时通信</title><link>https://wi1dcard.dev/posts/laravel-broadcasting/</link><pubDate>Fri, 02 Mar 2018 20:37:32 +0000</pubDate><guid>https://wi1dcard.dev/posts/laravel-broadcasting/</guid><description>Laravel 集成众多开包即用的功能, 虽然它真的很&amp;quot;胖&amp;quot;, 但这并不影响它是个好框架. 本篇文章将采用 Laravel 5.6 版本由浅入深为大家演示: 如何使用内置的 Broadcast（广播）功能实现与客户端实时通信.
Tips: 此仓库实现本文中的 0x02 广播 代码。
0x00 准备 广播系统 - Laravel 5.</description></item><item><title>Nginx+PHP 环境 499 错误码排查过程小记</title><link>https://wi1dcard.dev/posts/nginx-php-http-status-499/</link><pubDate>Fri, 02 Feb 2018 18:09:48 +0000</pubDate><guid>https://wi1dcard.dev/posts/nginx-php-http-status-499/</guid><description>前言 某公安项目过程中，在内网服务器部署 WNMP 环境，运行 Laravel 框架代码，后查看日志发现某一时刻突然所有请求 499，并持续一段时间，遂排查原因。
过程 0x01 经搜索得知： 哪些情况下会使 Nginx 返回 HTTP CODE 499？
即：「客户端主动关闭连接」
但某一时间段内全部请求均为返回 499，这显然不是所有客户端主动意识上的「关闭」，可能是因为客户端等待超时，自动关闭连接；加上 499 的时间段内包含部分 502，让我不得不怀疑：</description></item><item><title>Why PHP？浅谈选择 PHP 作为后端主力开发语言的原因</title><link>https://wi1dcard.dev/posts/why-php-in-2017/</link><pubDate>Thu, 18 Jan 2018 13:14:59 +0000</pubDate><guid>https://wi1dcard.dev/posts/why-php-in-2017/</guid><description>在各类交流群，甚至多数老一辈程序员的眼里，认为 PHP 是「轻量的」、「不完善的」、「性能难以优化」的，而这么多年来一直坚挺的 Java 却成了开发「XX 系统」的后端首选语言。为此，本篇文章将尽量从非技术角度告诉大家：Why PHP？
现状 其实，从 Java 和 PHP 的历史不难看出。在 Java 开始盛行的年代，PHP 还是个“毛头小子”，只是个普普通通的脚本语言罢了，甚至连面向对象的基本概念——类，都没有支持。
鉴于 PHP 历代升级以来坚守的向下兼容性，至今还可以看到不少用「当年的」原生函数写出来的产品代码可以运行，透过命名规则我们也可以看出当年的 PHP，好像的确「不够完善」。</description></item><item><title>Laravel 5.5 连接 MS SQL（SQL Server）数据库</title><link>https://wi1dcard.dev/posts/laravel-work-with-sql-server/</link><pubDate>Thu, 02 Nov 2017 10:49:20 +0000</pubDate><guid>https://wi1dcard.dev/posts/laravel-work-with-sql-server/</guid><description>因项目需要，要使用 Laravel 连接微软的 SQL Server，虽然这种组合显得非常奇葩，但经过测试还是可以成功实现的。
准备 首先，因为 Laravel 连接数据库默认是使用 PDO 扩展，而 PDO 连接 SQL Server 需要使用 pdo_dblib 扩展，所以首先第一步就是安装此扩展。
MAC 系统 直接使用 brew 命令安装即可。</description></item><item><title>UCenter 1.6 Client Example 对 PHP7 兼容不良的排查与修复</title><link>https://wi1dcard.dev/posts/php7-ucenter-client-example-issue/</link><pubDate>Fri, 27 Oct 2017 00:24:36 +0000</pubDate><guid>https://wi1dcard.dev/posts/php7-ucenter-client-example-issue/</guid><description>没错又踩坑了。
因项目需要与 DZ 论坛实现 SSO 登录、账号同步等功能，经老司机波波推荐，直接使用 DZ 官方产品 UCenter 集成即可；于是陈晟&amp;amp;潘昭宇折腾了一天 UCenter，可还是遇到了过不去的“拦路虎”，于是接近下班之际，决定接手这个问题，不知不觉踏上了过节依旧加班的不归路。
UCenter UCenter 是原 DZ 团队（现已被腾讯收购）开发的一套统一认证系统（顾名思义：User Center），具体介绍参见：百度百科。这套产品已经非常有年头，以现在的眼光再来审视当时的架构确实存在不少问题，当然，这并不影响它具有历史价值。
先来说下 UCenter（下称UC）的大致架构吧，这是坑踩完之后总结出来的，为了不影响后续理解所以提前介绍。</description></item></channel></rss>