手动修改 Laravel url() 函数生成的 URL 中的根地址

大家都晓得 Larevel 的一票帮助函数中有个 url(),可以通过给予的目录生成完整的 URL,是非常方便的一个函数:

// return: https://skin.dev/user/profile
url('user/profile')

但是这玩意生成的 URL 中要补完的部分是框架内部根据 Request 自动判断的,而自动判断出的东西有时候会出错(譬如在套了一层反向代理之类的情况下)。

文档上并没有提到我们要如何才能自定义它生成的 URL 中的根地址和协议头部分(http(s)),这就非常吃瘪了。那我们要咋办呢?

阅读全文→

Artisan::call('migrate') 在 APP_ENV 为 production 时不工作的解决方法

最近把版本库里 .env.exampleAPP_ENV 字段值从原来的 local 改为了 production,原意是为了更好的区分开发和生产环境。

然而今天在主机壳的虚拟主机上测试我的程序的时候(准备把演示站搬过去),却出现了奇怪的问题——数据库 Migration 不管用了。

我是在控制器里通过调用 Artisan::call('migrate') 来执行数据库迁移操作的(毕竟虚拟主机哪来的 shell 访问),但是这次这条命令竟然没有执行任何事务。

通过 Artisan 执行 Command 的简化流程大概是像这样的:

Illuminate\Foundation\Console\Kernel
↓
Illuminate\Console\Application
↓
Illuminate\Console\Command
↓
Illuminate\Container\Container
↓
// 这个就是执行 Artisan::call('migrate') 时调用的类
Illuminate\Database\Console\Migrations\MigrateCommand
↓
……

经过一段时间的排查,最后锁定了是在 MigrateCommand 这个类停止继续往下执行的,即接下来的脚本都没有被执行到,也就是说问题就出在 MigrateCommand 这里。

阅读全文→

使用 Certbot 更新 Let's Encrypt 证书

Let’s Encrypt 证书即将过期时会给你发送邮件,这个还是比较贴心的。这样也就不会陷入证书过期却没发现的尴尬境地(Let’s Encrypt 的证书只有 90 天的有效期)。

2826714bc9645e4b9828433b8e674800.png

以前我写过使用 Certbot 这个工具申请证书的文章,而同样使用这个工具更新证书只需要一行命令:

certbot renew --post-hook "service nginx reload"

certbot 这个脚本的位置呀名称啥的自己看着改,对于我来说是 ./certbot-auto。加了个钩子可以让它在证书更新更新完毕后重载 Nginx 配置来更新证书。

阅读全文→

PHP 远程文件下载的进度条实现

PHP 实现远程下载文件到服务端并不是什么新鲜玩意,用 cURLfile_get_contentsfopen 等都能够轻易实现。

但是这几种常规的方法都是在一个线程内下载文件,等文件下载完毕以后才能返回 HTTP 响应。所造成的结果就是用户在页面上点击「下载到服务器」按钮后,会看到空白页和加载的小菊花转啊转,转好久之后才出现「下载成功」的页面。

当然,我上面所举例的情况是只使用纯粹的表单 POST 发送请求的情况。现在的话就算再不济也一般会使用 ajax 发送请求,然后在前台放个加载动画,等收到下载成功的回应之后再进行下一步操作。

但是!即使是去掉了恶心的且需要等待的空白页,这样做还是对用户体验有不好的影响。没有具体的下载进度,只有一个一直转呀转的菊花图,估计挺多用户都无法坐和放宽吧(至少对于我来说是这样的)

而我一个 PHP 项目的一键更新系统正好需要重构,遂研究了如何在 PHP 作为后端时显示远程文件下载进度条,并捣鼓出了个像样的解决方案,在这里分享一下。

阅读全文→

耳机插头修理技巧

群里大佬 pan爷低价出了我一个耳机插头附近断线的 ATH-ES55,这已经是挺久以前的事了。当时我去某宝上买了个耳机插头,刮掉耳机线的漆包草草焊上去就完事了(好歹是挺不错的耳机你就这样对待啊喂)。然而最近耳机插头接触不良了,我就寻思着重新焊下,在这里记录一下需要注意的地方。

虽然修耳机这种事我在小学的时候就鼓捣过了,但总归当时还是不专业,也没啥像样的工具。而且最近听的好歹也算是 HiFi 耳机,不能再用之前那种乡巴佬方法了(笑)。在网上搜了一些,学到了不少,在此记录一下。

下面几乎都是盗图,侵删w

3.5mm 耳机插头接线图

耳机插头示意

阅读全文→

Laravel 框架下的插件机制实现(一)—— 构建插件系统

插件,即 Plug-in(又有外挂、Extension、Addon 等叫法),是一类特定的功能模块,通过和应用程序的互动,用来替应用程序增加一些所需要的特定的功能。插件的特点是:

  • 当你需要它的时候激活它,不需要它的时候禁用/删除它;
  • 无论是激活还是禁用都不影响系统核心模块的运行。

也就是说插件是一种非侵入式的模块化设计,实现了核心程序与插件程序的松散耦合。上面的介绍部分摘自 中文 WikiPedia

虽然现在网上有很多 PHP 的插件机制的实现(当然我指的是英文内容,中文关于 PHP 插件机制的搜出来现在还是那么点破文章),譬如 FoolCode/Plugin,或者 WordPress 的插件实现。

不过我今天想介绍的是如何使用 Laravel 的服务容器、事件机制等功能来实现一个比较优雅的插件机制。

Greatly inspired by Flarum,在此致谢 ヾ(´ω゚`)

阅读全文→

实现点击按钮加载 Gist 代码块

GitHub Gist 应该也是很多人都在用的功能了,我也喜欢把一些大段的代码块贴上去而不是直接写在博文里。

但是 Gist 的 embed js 是在页面加载的时候就直接开始加载了的,所以或多或少还是对网页的性能有所影响。受上次搞的「点击加载 Disqus」启发,我也准备写一个点击加载 Gist。

最开始我尝试了传统方法,即动态创建一个 <script> 标签并添加到文档流中。然而却得到了一个这个错误:

Failed to execute 'write' on 'Do

          ...
          阅读全文→
        
      

使用 ADB Shell 刷入 Recovery

众所周知 MTK(联发科)的大部分机器都是没有 fastboot 模式的,也就意味着不能进行普通的依赖于 fastboot 系列命令的线刷模式。普通来讲这也没啥特别大的影响,毕竟刷 recovery 可以直接系统里拿到 root 后用工具刷,救砖有 MTK 专用的线刷工具(这玩意的驱动坑的不行)

但是,在一些神秘的状况下,我有可能会被没有 fastboot 的情况下坑到。

这次我想刷的是「朵唯 iSuper S1」,用的是 MTK6589 芯片组。按照惯例刷机之前首先要把 Recovery 换掉以刷入第三方 ROM 包。照理来说这块是没有问题的,但是不知道为什么,市面上的 Root 工具能够让手机拿到 Root 权限,但是在手机上安装权限管理应用时均告失败,也是迷的不行。

明明 Root 权限都已经拿到了却刷不了 Rec,这也太吃瘪了吧!然而没有 MTK 机子也不能用 fastboot 刷 rec,专门的线刷工具又太难用。。就在这时,我突然想到了一个命令 —— dd

阅读全文→

使用 Nginx 反代并缓存动态内容

因为着实没想到一个皮肤站竟然会有这么大的并发(好吧其实也不大,QPS 大概 50 左右),所以我之前 开发/部署 Blessing Skin Server 的时候是完全没考虑到缓存优化的。直到后来出现了 神秘的高并发(QPS 上 200)导致皮肤站宕机我才意识到缓存的重要性。

我到现在也还是搞不懂那到底是正常流量还是 CC 攻击。。难道正常用户会每秒请求 20+ 次 Json Profile 吗?又不是天天退/进游戏玩 emotion

虽然当时我就花了一点时间给 Json Profile 和皮肤预览之类的地方 加上了缓存,但是由于这些缓存方案都是在 Laravel 层之上的,所以框架的性能依旧是硬伤。试了下 Stone
之类的优化措施也没什么卵效果,再加上我学业也忙了起来,这个问题就被搁置了。

正好最近国庆放假(虽然只有四天),我就抽了点时间出来研究了一下如何给我的皮肤站套一层缓存 ( ・_ゝ・)

阅读全文→